问题描述
我正在研究编写嵌入式 linux 驱动程序,并决定触发一些 GPIO 以确保我理解这本书 (LDD3, chap9.4.1) 正确.
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.
我能够按预期控制正确的 GPIO 引脚(使其高低,我用万用表探测);但是,我测试了两段代码,一段带有 request_mem_region()
,另一段没有.我期待没有的会失败,但两者都工作得很好.
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.
带有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
",
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
",
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
.
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
.
我的问题是为什么需要 request_mem_region()
因为我仍然可以仅使用 ioremap()
与硬件地址通信?那么我们什么时候真正需要使用request_mem_region()
?
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()
?
感谢您的回复!
推荐答案
request_mem_region
告诉内核你的驱动程序将使用这个范围的 I/O 地址,这将阻止其他驱动程序通过 request_mem_region
对同一区域的任何重叠调用.这种机制不做任何类型的映射,它是一种纯粹的保留机制,它依赖于所有内核设备驱动程序都必须良好的事实,并且它们必须调用request_mem_region
,检查返回值,并表现以防万一.
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 through request_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 call request_mem_region
, check the return value, and behave properly in case of error.
所以你的代码在没有request_mem_region
的情况下工作是完全合乎逻辑的,只是它不符合内核编码规则.
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.
但是,您的代码不符合内核编码风格.此外,还有一个现有的基础架构来处理 GPIO,名为 gpiolib,您应该使用它而不是手动重新映射您的 GPIO 组寄存器.您在哪个平台上工作?
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() 实际做什么以及何时需要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!