mmapでのGPIO設定
mmapによるユーザランドからのGPIO制御。
デバイスドライバによる方法よりオーバヘッドが少ない。
/* gpioMmap.h */ // definition typedef enum{ E_GPFSEL_INPUT = 0, E_GPFSEL_OUTPUT = 1, E_GPFSEL_F0 = 4, E_GPFSEL_F1 = 5, E_GPFSEL_F2 = 6, E_GPFSEL_F3 = 7, E_GPFSEL_F4 = 3, E_GPFSEL_F5 = 2 } E_GPFSEL; // finction prototypes void gpio_open(void); void gpio_close(void); void set_gpio_function(int pin, E_GPFSEL function); void set_gpio(int pin, int level); int get_gpio(int pin);
// gpioMmap.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include "gpioMmap.h" //---------- // Macros #define PRINTLINE printf("%s:%d\n", __FUNCTION__, __LINE__) #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) #define GPIO_BASE 0x20200000 //---------- // global variables int mem_fd; // mmap file void *ptr; // virtual memory allocated by alloc // the variable gpio points to 0x20200000, that is GPIO registers // starts from GPFSEL0 to GPPUDCLK1 volatile unsigned long *gpio; // 0x20200000 volatile unsigned long *gpfsel; // 0x20200000 volatile unsigned long *gpset; // 0x2020001C volatile unsigned long *gpclr; // 0x20200028 volatile unsigned long *gplev; // 0x20200034 /*----------------------------------------------- * Open the GPIO Lib */ void gpio_open(void) { char *gpio_map; char *gpio_mem; PRINTLINE; // open /dev/mem mem_fd = open("/dev/mem", O_RDWR | O_SYNC); if(mem_fd < 0){ perror("Fail to open /dev/mem"); exit(-1); } ptr = malloc(BLOCK_SIZE + (PAGE_SIZE - 1)); if(ptr == NULL){ perror("Fail to malloc"); exit(-1); } // align page boundary if((unsigned long)ptr % PAGE_SIZE != 0){ gpio_mem = ptr + (PAGE_SIZE - ((unsigned long)ptr % PAGE_SIZE)); } else{ gpio_mem = ptr; } // map virtual to physical gpio_map = (char *)mmap( (caddr_t)gpio_mem, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, mem_fd, GPIO_BASE ); if((long)gpio_map < 0){ perror("Fail to mmap"); exit(-1); } gpio = (volatile unsigned long *)gpio_map; gpfsel = gpio + (0x00/4); gpset = gpio + (0x1C/4); gpclr = gpio + (0x28/4); gplev = gpio + (0x34/4); } /*----------------------------------------------- * Close the GPIO Lib */ void gpio_close(void) { close(mem_fd); free(ptr); } /*----------------------------------------------- * set function to the GPIO pin * once clear the 3 bits then set the function to the 3 bits */ void set_gpio_function(int pin, E_GPFSEL function) { volatile unsigned long *ptr; ptr = (gpfsel + (pin / 10)); *ptr &= ~(7 << ((pin % 10) * 3)); *ptr |= (function << ((pin % 10) * 3)); } /*----------------------------------------------- * set the GPIO pin to High/Low */ void set_gpio(int pin, int level) { volatile unsigned long *ptr; if(level == 1) ptr = gpset; else ptr = gpclr; if(pin < 32){ ptr = ptr + 0; } else{ ptr = ptr + 1; pin -= 32; } *ptr = 1 << pin; } /*----------------------------------------------- * get the level of the GPIO pin */ int get_gpio(int pin) { volatile unsigned long *gp; if(pin < 32){ gp = gplev + 0; } else{ gp = gplev + 1; pin -= 32; } return (((*gp) >> pin) & 1); }