0

我可以在user spaceusingmmap系统调用中访问 i/o 端口/dev/mem

#define BCM2708_PERI_BASE       0x20000000
#define GPIO_PADS               (BCM2708_PERI_BASE + 0x100000)
#define CLOCK_BASE              (BCM2708_PERI_BASE + 0x101000)
#define GPIO_BASE               (BCM2708_PERI_BASE + 0x200000)
#define GPIO_PWM                (BCM2708_PERI_BASE + 0x20C000)


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdint.h>

static volatile uint32_t *gpio;

int main(int argc, char **argv)
{
        int fd ;

        //Obtain handle to physical memory
        if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
                printf("Unable to open /dev/mem: %s\n", strerror(errno));
                return -1;
        }


        //map a page of memory to gpio at offset 0x20200000 which is where GPIO goodnessstarts
        gpio = (uint32_t *)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x20200000);

        if ((int32_t)gpio < 0){
                printf("Mmap failed: %s\n", strerror(errno));
                return -1;
        }

        //set gpio17 as an output
        //increment the pointer to 0x20200004
        //set the value through a little bit twiddling where we only modify the bits 21-23 in the register
        *(gpio + 1) = (*(gpio + 1) & ~(7 << 21)) | (1 << 21);

        //toggle gpio17 every second
        while(1){
                //set the pin high
                //increment the pointer to 0x2020001C
                *(gpio + 7) = 1 << 17;

                //sleep
                sleep(1);

                //set the pin to low
                //increment the pointer to 0x20200028
                *(gpio + 10) = 1 << 17;

                sleep(1);
        }
}

Map 只能在用户空间工作。kernel space 现在我如何在设备驱动程序中访问相同的 i/o 端口?

4

1 回答 1

3

例如:GPIO 模块的每个模块都有自己的内存映射,即处理器技术参考手册中指定的物理地址。首先,您需要检查内存区域是否正在使用或未使用check_mem_region。如果是空闲请求访问这个内存区域,则使用or映射request_mem_regionGPIO 模块(将总线内存映射到 CPU 空间),返回一个 void 指针。返回的地址不保证可以直接作为虚拟地址使用;它只能由等函数使用。使用函数从/向 i/o 端口读取或写入。最后,您需要取消映射内存,然后您需要使用. 通常在内核空间,大部分时间ioremapioremap_nocacheioread*|iowrite*|read*|write*ioread8|16|32/iowrite8|16|32iounmaprelease_mem_region无需检查和请求内存区域。您只需使用ioremapor将总线内存映射到 CPU 空间,ioremap_nocache然后使用取消映射iounmap

于 2013-06-07T11:58:20.837 回答