# HG changeset patch # User John Tsiombikas # Date 1456979291 0 # Node ID 7cdaa3a0df9723b41a585022b65fb742e9206e6a # Parent fbf9076c1984627743c3baa2c6d71b86fc977336 - non-priviledged GPIO by opening /dev/gpiomem - input pin with internal pullup/pulldown resistor diff -r fbf9076c1984 -r 7cdaa3a0df97 gpiotest1/test.c --- a/gpiotest1/test.c Tue Mar 01 07:38:36 2016 +0000 +++ b/gpiotest1/test.c Thu Mar 03 04:28:11 2016 +0000 @@ -1,14 +1,19 @@ #include +#include #include +#include #include #include #include #include "bcm_host.h" -#define REG_GPFSEL_BASE 0x200000 -#define REG_GPSET_BASE 0x20001c -#define REG_GPCLR_BASE 0x200028 -#define REG_GPLEV_BASE 0x200034 +#define REG_GPIO_BASE 0x200000 +#define REG_GPFSEL_BASE 0x200000 +#define REG_GPSET_BASE 0x20001c +#define REG_GPCLR_BASE 0x200028 +#define REG_GPLEV_BASE 0x200034 +#define REG_GPPUD 0x200094 +#define REG_GPPUDCLK_BASE 0x200098 #define FSEL_BITS 3 #define FSEL_INPUT 0 @@ -25,13 +30,16 @@ static inline void set_pin_func(int pin, int func); static inline void set_pin_state(int pin, int s); static inline int get_pin_state(int pin); +static inline void set_pullup(int pin, int en); +static inline void set_pulldown(int pin, int en); static void sighandler(int s); int main(void) { int fd; int i; - uint32_t io_addr, io_size; + uint32_t io_addr, io_size, mmap_size; + void *mmap_ptr; signal(SIGINT, sighandler); signal(SIGQUIT, sighandler); @@ -45,33 +53,52 @@ printf(" addr: %x\n", io_addr); printf(" size: %d\n", io_size); - if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { + if((fd = open("/dev/gpiomem", O_RDWR | O_SYNC)) >= 0) { + mmap_size = 0xb4; /* last gpio reg addr + 4 */ + if((mmap_ptr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == (void*)-1) { + perror("failed to map I/O registers"); + return 1; + } + iomem = ((unsigned char*)mmap_ptr) - REG_GPIO_BASE; + } else if((fd = open("/dev/mem", O_RDWR | O_SYNC)) >= 0) { + mmap_size = io_size; + if((mmap_ptr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, io_addr)) == (void*)-1) { + perror("failed to map I/O registers"); + return 1; + } + iomem = mmap_ptr; + } else { perror("failed to open /dev/mem"); return 1; } - if((iomem = mmap(0, io_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, io_addr)) == (void*)-1) { - perror("failed to map I/O registers range"); - return 1; - } /* configure GPIO pins 4 and 17 as outputs */ set_pin_func(4, FSEL_OUTPUT); set_pin_func(17, FSEL_OUTPUT); + /* configure GPIO pin 22 as input, and enable it's pulldown resistor */ + set_pin_func(22, FSEL_INPUT); + set_pulldown(22, 1); i = 0; while(!quit) { - set_pin_state(4, i & 1); - set_pin_state(17, (~i) & 1); - ++i; - sleep(1); + if(get_pin_state(22)) { + set_pin_state(4, 1); + set_pin_state(17, 1); + } else { + set_pin_state(4, i & 1); + set_pin_state(17, (~i) & 1); + ++i; + } + usleep(250000); } set_pin_state(4, 0); set_pin_state(17, 0); set_pin_func(4, FSEL_INPUT); set_pin_func(17, FSEL_INPUT); + set_pulldown(22, 0); - munmap(iomem, io_size); + munmap(mmap_ptr, mmap_size); close(fd); return 0; } @@ -109,6 +136,39 @@ return (*REG(reg_addr) >> bit) & 1; } +#define delay_cycles(x) \ + __asm__ __volatile__ ( \ + "mov %0, #150\n" \ + "1:\n\t" \ + "nop\n\t" \ + "subs %0, %0, #1\n\t" \ + "bne 1b\n\t" \ + :: "r"(x)) + +static inline void set_pull_updown(int pin, int updown) +{ + int regidx = pin / 32; + int bit = pin % 32; + int clk_addr = REG_GPPUDCLK_BASE + regidx * 4; + + *REG(REG_GPPUD) = updown; + delay_cycles(150); + *REG(clk_addr) = bit; + delay_cycles(150); + *REG(REG_GPPUD) = 0; + *REG(clk_addr) = 0; +} + +static inline void set_pullup(int pin, int en) +{ + set_pull_updown(pin, en ? 2 : 0); +} + +static inline void set_pulldown(int pin, int en) +{ + set_pull_updown(pin, en ? 1 : 0); +} + static void sighandler(int s) { quit = 1;