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

问题描述 投票:0回答:2

我正在学习编写嵌入式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()

感谢您的回复!

c linux-kernel linux-device-driver embedded-linux
2个回答
49
投票

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

所以你的代码在没有

request_mem_region
的情况下工作是完全合乎逻辑的,只是它不符合内核编码规则。

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


6
投票

在设备驱动程序中使用

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

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

查看bootlin公司培训课程的幻灯片293

© www.soinside.com 2019 - 2024. All rights reserved.