我正在使用Raspberry PI(Linux rpi 3.12.28+),我有以下可用于操作GPIO端口的C代码:
// IO Acces
struct bcm2835_peripheral {
unsigned long addr_p;
int mem_fd; // memory file descriptor
void *map;
volatile unsigned int *addr;
};
struct bcm2835_peripheral gpio = {0x40000000};
// Exposes the physical address defined in the passed structure using mmap on /dev/mem
int map_peripheral(struct bcm2835_peripheral *p)
{
// Open /dev/mem
if ((p->mem_fd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
return -1;
}
p->map = mmap(
NULL,
BLOCK_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
p->mem_fd, // File descriptor to physical memory virtual file '/dev/mem'
p->addr_p // Address in physical map that we want this memory block to expose
);
if (p->map == MAP_FAILED) {
return -1;
}
p->addr = (volatile unsigned int *)p->map;
return 0;
}
以上代码适用于普通程序(用户空间)。但是我需要创建一个能够做同样事情的Linux内核模块。问题是编译器不能识别open()或mmap()等方法。将此代码转换为内核模块(驱动程序)的适当方法是什么?这些函数是否可用于内核编程,还是应该以不同的方式执行?我见过像syscall_open(),filp_open(),sys_mmap2()这样的方法,但我很困惑。我将不胜感激。
答案 0 :(得分:1)
你没有在内核空间中进行系统调用(打开,关闭,读取,写入等),相反,你必须使用模块提供的内部接口,但似乎不是你的情况。
考虑到您正在访问/dev/mem
我想您正在尝试读取RaspberyPi的物理内存。从内核空间可以直接访问它,因为没有内存保护,但是,您必须使用phys_to_virt
函数来转换地址。
答案 1 :(得分:0)
确实无需访问内核模块中的/dev/mem
。使用phys_to_virt
直接访问内存是一种操作内存的解决方案,但如果目标是操作GPIO端口,它将无法在Raspberry PI上运行。
解决方案是访问硬件寄存器。我在这里找到了很好的教程: