Note that there are some explanatory texts on larger screens.

plurals
  1. POmmap slower than ioremap
    primarykey
    data
    text
    <p>I am developing for an ARM device running Linux 2.6.37. I am trying to toggle an IO pin as fast as possible. I made a little kernel module and a user space application. I tried two things :</p> <ol> <li>Manipulate the GPIO control registers directly from the kernel space using <code>ioremap</code>.</li> <li><code>mmap()</code> the GPIO control registers without caching and using them from user space.</li> </ol> <p>Both methods work, but the second is about 3 times slower than the first (observed on oscilloscope). I think I disabled all caching mechanisms. </p> <p>Of course I'd like to get the best of the two worlds : flexibility and ease of development from user space with the speed of kernel space. </p> <p>Does anybody know why the <code>mmap()</code> could be slower than the <code>ioremap()</code> ?</p> <p>Here's my code :</p> <h3>Kernel module code</h3> <pre class="lang-c prettyprint-override"><code>static int ti81xx_usmap_mmap(struct file* pFile, struct vm_area_struct* pVma) { pVma-&gt;vm_flags |= VM_RESERVED; pVma-&gt;vm_page_prot = pgprot_noncached(pVma-&gt;vm_page_prot); if (io_remap_pfn_range(pVma, pVma-&gt;vm_start, pVma-&gt;vm_pgoff, pVma-&gt;vm_end - pVma-&gt;vm_start, pVma-&gt;vm_page_prot)) return -EAGAIN; pVma-&gt;vm_ops = &amp;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 &lt;&lt; 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 &gt;&gt; 2] &amp;= ~pin; /* Set pin as output*/ for (i = 0; i &lt; 200000000; ++i) { pGpIoRegisters[OMAP4_GPIO_SETDATAOUT &gt;&gt; 2] = pin; pGpIoRegisters[OMAP4_GPIO_CLEARDATAOUT &gt;&gt; 2] = pin; } pGpIoRegisters[OMAP4_GPIO_OE &gt;&gt; 2] |= pin; /* Set pin as input*/ iounmap(pGpIoRegisters); } </code></pre> <h3>User space application code</h3> <pre class="lang-c prettyprint-override"><code>int main(int argc, char** argv) { int file, i; ulong* pGpIoRegisters = NULL; ulong pin = 1 &lt;&lt; 24; file = open("/dev/ti81xx-usmap", O_RDWR | O_SYNC); if (file &lt; 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 &gt;&gt; 2] &amp;= ~pin; for (i = 0; i &lt; 30000000; ++i) { pGpIoRegisters[OMAP4_GPIO_SETDATAOUT &gt;&gt; 2] = pin; pGpIoRegisters[OMAP4_GPIO_CLEARDATAOUT &gt;&gt; 2] = pin; } pGpIoRegisters[OMAP4_GPIO_OE &gt;&gt; 2] |= pin; printf(" done\n"); fflush(stdout); munmap(pGpIoRegisters, 0x400); close(file); return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload