request_mem_region() 实际上做了什么以及什么时候需要它?
我正在学习编写嵌入式 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
。
我的问题是,既然我仍然可以仅使用 ioremap()
与硬件地址通信,为什么需要 request_mem_region()
?那么我们什么时候真正需要使用 request_mem_region() 呢?
感谢您的回复!
I'm studying on writing embedded linux driver, and decided to fire a few GPIOs to make sure I understand the book (LDD3, chap9.4.1) correctly.
I am able to control the correct GPIO pins as intended (making it high and low, I probed with a multimeter); however, I tested 2 pieces of code, one with request_mem_region()
, and one without. I'm expecting the one without will fail, but both is working just fine.
Code with 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...
Code without 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...
The only difference I can observe from both cases is the result of doing a cat /proc/iomem
, the one with request_mem_region()
will display an additional line showing 49056000-49056097 : GPIO3
.
My question is why request_mem_region()
is needed since I can still communicate with the hardware address with only ioremap()
? So when do we actually need to use request_mem_region()
?
Thanks for any replies!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
request_mem_region
告诉内核您的驱动程序将使用此范围的 I/O 地址,这将防止其他驱动程序通过request_mem_region
对同一区域进行任何重叠调用。这个机制不做任何类型的映射,它是一个纯粹的预留机制,它依赖于这样一个事实:所有内核设备驱动程序都必须是好的,并且它们必须调用request_mem_region
,检查返回值,并表现出行为发生错误时正确处理。因此,您的代码在没有
request_mem_region
的情况下工作是完全合乎逻辑的,只是它不符合内核编码规则。但是,您的代码不符合内核编码风格。此外,还有一个用于处理 GPIO 的现有基础设施,名为 gpiolib,您应该使用它,而不是手动重新映射 GPIO 组寄存器。您在哪个平台上工作?
request_mem_region
tells the kernel that your driver is going to use this range of I/O addresses, which will prevent other drivers to make any overlapping call to the same region throughrequest_mem_region
. This mechanism does not do any kind of mapping, it's a pure reservation mechanism, which relies on the fact that all kernel device drivers must be nice, and they must callrequest_mem_region
, check the return value, and behave properly in case of error.So it is completely logical that your code works without
request_mem_region
, it's just that it doesn't comply with the kernel coding rules.However, your code doesn't comply with the kernel coding style. And additionnally, there is an existing infrastructure to handle GPIOs, named gpiolib, which you should use instead of manually remapping your GPIO bank registers. Which platform are you working on ?
在设备驱动程序中使用
request_mem_region()
和ioremap()
是现在已弃用。您应该使用以下“托管”功能
相反,它简化了驱动程序编码和错误处理:
查看 bootlin 公司培训课程的幻灯片 293。
Using
request_mem_region()
andioremap()
in device drivers isnow deprecated. You should use the below "managed" functions
instead, which simplify driver coding and error handling:
Look at slide 293 of bootlin company training course.