454
|
1 // |
|
2 // How to access GPIO registers from C-code on the Raspberry-Pi |
|
3 // Example program |
|
4 // 15-January-2012 |
|
5 // Dom and Gert |
|
6 // |
|
7 |
|
8 |
|
9 // Access from ARM Running Linux |
|
10 |
|
11 #define BCM2708_PERI_BASE 0x20000000 |
|
12 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ |
|
13 |
|
14 |
|
15 #include <stdio.h> |
|
16 #include <string.h> |
|
17 #include <stdlib.h> |
|
18 #include <dirent.h> |
|
19 #include <fcntl.h> |
|
20 #include <assert.h> |
|
21 #include <sys/mman.h> |
|
22 #include <sys/types.h> |
|
23 #include <sys/stat.h> |
|
24 |
|
25 #include <unistd.h> |
|
26 |
|
27 #define PAGE_SIZE (4*1024) |
|
28 #define BLOCK_SIZE (4*1024) |
|
29 |
|
30 int mem_fd; |
|
31 char *gpio_mem, *gpio_map; |
|
32 char *spi0_mem, *spi0_map; |
|
33 |
|
34 |
|
35 // I/O access |
|
36 volatile unsigned *gpio; |
|
37 |
|
38 |
|
39 // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y) |
|
40 #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) |
|
41 #define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) |
|
42 #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) |
|
43 |
|
44 #define FSEL_OFFSET 0 // 0x0000 |
|
45 #define SET_OFFSET 7 // 0x001c / 4 |
|
46 #define CLR_OFFSET 10 // 0x0028 / 4 |
|
47 #define PINLEVEL_OFFSET 13 // 0x0034 / 4 |
|
48 #define EVENT_DETECT_OFFSET 16 // 0x0040 / 4 |
|
49 #define RISING_ED_OFFSET 19 // 0x004c / 4 |
|
50 #define FALLING_ED_OFFSET 22 // 0x0058 / 4 |
|
51 #define HIGH_DETECT_OFFSET 25 // 0x0064 / 4 |
|
52 #define LOW_DETECT_OFFSET 28 // 0x0070 / 4 |
|
53 #define PULLUPDN_OFFSET 37 // 0x0094 / 4 |
|
54 #define PULLUPDNCLK_OFFSET 38 // 0x0098 / 4 |
|
55 |
|
56 |
|
57 #define GPIO_GET(g) ((*(gpio+PINLEVEL_OFFSET) & (1<<(g))) >> (g)) |
|
58 #define GPIO_SET(g) (*(gpio+SET_OFFSET) = 1<<(g)) // sets bits which are 1 ignores bits which are 0 |
|
59 #define GPIO_CLR(g) (*(gpio+CLR_OFFSET) = 1<<(g))// clears bits which are 1 ignores bits which are 0 |
|
60 |
|
61 #define TOUCH_IN 24 |
|
62 #define TOUCH_OUT 25 |
|
63 |
|
64 void setup_io(); |
|
65 |
|
66 int main(int argc, char **argv) |
|
67 { |
|
68 int g,rep; |
|
69 |
|
70 // Set up gpi pointer for direct register access |
|
71 setup_io(); |
|
72 |
|
73 // Switch GPIO 7..11 to output mode |
|
74 |
|
75 /************************************************************************\ |
|
76 * You are about to change the GPIO settings of your computer. * |
|
77 * Mess this up and it will stop working! * |
|
78 * It might be a good idea to 'sync' before running this program * |
|
79 * so at least you still have your code changes written to the SD-card! * |
|
80 \************************************************************************/ |
|
81 |
|
82 |
|
83 INP_GPIO(TOUCH_IN); |
|
84 INP_GPIO(TOUCH_OUT); |
|
85 OUT_GPIO(TOUCH_OUT); |
|
86 |
|
87 int num = 1000; |
|
88 int sum = 0; |
|
89 |
|
90 while (1) |
|
91 { |
|
92 int n; |
|
93 sum = 0; |
|
94 for (n = 0; n < num; n++) |
|
95 { |
|
96 GPIO_CLR(TOUCH_OUT); |
|
97 usleep(1000); |
|
98 GPIO_SET(TOUCH_OUT); |
|
99 while (GPIO_GET(TOUCH_IN) == 0) |
|
100 { |
|
101 sum++; |
|
102 } |
|
103 } |
|
104 printf("total %f\n", (float)sum / num); |
|
105 } |
|
106 return 0; |
|
107 |
|
108 } // main |
|
109 |
|
110 |
|
111 // |
|
112 // Set up a memory regions to access GPIO |
|
113 // |
|
114 void setup_io() |
|
115 { |
|
116 /* open /dev/mem */ |
|
117 if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { |
|
118 printf("can't open /dev/mem \n"); |
|
119 exit (-1); |
|
120 } |
|
121 |
|
122 /* mmap GPIO */ |
|
123 |
|
124 // Allocate MAP block |
|
125 if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) { |
|
126 printf("allocation error \n"); |
|
127 exit (-1); |
|
128 } |
|
129 |
|
130 // Make sure pointer is on 4K boundary |
|
131 if ((unsigned long)gpio_mem % PAGE_SIZE) |
|
132 gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE); |
|
133 |
|
134 // Now map it |
|
135 gpio_map = (unsigned char *)mmap( |
|
136 (caddr_t)gpio_mem, |
|
137 BLOCK_SIZE, |
|
138 PROT_READ|PROT_WRITE, |
|
139 MAP_SHARED|MAP_FIXED, |
|
140 mem_fd, |
|
141 GPIO_BASE |
|
142 ); |
|
143 |
|
144 if ((long)gpio_map < 0) { |
|
145 printf("mmap error %d\n", (int)gpio_map); |
|
146 exit (-1); |
|
147 } |
|
148 |
|
149 // Always use volatile pointer! |
|
150 gpio = (volatile unsigned *)gpio_map; |
|
151 |
|
152 |
|
153 } // setup_io |