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;