request_mem_region()实际上做什么以及何时需要它?

时间:2011-10-07 02:09:54

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

我正在学习编写嵌入式Linux驱动程序,并决定启动一些GPIO以确保我正确理解了这本书(LDD3, chap9.4.1)

我能够按照预期控制正确的GPIO引脚(使其高低,我用万用表探测);但是,我测试了2个代码,一个代码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()

感谢您的回复!

2 个答案:

答案 0 :(得分:37)

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

因此,没有request_mem_region的代码工作是完全合乎逻辑的,只是它不符合内核编码规则。

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

答案 1 :(得分:0)

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

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

https://bootlin.com/doc/training/linux-kernel/linux-kernel-slides.pdf幻灯片276