raspi_tests
changeset 1:7cdaa3a0df97 tip
- non-priviledged GPIO by opening /dev/gpiomem
- input pin with internal pullup/pulldown resistor
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 03 Mar 2016 04:28:11 +0000 |
parents | fbf9076c1984 |
children | |
files | gpiotest1/test.c |
diffstat | 1 files changed, 75 insertions(+), 15 deletions(-) [+] |
line diff
1.1 --- a/gpiotest1/test.c Tue Mar 01 07:38:36 2016 +0000 1.2 +++ b/gpiotest1/test.c Thu Mar 03 04:28:11 2016 +0000 1.3 @@ -1,14 +1,19 @@ 1.4 #include <stdio.h> 1.5 +#include <string.h> 1.6 #include <signal.h> 1.7 +#include <errno.h> 1.8 #include <unistd.h> 1.9 #include <fcntl.h> 1.10 #include <sys/mman.h> 1.11 #include "bcm_host.h" 1.12 1.13 -#define REG_GPFSEL_BASE 0x200000 1.14 -#define REG_GPSET_BASE 0x20001c 1.15 -#define REG_GPCLR_BASE 0x200028 1.16 -#define REG_GPLEV_BASE 0x200034 1.17 +#define REG_GPIO_BASE 0x200000 1.18 +#define REG_GPFSEL_BASE 0x200000 1.19 +#define REG_GPSET_BASE 0x20001c 1.20 +#define REG_GPCLR_BASE 0x200028 1.21 +#define REG_GPLEV_BASE 0x200034 1.22 +#define REG_GPPUD 0x200094 1.23 +#define REG_GPPUDCLK_BASE 0x200098 1.24 1.25 #define FSEL_BITS 3 1.26 #define FSEL_INPUT 0 1.27 @@ -25,13 +30,16 @@ 1.28 static inline void set_pin_func(int pin, int func); 1.29 static inline void set_pin_state(int pin, int s); 1.30 static inline int get_pin_state(int pin); 1.31 +static inline void set_pullup(int pin, int en); 1.32 +static inline void set_pulldown(int pin, int en); 1.33 static void sighandler(int s); 1.34 1.35 int main(void) 1.36 { 1.37 int fd; 1.38 int i; 1.39 - uint32_t io_addr, io_size; 1.40 + uint32_t io_addr, io_size, mmap_size; 1.41 + void *mmap_ptr; 1.42 1.43 signal(SIGINT, sighandler); 1.44 signal(SIGQUIT, sighandler); 1.45 @@ -45,33 +53,52 @@ 1.46 printf(" addr: %x\n", io_addr); 1.47 printf(" size: %d\n", io_size); 1.48 1.49 - if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { 1.50 + if((fd = open("/dev/gpiomem", O_RDWR | O_SYNC)) >= 0) { 1.51 + mmap_size = 0xb4; /* last gpio reg addr + 4 */ 1.52 + if((mmap_ptr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == (void*)-1) { 1.53 + perror("failed to map I/O registers"); 1.54 + return 1; 1.55 + } 1.56 + iomem = ((unsigned char*)mmap_ptr) - REG_GPIO_BASE; 1.57 + } else if((fd = open("/dev/mem", O_RDWR | O_SYNC)) >= 0) { 1.58 + mmap_size = io_size; 1.59 + if((mmap_ptr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, io_addr)) == (void*)-1) { 1.60 + perror("failed to map I/O registers"); 1.61 + return 1; 1.62 + } 1.63 + iomem = mmap_ptr; 1.64 + } else { 1.65 perror("failed to open /dev/mem"); 1.66 return 1; 1.67 } 1.68 - if((iomem = mmap(0, io_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, io_addr)) == (void*)-1) { 1.69 - perror("failed to map I/O registers range"); 1.70 - return 1; 1.71 - } 1.72 1.73 /* configure GPIO pins 4 and 17 as outputs */ 1.74 set_pin_func(4, FSEL_OUTPUT); 1.75 set_pin_func(17, FSEL_OUTPUT); 1.76 + /* configure GPIO pin 22 as input, and enable it's pulldown resistor */ 1.77 + set_pin_func(22, FSEL_INPUT); 1.78 + set_pulldown(22, 1); 1.79 1.80 i = 0; 1.81 while(!quit) { 1.82 - set_pin_state(4, i & 1); 1.83 - set_pin_state(17, (~i) & 1); 1.84 - ++i; 1.85 - sleep(1); 1.86 + if(get_pin_state(22)) { 1.87 + set_pin_state(4, 1); 1.88 + set_pin_state(17, 1); 1.89 + } else { 1.90 + set_pin_state(4, i & 1); 1.91 + set_pin_state(17, (~i) & 1); 1.92 + ++i; 1.93 + } 1.94 + usleep(250000); 1.95 } 1.96 1.97 set_pin_state(4, 0); 1.98 set_pin_state(17, 0); 1.99 set_pin_func(4, FSEL_INPUT); 1.100 set_pin_func(17, FSEL_INPUT); 1.101 + set_pulldown(22, 0); 1.102 1.103 - munmap(iomem, io_size); 1.104 + munmap(mmap_ptr, mmap_size); 1.105 close(fd); 1.106 return 0; 1.107 } 1.108 @@ -109,6 +136,39 @@ 1.109 return (*REG(reg_addr) >> bit) & 1; 1.110 } 1.111 1.112 +#define delay_cycles(x) \ 1.113 + __asm__ __volatile__ ( \ 1.114 + "mov %0, #150\n" \ 1.115 + "1:\n\t" \ 1.116 + "nop\n\t" \ 1.117 + "subs %0, %0, #1\n\t" \ 1.118 + "bne 1b\n\t" \ 1.119 + :: "r"(x)) 1.120 + 1.121 +static inline void set_pull_updown(int pin, int updown) 1.122 +{ 1.123 + int regidx = pin / 32; 1.124 + int bit = pin % 32; 1.125 + int clk_addr = REG_GPPUDCLK_BASE + regidx * 4; 1.126 + 1.127 + *REG(REG_GPPUD) = updown; 1.128 + delay_cycles(150); 1.129 + *REG(clk_addr) = bit; 1.130 + delay_cycles(150); 1.131 + *REG(REG_GPPUD) = 0; 1.132 + *REG(clk_addr) = 0; 1.133 +} 1.134 + 1.135 +static inline void set_pullup(int pin, int en) 1.136 +{ 1.137 + set_pull_updown(pin, en ? 2 : 0); 1.138 +} 1.139 + 1.140 +static inline void set_pulldown(int pin, int en) 1.141 +{ 1.142 + set_pull_updown(pin, en ? 1 : 0); 1.143 +} 1.144 + 1.145 static void sighandler(int s) 1.146 { 1.147 quit = 1;