您的位置:首页 > 运维架构 > Linux

Xilinx-Linux User Mode Pseudo Driver

2017-09-09 10:40 441 查看


Linux User Mode Pseudo Driver

 Edit 0 4

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.





usergpio.c
Details
Download

2 KB

#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

Linux Drivers
link: http://www.wiki.xilinx.com/Linux+User+Mode+Pseudo+Driver
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: