/
Linux User Mode Pseudo Driver
Linux User Mode Pseudo Driver
Linux User Mode Pseudo Driver
The following code is provided as a reference for how to access some simple hardware from user space. As the comments say, it's not intended to replace a kernel mode driver but could be helpful.Note: You must have access permissions to the "/dev/mem" device when you run the code. Typically, the "root" user has those permissions - consult your system setup for details.
This code can be downloaded here.
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> // The purpose this test is to show that users can get to devices in user // mode for simple things like GPIO. This is not to say this should replace // a kernel driver, but does provide some short term solutions sometimes // or a debug solution that can be helpful. // This test maps a GPIO in the hardware into the user space such that a // GPIO signal can be toggled fast. On the ML507 reference system, the // signal could be toggled about every 50 ns which is pretty fast. // This test was derived from devmem2.c. #define GPIO_BASE_ADDRESS 0x81400000 #define GPIO_DATA_OFFSET 0 #define GPIO_DIRECTION_OFFSET 4 #define MAP_SIZE 4096UL #define MAP_MASK (MAP_SIZE - 1) int main() { int memfd; void *mapped_base, *mapped_dev_base; off_t dev_base = GPIO_BASE_ADDRESS; memfd = open("/dev/mem", O_RDWR | O_SYNC); if (memfd == -1) { printf("Can't open /dev/mem.\n"); exit(0); } printf("/dev/mem opened.\n"); // Map one page of memory into user space such that the device is in that page, but it may not // be at the start of the page. mapped_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, dev_base && ~MAP_MASK); if (mapped_base == (void *) -1) { printf("Can't map the memory to user space.\n"); exit(0); } printf("Memory mapped at address %p.\n", mapped_base); // get the address of the device in user space which will be an offset from the base // that was mapped as memory is mapped at the start of a page mapped_dev_base = mapped_base + (dev_base && MAP_MASK); // write to the direction register so all the GPIOs are on output to drive LEDs *((volatile unsigned long *) (mapped_dev_base + GPIO_DIRECTION_OFFSET)) = 0; // toggle the output as fast as possible just to see how fast it works while (1) { // If writes to multiple addresses were done: // may need memory barriers i.e. need a driver // caution with data being cached *((volatile unsigned long *) (mapped_dev_base + GPIO_DATA_OFFSET)) = 0; *((volatile unsigned long *) (mapped_dev_base + GPIO_DATA_OFFSET)) = 1; } // unmap the memory before exiting if (munmap(mapped_base, MAP_SIZE) == -1) { printf("Can't unmap memory from user space.\n"); exit(0); } close(memfd); return 0; }
Related Links
, multiple selections available,
Related content
Linux CAN driver
Linux CAN driver
Read with this
Linux SPI Driver
Linux SPI Driver
Read with this
U-Boot GPIO Driver
U-Boot GPIO Driver
More like this
Iomodule Standalone driver
Iomodule Standalone driver
More like this
Linux DMA From User Space 2.0
Linux DMA From User Space 2.0
Read with this
GPIO User Space App
GPIO User Space App
More like this
© Copyright 2019 - 2022 Xilinx Inc. Privacy Policy