【发布时间】:2012-06-11 08:09:56
【问题描述】:
我正在为运行 Linux 2.6.37 的 ARM 设备进行开发。我正在尝试尽快切换 IO 引脚。我做了一个小内核模块和一个用户空间应用程序。我尝试了两件事:
- 使用
ioremap直接从内核空间操作GPIO控制寄存器。 -
mmap()GPIO 控制寄存器,无需从用户空间缓存和使用它们。
两种方法都有效,但第二种方法比第一种方法慢约 3 倍(在示波器上观察)。我想我禁用了所有缓存机制。
当然,我希望获得两全其美:从用户空间开发的灵活性和易用性以及内核空间的速度。
有人知道为什么mmap() 会比ioremap() 慢吗?
这是我的代码:
内核模块代码
static int ti81xx_usmap_mmap(struct file* pFile, struct vm_area_struct* pVma)
{
pVma->vm_flags |= VM_RESERVED;
pVma->vm_page_prot = pgprot_noncached(pVma->vm_page_prot);
if (io_remap_pfn_range(pVma, pVma->vm_start, pVma->vm_pgoff,
pVma->vm_end - pVma->vm_start, pVma->vm_page_prot))
return -EAGAIN;
pVma->vm_ops = &ti81xx_usmap_vm_ops;
return 0;
}
static void ti81xx_usmap_test_gpio(void)
{
u32* pGpIoRegisters = ioremap_nocache(TI81XX_GPIO0_BASE, 0x400);
const u32 pin = 1 << 24;
int i;
/* I should use IO read/write functions instead of pointer deferencing,
* but portability isn't the issue here */
pGpIoRegisters[OMAP4_GPIO_OE >> 2] &= ~pin; /* Set pin as output*/
for (i = 0; i < 200000000; ++i)
{
pGpIoRegisters[OMAP4_GPIO_SETDATAOUT >> 2] = pin;
pGpIoRegisters[OMAP4_GPIO_CLEARDATAOUT >> 2] = pin;
}
pGpIoRegisters[OMAP4_GPIO_OE >> 2] |= pin; /* Set pin as input*/
iounmap(pGpIoRegisters);
}
用户空间应用代码
int main(int argc, char** argv)
{
int file, i;
ulong* pGpIoRegisters = NULL;
ulong pin = 1 << 24;
file = open("/dev/ti81xx-usmap", O_RDWR | O_SYNC);
if (file < 0)
{
printf("open failed (%d)\n", errno);
return 1;
}
printf("Toggle from kernel space...");
fflush(stdout);
ioctl(file, TI81XX_USMAP_IOCTL_TEST_GPIO);
printf(" done\n");
pGpIoRegisters = mmap(NULL, 0x400, PROT_READ | PROT_WRITE, MAP_SHARED, file, TI81XX_GPIO0_BASE);
printf("Toggle from user space...");
fflush(stdout);
pGpIoRegisters[OMAP4_GPIO_OE >> 2] &= ~pin;
for (i = 0; i < 30000000; ++i)
{
pGpIoRegisters[OMAP4_GPIO_SETDATAOUT >> 2] = pin;
pGpIoRegisters[OMAP4_GPIO_CLEARDATAOUT >> 2] = pin;
}
pGpIoRegisters[OMAP4_GPIO_OE >> 2] |= pin;
printf(" done\n");
fflush(stdout);
munmap(pGpIoRegisters, 0x400);
close(file);
return 0;
}
【问题讨论】:
-
慢 3 倍是什么意思?个别振荡时间较长,还是整体执行?
-
两者,示波器上的振荡慢了 3 倍,处理器在“str”指令上花费了更多时间,但我不知道为什么。它是在等待一些硬件(总线传输?),还是像内核页面错误异常处理程序这样的软件?这是我的问题的核心......
-
请注意,在您的示例代码中,循环的迭代次数非常不同。
-
@ysap 以补偿一个比另一个更快(频率)的事实:-)。在内核空间中进行了 30000000 次迭代,我几乎没有时间在我的范围内测量某些东西。