raspi_tests

annotate gpiotest1/test.c @ 0:fbf9076c1984

first raspberry pi gpio test (led blinker)
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 01 Mar 2016 07:38:36 +0000
parents
children 7cdaa3a0df97
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <signal.h>
nuclear@0 3 #include <unistd.h>
nuclear@0 4 #include <fcntl.h>
nuclear@0 5 #include <sys/mman.h>
nuclear@0 6 #include "bcm_host.h"
nuclear@0 7
nuclear@0 8 #define REG_GPFSEL_BASE 0x200000
nuclear@0 9 #define REG_GPSET_BASE 0x20001c
nuclear@0 10 #define REG_GPCLR_BASE 0x200028
nuclear@0 11 #define REG_GPLEV_BASE 0x200034
nuclear@0 12
nuclear@0 13 #define FSEL_BITS 3
nuclear@0 14 #define FSEL_INPUT 0
nuclear@0 15 #define FSEL_OUTPUT 1
nuclear@0 16
nuclear@0 17 #define FSEL_SHIFT(i) (((i) % 10) * 3)
nuclear@0 18 #define FSEL_MASK(i) (3 << FSEL_SHIFT(i))
nuclear@0 19
nuclear@0 20 #define REG(r) (volatile uint32_t*)((unsigned char*)iomem + (r))
nuclear@0 21
nuclear@0 22 void *iomem;
nuclear@0 23 int quit;
nuclear@0 24
nuclear@0 25 static inline void set_pin_func(int pin, int func);
nuclear@0 26 static inline void set_pin_state(int pin, int s);
nuclear@0 27 static inline int get_pin_state(int pin);
nuclear@0 28 static void sighandler(int s);
nuclear@0 29
nuclear@0 30 int main(void)
nuclear@0 31 {
nuclear@0 32 int fd;
nuclear@0 33 int i;
nuclear@0 34 uint32_t io_addr, io_size;
nuclear@0 35
nuclear@0 36 signal(SIGINT, sighandler);
nuclear@0 37 signal(SIGQUIT, sighandler);
nuclear@0 38 signal(SIGSEGV, sighandler);
nuclear@0 39 signal(SIGILL, sighandler);
nuclear@0 40 signal(SIGFPE, sighandler);
nuclear@0 41
nuclear@0 42 io_addr = bcm_host_get_peripheral_address();
nuclear@0 43 io_size = bcm_host_get_peripheral_size();
nuclear@0 44 printf("I/O registers\n");
nuclear@0 45 printf(" addr: %x\n", io_addr);
nuclear@0 46 printf(" size: %d\n", io_size);
nuclear@0 47
nuclear@0 48 if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
nuclear@0 49 perror("failed to open /dev/mem");
nuclear@0 50 return 1;
nuclear@0 51 }
nuclear@0 52 if((iomem = mmap(0, io_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, io_addr)) == (void*)-1) {
nuclear@0 53 perror("failed to map I/O registers range");
nuclear@0 54 return 1;
nuclear@0 55 }
nuclear@0 56
nuclear@0 57 /* configure GPIO pins 4 and 17 as outputs */
nuclear@0 58 set_pin_func(4, FSEL_OUTPUT);
nuclear@0 59 set_pin_func(17, FSEL_OUTPUT);
nuclear@0 60
nuclear@0 61 i = 0;
nuclear@0 62 while(!quit) {
nuclear@0 63 set_pin_state(4, i & 1);
nuclear@0 64 set_pin_state(17, (~i) & 1);
nuclear@0 65 ++i;
nuclear@0 66 sleep(1);
nuclear@0 67 }
nuclear@0 68
nuclear@0 69 set_pin_state(4, 0);
nuclear@0 70 set_pin_state(17, 0);
nuclear@0 71 set_pin_func(4, FSEL_INPUT);
nuclear@0 72 set_pin_func(17, FSEL_INPUT);
nuclear@0 73
nuclear@0 74 munmap(iomem, io_size);
nuclear@0 75 close(fd);
nuclear@0 76 return 0;
nuclear@0 77 }
nuclear@0 78
nuclear@0 79 static inline void set_pin_func(int pin, int func)
nuclear@0 80 {
nuclear@0 81 int reg_addr, val;
nuclear@0 82 reg_addr = REG_GPFSEL_BASE + (pin / 10) * 4;
nuclear@0 83 val = *REG(reg_addr);
nuclear@0 84 *REG(reg_addr) = (val & FSEL_MASK(pin)) | (func << FSEL_SHIFT(pin));
nuclear@0 85 }
nuclear@0 86
nuclear@0 87 static inline void set_pin_state(int pin, int s)
nuclear@0 88 {
nuclear@0 89 int reg_addr;
nuclear@0 90 int regidx = pin / 32;
nuclear@0 91 int bit = pin % 32;
nuclear@0 92
nuclear@0 93 if(s) {
nuclear@0 94 reg_addr = REG_GPSET_BASE + regidx * 4;
nuclear@0 95 *REG(reg_addr) |= 1 << bit;
nuclear@0 96 } else {
nuclear@0 97 reg_addr = REG_GPCLR_BASE + regidx * 4;
nuclear@0 98 *REG(reg_addr) |= 1 << bit;
nuclear@0 99 }
nuclear@0 100 }
nuclear@0 101
nuclear@0 102 static inline int get_pin_state(int pin)
nuclear@0 103 {
nuclear@0 104 int reg_addr;
nuclear@0 105 int regidx = pin / 32;
nuclear@0 106 int bit = pin % 32;
nuclear@0 107
nuclear@0 108 reg_addr = REG_GPLEV_BASE + regidx * 4;
nuclear@0 109 return (*REG(reg_addr) >> bit) & 1;
nuclear@0 110 }
nuclear@0 111
nuclear@0 112 static void sighandler(int s)
nuclear@0 113 {
nuclear@0 114 quit = 1;
nuclear@0 115 }