rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@1
|
2 #include <string.h>
|
nuclear@0
|
3 #include <signal.h>
|
nuclear@1
|
4 #include <errno.h>
|
nuclear@0
|
5 #include <unistd.h>
|
nuclear@0
|
6 #include <fcntl.h>
|
nuclear@0
|
7 #include <sys/mman.h>
|
nuclear@0
|
8 #include "bcm_host.h"
|
nuclear@0
|
9
|
nuclear@1
|
10 #define REG_GPIO_BASE 0x200000
|
nuclear@1
|
11 #define REG_GPFSEL_BASE 0x200000
|
nuclear@1
|
12 #define REG_GPSET_BASE 0x20001c
|
nuclear@1
|
13 #define REG_GPCLR_BASE 0x200028
|
nuclear@1
|
14 #define REG_GPLEV_BASE 0x200034
|
nuclear@1
|
15 #define REG_GPPUD 0x200094
|
nuclear@1
|
16 #define REG_GPPUDCLK_BASE 0x200098
|
nuclear@0
|
17
|
nuclear@0
|
18 #define FSEL_BITS 3
|
nuclear@0
|
19 #define FSEL_INPUT 0
|
nuclear@0
|
20 #define FSEL_OUTPUT 1
|
nuclear@0
|
21
|
nuclear@0
|
22 #define FSEL_SHIFT(i) (((i) % 10) * 3)
|
nuclear@0
|
23 #define FSEL_MASK(i) (3 << FSEL_SHIFT(i))
|
nuclear@0
|
24
|
nuclear@0
|
25 #define REG(r) (volatile uint32_t*)((unsigned char*)iomem + (r))
|
nuclear@0
|
26
|
nuclear@0
|
27 void *iomem;
|
nuclear@0
|
28 int quit;
|
nuclear@0
|
29
|
nuclear@0
|
30 static inline void set_pin_func(int pin, int func);
|
nuclear@0
|
31 static inline void set_pin_state(int pin, int s);
|
nuclear@0
|
32 static inline int get_pin_state(int pin);
|
nuclear@1
|
33 static inline void set_pullup(int pin, int en);
|
nuclear@1
|
34 static inline void set_pulldown(int pin, int en);
|
nuclear@0
|
35 static void sighandler(int s);
|
nuclear@0
|
36
|
nuclear@0
|
37 int main(void)
|
nuclear@0
|
38 {
|
nuclear@0
|
39 int fd;
|
nuclear@0
|
40 int i;
|
nuclear@1
|
41 uint32_t io_addr, io_size, mmap_size;
|
nuclear@1
|
42 void *mmap_ptr;
|
nuclear@0
|
43
|
nuclear@0
|
44 signal(SIGINT, sighandler);
|
nuclear@0
|
45 signal(SIGQUIT, sighandler);
|
nuclear@0
|
46 signal(SIGSEGV, sighandler);
|
nuclear@0
|
47 signal(SIGILL, sighandler);
|
nuclear@0
|
48 signal(SIGFPE, sighandler);
|
nuclear@0
|
49
|
nuclear@0
|
50 io_addr = bcm_host_get_peripheral_address();
|
nuclear@0
|
51 io_size = bcm_host_get_peripheral_size();
|
nuclear@0
|
52 printf("I/O registers\n");
|
nuclear@0
|
53 printf(" addr: %x\n", io_addr);
|
nuclear@0
|
54 printf(" size: %d\n", io_size);
|
nuclear@0
|
55
|
nuclear@1
|
56 if((fd = open("/dev/gpiomem", O_RDWR | O_SYNC)) >= 0) {
|
nuclear@1
|
57 mmap_size = 0xb4; /* last gpio reg addr + 4 */
|
nuclear@1
|
58 if((mmap_ptr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == (void*)-1) {
|
nuclear@1
|
59 perror("failed to map I/O registers");
|
nuclear@1
|
60 return 1;
|
nuclear@1
|
61 }
|
nuclear@1
|
62 iomem = ((unsigned char*)mmap_ptr) - REG_GPIO_BASE;
|
nuclear@1
|
63 } else if((fd = open("/dev/mem", O_RDWR | O_SYNC)) >= 0) {
|
nuclear@1
|
64 mmap_size = io_size;
|
nuclear@1
|
65 if((mmap_ptr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, io_addr)) == (void*)-1) {
|
nuclear@1
|
66 perror("failed to map I/O registers");
|
nuclear@1
|
67 return 1;
|
nuclear@1
|
68 }
|
nuclear@1
|
69 iomem = mmap_ptr;
|
nuclear@1
|
70 } else {
|
nuclear@0
|
71 perror("failed to open /dev/mem");
|
nuclear@0
|
72 return 1;
|
nuclear@0
|
73 }
|
nuclear@0
|
74
|
nuclear@0
|
75 /* configure GPIO pins 4 and 17 as outputs */
|
nuclear@0
|
76 set_pin_func(4, FSEL_OUTPUT);
|
nuclear@0
|
77 set_pin_func(17, FSEL_OUTPUT);
|
nuclear@1
|
78 /* configure GPIO pin 22 as input, and enable it's pulldown resistor */
|
nuclear@1
|
79 set_pin_func(22, FSEL_INPUT);
|
nuclear@1
|
80 set_pulldown(22, 1);
|
nuclear@0
|
81
|
nuclear@0
|
82 i = 0;
|
nuclear@0
|
83 while(!quit) {
|
nuclear@1
|
84 if(get_pin_state(22)) {
|
nuclear@1
|
85 set_pin_state(4, 1);
|
nuclear@1
|
86 set_pin_state(17, 1);
|
nuclear@1
|
87 } else {
|
nuclear@1
|
88 set_pin_state(4, i & 1);
|
nuclear@1
|
89 set_pin_state(17, (~i) & 1);
|
nuclear@1
|
90 ++i;
|
nuclear@1
|
91 }
|
nuclear@1
|
92 usleep(250000);
|
nuclear@0
|
93 }
|
nuclear@0
|
94
|
nuclear@0
|
95 set_pin_state(4, 0);
|
nuclear@0
|
96 set_pin_state(17, 0);
|
nuclear@0
|
97 set_pin_func(4, FSEL_INPUT);
|
nuclear@0
|
98 set_pin_func(17, FSEL_INPUT);
|
nuclear@1
|
99 set_pulldown(22, 0);
|
nuclear@0
|
100
|
nuclear@1
|
101 munmap(mmap_ptr, mmap_size);
|
nuclear@0
|
102 close(fd);
|
nuclear@0
|
103 return 0;
|
nuclear@0
|
104 }
|
nuclear@0
|
105
|
nuclear@0
|
106 static inline void set_pin_func(int pin, int func)
|
nuclear@0
|
107 {
|
nuclear@0
|
108 int reg_addr, val;
|
nuclear@0
|
109 reg_addr = REG_GPFSEL_BASE + (pin / 10) * 4;
|
nuclear@0
|
110 val = *REG(reg_addr);
|
nuclear@0
|
111 *REG(reg_addr) = (val & FSEL_MASK(pin)) | (func << FSEL_SHIFT(pin));
|
nuclear@0
|
112 }
|
nuclear@0
|
113
|
nuclear@0
|
114 static inline void set_pin_state(int pin, int s)
|
nuclear@0
|
115 {
|
nuclear@0
|
116 int reg_addr;
|
nuclear@0
|
117 int regidx = pin / 32;
|
nuclear@0
|
118 int bit = pin % 32;
|
nuclear@0
|
119
|
nuclear@0
|
120 if(s) {
|
nuclear@0
|
121 reg_addr = REG_GPSET_BASE + regidx * 4;
|
nuclear@0
|
122 *REG(reg_addr) |= 1 << bit;
|
nuclear@0
|
123 } else {
|
nuclear@0
|
124 reg_addr = REG_GPCLR_BASE + regidx * 4;
|
nuclear@0
|
125 *REG(reg_addr) |= 1 << bit;
|
nuclear@0
|
126 }
|
nuclear@0
|
127 }
|
nuclear@0
|
128
|
nuclear@0
|
129 static inline int get_pin_state(int pin)
|
nuclear@0
|
130 {
|
nuclear@0
|
131 int reg_addr;
|
nuclear@0
|
132 int regidx = pin / 32;
|
nuclear@0
|
133 int bit = pin % 32;
|
nuclear@0
|
134
|
nuclear@0
|
135 reg_addr = REG_GPLEV_BASE + regidx * 4;
|
nuclear@0
|
136 return (*REG(reg_addr) >> bit) & 1;
|
nuclear@0
|
137 }
|
nuclear@0
|
138
|
nuclear@1
|
139 #define delay_cycles(x) \
|
nuclear@1
|
140 __asm__ __volatile__ ( \
|
nuclear@1
|
141 "mov %0, #150\n" \
|
nuclear@1
|
142 "1:\n\t" \
|
nuclear@1
|
143 "nop\n\t" \
|
nuclear@1
|
144 "subs %0, %0, #1\n\t" \
|
nuclear@1
|
145 "bne 1b\n\t" \
|
nuclear@1
|
146 :: "r"(x))
|
nuclear@1
|
147
|
nuclear@1
|
148 static inline void set_pull_updown(int pin, int updown)
|
nuclear@1
|
149 {
|
nuclear@1
|
150 int regidx = pin / 32;
|
nuclear@1
|
151 int bit = pin % 32;
|
nuclear@1
|
152 int clk_addr = REG_GPPUDCLK_BASE + regidx * 4;
|
nuclear@1
|
153
|
nuclear@1
|
154 *REG(REG_GPPUD) = updown;
|
nuclear@1
|
155 delay_cycles(150);
|
nuclear@1
|
156 *REG(clk_addr) = bit;
|
nuclear@1
|
157 delay_cycles(150);
|
nuclear@1
|
158 *REG(REG_GPPUD) = 0;
|
nuclear@1
|
159 *REG(clk_addr) = 0;
|
nuclear@1
|
160 }
|
nuclear@1
|
161
|
nuclear@1
|
162 static inline void set_pullup(int pin, int en)
|
nuclear@1
|
163 {
|
nuclear@1
|
164 set_pull_updown(pin, en ? 2 : 0);
|
nuclear@1
|
165 }
|
nuclear@1
|
166
|
nuclear@1
|
167 static inline void set_pulldown(int pin, int en)
|
nuclear@1
|
168 {
|
nuclear@1
|
169 set_pull_updown(pin, en ? 1 : 0);
|
nuclear@1
|
170 }
|
nuclear@1
|
171
|
nuclear@0
|
172 static void sighandler(int s)
|
nuclear@0
|
173 {
|
nuclear@0
|
174 quit = 1;
|
nuclear@0
|
175 }
|