我正在开发运行
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; }
解决方法
这是因为ioremap_nocache()仍然启用VM映射中的cpu写缓冲区,而pgprot_noncached()禁用缓冲性和可缓存性.
苹果对苹果的比较将是使用ioremap_strongly_ordered()而不是.