首页 文章

mmap比ioremap慢

提问于
浏览
12

我正在开发运行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;
}

2 回答

  • 7

    这是因为ioremap_nocache()仍然在VM映射中启用CPU写入缓冲区,而pgprot_noncached()禁用了可缓冲性和可缓存性 .

    苹果与苹果的比较将是使用ioremap_strongly_ordered()代替 .

  • 3

    我的猜测是,因为 mmap 必须检查以确保你允许写入,所以's going to be slower than the kernel version (which I believe/assume doesn't做那种检查 - 使用内核模块你're responsible for testing until you'非常确定你没有破坏东西) .

    尝试使用 do_mmap (我相信是那个)从内核空间使用 mmap ,看看它是如何比较的 . 如果它's comparably faster, then I'我是对的 . 如果它's not, it'是别的 .

相关问题