【问题标题】:What does request_mem_region() actually do and when it is needed?request_mem_region() 实际做什么以及何时需要?
【发布时间】:2011-10-07 02:09:54
【问题描述】:

我正在研究编写嵌入式 linux 驱动程序,并决定触发一些 GPIO 以确保我正确理解这本书 (LDD3, chap9.4.1)

我能够按预期控制正确的 GPIO 引脚(使其高低,我用万用表探测);但是,我测试了两段代码,一段带有request_mem_region(),另一段没有。我预计没有的会失败,但两者都工作得很好。

代码request_mem_region:

if( request_mem_region( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF,DEVICE_NAME ) == NULL )
  {
    printk( KERN_ALERT
            "GPIO_140_141_conf_phys error:%s: unable to obtain I/O memory address 0x%08llX\n",
            DEVICE_NAME, PIN3_CONF_PHYS );

    return -EBUSY;
  }

pin3_conf = (u32)ioremap( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin4_conf = (u32)ioremap( PIN4_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin5_conf = (u32)ioremap( PIN5_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin6_conf = (u32)ioremap( PIN6_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
//-----------------------------------------------------------------
if( request_mem_region( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5,DEVICE_NAME ) == NULL )
  {
    printk( KERN_ALERT
            "error:%s: unable to obtain I/O memory address 0x%08llX\n",
            DEVICE_NAME, GPIO_BANK5_PHYS );
 
    return -EBUSY;
  }
    
gpio_virt = (u32)ioremap( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5 );

//some iowrite32() functions continue...

没有request_mem_region()的代码:

pin3_conf = (u32)ioremap( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin4_conf = (u32)ioremap( PIN4_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin5_conf = (u32)ioremap( PIN5_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin6_conf = (u32)ioremap( PIN6_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
gpio_virt = (u32)ioremap( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5 );
//some iowrite32() functions continue...

我可以从这两种情况中观察到的唯一区别是执行cat /proc/iomem 的结果,带有request_mem_region() 的那个将显示一个显示49056000-49056097 : GPIO3 的附加行。

我的问题是为什么需要request_mem_region(),因为我仍然可以仅使用ioremap() 与硬件地址通信?那么我们什么时候真正需要使用request_mem_region()呢?

感谢您的回复!

【问题讨论】:

    标签: c linux-kernel linux-device-driver embedded-linux


    【解决方案1】:

    request_mem_region 告诉内核您的驱动程序将使用此 I/O 地址范围,这将防止其他驱动程序通过request_mem_region 对同一区域进行任何重叠调用。这个机制不做任何类型的映射,它是一个纯粹的保留机制,它依赖于所有内核设备驱动程序必须是nice的事实,它们必须调用request_mem_region,检查返回值,并在错误的情况下正常运行.

    所以你的代码在没有request_mem_region 的情况下工作是完全合乎逻辑的,只是它不符合内核编码规则。

    但是,您的代码不符合内核编码风格。此外,还有一个名为 gpiolib 的现有基础架构来处理 GPIO,您应该使用它而不是手动重新映射 GPIO 组寄存器。你在哪个平台上工作?

    【讨论】:

    • 感谢您的回复!这对我来说很清楚,我正在使用带有 Angstrom 的 beagleboard。我在beagleboard group 中发布了另一个问题,建议我也使用gpiolib。但是,我尝试了#include <linux/gpio.h>#include <asm/gpio.h>,但都失败了,我应该改用什么?
    • 另一个问题,当我使用make 编译内核模块或驱动程序时,它将在哪些目录中查找#include 的标头?例如,其中之一是/include,因此#include <linux/module.h>#include <linux/kernel.h> 将查看/include/linux/#include <asm/io.h> 将查看 /include/asm/
    • @Petazzoni 很抱歉发布第三条评论,我刚刚得知我可以通知回答我问题的人,并且我无法编辑以前的 cmets,所以我必须发布这个。
    【解决方案2】:

    在设备驱动程序中使用request_mem_region()ioremap() 是 现在已弃用。您应该使用以下“托管”功能 相反,它简化了驱动程序编码和错误处理:

    devm_ioremap()
    devm_iounmap()
    devm_ioremap_resource(), Takes care of both the request and remapping operations
    

    看看slide 289bootlin company 培训课程。

    【讨论】:

      猜你喜欢
      • 2013-09-11
      • 1970-01-01
      • 1970-01-01
      • 2018-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      相关资源
      最近更新 更多