Skip to content

Commit 3982134

Browse files
committed
upload from mac
1 parent a0aa567 commit 3982134

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+37913
-0
lines changed

Adafruit-GPIO-Halt/LICENSE

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Copyright (c) 2014, Adafruit Industries
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are met:
6+
7+
* Redistributions of source code must retain the above copyright notice, this
8+
list of conditions and the following disclaimer.
9+
10+
* Redistributions in binary form must reproduce the above copyright notice,
11+
this list of conditions and the following disclaimer in the documentation
12+
and/or other materials provided with the distribution.
13+
14+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24+

Adafruit-GPIO-Halt/Makefile

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
EXECS = gpio-halt
2+
CC = gcc $(CFLAGS) -Wall -O3 -fomit-frame-pointer -funroll-loops -s
3+
4+
all: $(EXECS)
5+
6+
gpio-halt: gpio-halt.c
7+
$(CC) $< -o $@
8+
strip $@
9+
10+
install:
11+
mv $(EXECS) /usr/local/bin
12+
13+
clean:
14+
rm -f $(EXECS)

Adafruit-GPIO-Halt/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Adafruit-GPIO-Halt
2+
==================
3+
4+
Press-to-halt program for headless Raspberry Pi. Similar functionality to the rpi_power_switch kernel module from the fbtft project, but easier to compile (no kernel headers needed).

Adafruit-GPIO-Halt/gpio-halt.c

+293
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
/*
2+
GPIO HALT: monitors a single GPIO pin, initiates orderly shutdown.
3+
Similar functionality to the rpi_power_switch kernel module from the
4+
fbtft project, but easier to compile (no kernel headers needed).
5+
6+
Connect button between any GND pin (there are several on the GPIO header)
7+
and the GPIO pin of interest. Internal pullup is used; no resistors needed.
8+
By default GPIO21 is used; this and GND are the last pins on the Model B+
9+
GPIO (40 pin) header, so it's very easy to plug in a button quick-connect.
10+
Different pin can be specified on the command line or by editing the code.
11+
Avoid pins 8 and 10; these are configured as a serial port by default on
12+
most systems (this can be disabled but takes some doing).
13+
14+
To run automatically at startup, move the executable to /usr/local/bin and
15+
edit /etc/rc.local, inserting this one line before the final 'exit 0':
16+
17+
/usr/local/bin/gpio-halt &
18+
19+
An alternate pin number can optionally be specified before the '&'
20+
21+
This is mostly just a pared-down 'retrogame' from the Cupcade project.
22+
23+
Written by Phil Burgess for Adafruit Industries, distributed under BSD
24+
License. Adafruit invests time and resources providing this open source
25+
code, please support Adafruit and open-source hardware by purchasing
26+
products from Adafruit!
27+
28+
29+
Copyright (c) 2014 Adafruit Industries.
30+
All rights reserved.
31+
32+
Redistribution and use in source and binary forms, with or without
33+
modification, are permitted provided that the following conditions are met:
34+
35+
- Redistributions of source code must retain the above copyright notice,
36+
this list of conditions and the following disclaimer.
37+
- Redistributions in binary form must reproduce the above copyright notice,
38+
this list of conditions and the following disclaimer in the documentation
39+
and/or other materials provided with the distribution.
40+
41+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
42+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
45+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
47+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51+
POSSIBILITY OF SUCH DAMAGE.
52+
*/
53+
54+
#include <stdio.h>
55+
#include <stdlib.h>
56+
#include <string.h>
57+
#include <unistd.h>
58+
#include <fcntl.h>
59+
#include <poll.h>
60+
#include <signal.h>
61+
#include <sys/mman.h>
62+
63+
// A few globals ---------------------------------------------------------
64+
65+
char
66+
*progName, // Program name (for error reporting)
67+
sysfs_root[] = "/sys/class/gpio", // Location of Sysfs GPIO files
68+
running = 1; // Signal handler will set to 0 (exit)
69+
int
70+
pin = 21; // Shutdown pin # (override w/argv)
71+
volatile unsigned int
72+
*gpio; // GPIO register table
73+
const int
74+
debounceTime = 20; // 20 ms for button debouncing
75+
76+
77+
// Some utility functions ------------------------------------------------
78+
79+
// Set one GPIO pin attribute through the Sysfs interface.
80+
int pinConfig(char *attr, char *value) {
81+
char filename[50];
82+
int fd, w, len = strlen(value);
83+
sprintf(filename, "%s/gpio%d/%s", sysfs_root, pin, attr);
84+
if((fd = open(filename, O_WRONLY)) < 0) return -1;
85+
w = write(fd, value, len);
86+
close(fd);
87+
return (w != len); // 0 = success
88+
}
89+
90+
// Un-export Sysfs pins; don't leave filesystem cruft. Write errors are
91+
// ignored as pins may be in a partially-initialized state.
92+
void cleanup() {
93+
char buf[50];
94+
int fd;
95+
sprintf(buf, "%s/unexport", sysfs_root);
96+
if((fd = open(buf, O_WRONLY)) >= 0) {
97+
sprintf(buf, "%d", pin);
98+
write(fd, buf, strlen(buf));
99+
close(fd);
100+
}
101+
}
102+
103+
// Quick-n-dirty error reporter; print message, clean up and exit.
104+
void err(char *msg) {
105+
printf("%s: %s. Try 'sudo %s'.\n", progName, msg, progName);
106+
cleanup();
107+
exit(1);
108+
}
109+
110+
// Interrupt handler -- set global flag to abort main loop.
111+
void signalHandler(int n) {
112+
running = 0;
113+
}
114+
115+
// Detect Pi board type. Doesn't return super-granular details,
116+
// just the most basic distinction needed for GPIO compatibility:
117+
// 0: Pi 1 Model B revision 1
118+
// 1: Pi 1 Model B revision 2, Model A, Model B+, Model A+
119+
// 2: Pi 2 Model B
120+
121+
static int boardType(void) {
122+
FILE *fp;
123+
char buf[1024], *ptr;
124+
int n, board = 1; // Assume Pi1 Rev2 by default
125+
126+
// Relies on info in /proc/cmdline. If this becomes unreliable
127+
// in the future, alt code below uses /proc/cpuinfo if any better.
128+
#if 1
129+
if((fp = fopen("/proc/cmdline", "r"))) {
130+
while(fgets(buf, sizeof(buf), fp)) {
131+
if((ptr = strstr(buf, "mem_size=")) &&
132+
(sscanf(&ptr[9], "%x", &n) == 1) &&
133+
((n == 0x3F000000) || (n == 0x40000000))) {
134+
board = 2; // Appears to be a Pi 2
135+
break;
136+
} else if((ptr = strstr(buf, "boardrev=")) &&
137+
(sscanf(&ptr[9], "%x", &n) == 1) &&
138+
((n == 0x02) || (n == 0x03))) {
139+
board = 0; // Appears to be an early Pi
140+
break;
141+
}
142+
}
143+
fclose(fp);
144+
}
145+
#else
146+
char s[8];
147+
if((fp = fopen("/proc/cpuinfo", "r"))) {
148+
while(fgets(buf, sizeof(buf), fp)) {
149+
if((ptr = strstr(buf, "Hardware")) &&
150+
(sscanf(&ptr[8], " : %7s", s) == 1) &&
151+
(!strcmp(s, "BCM2709"))) {
152+
board = 2; // Appears to be a Pi 2
153+
break;
154+
} else if((ptr = strstr(buf, "Revision")) &&
155+
(sscanf(&ptr[8], " : %x", &n) == 1) &&
156+
((n == 0x02) || (n == 0x03))) {
157+
board = 0; // Appears to be an early Pi
158+
break;
159+
}
160+
}
161+
fclose(fp);
162+
}
163+
#endif
164+
165+
return board;
166+
}
167+
168+
169+
// Main stuff ------------------------------------------------------------
170+
171+
#define PI1_BCM2708_PERI_BASE 0x20000000
172+
#define PI1_GPIO_BASE (PI1_BCM2708_PERI_BASE + 0x200000)
173+
#define PI2_BCM2708_PERI_BASE 0x3F000000
174+
#define PI2_GPIO_BASE (PI2_BCM2708_PERI_BASE + 0x200000)
175+
#define BLOCK_SIZE (4*1024)
176+
#define GPPUD (0x94 / 4)
177+
#define GPPUDCLK0 (0x98 / 4)
178+
179+
int main(int argc, char *argv[]) {
180+
181+
char buf[50], // For sundry filenames
182+
c, // Pin input value ('0'/'1')
183+
board; // 0=Pi1Rev1, 1=Pi1Rev2, 2=Pi2
184+
int fd, // For mmap, sysfs, uinput
185+
timeout = -1, // poll() timeout
186+
pressed; // Last-read pin state
187+
volatile unsigned char shortWait; // Delay counter
188+
struct pollfd p; // GPIO file descriptor
189+
190+
progName = argv[0]; // For error reporting
191+
signal(SIGINT , signalHandler); // Trap basic signals (exit cleanly)
192+
signal(SIGKILL, signalHandler);
193+
194+
if(argc > 1) pin = atoi(argv[1]);
195+
196+
// If this is a "Revision 1" Pi board (no mounting holes),
197+
// remap certain pin numbers for compatibility.
198+
board = boardType();
199+
if(board == 0) {
200+
if( pin == 2) pin = 0;
201+
else if(pin == 3) pin = 1;
202+
else if(pin == 27) pin = 21;
203+
}
204+
205+
// ----------------------------------------------------------------
206+
// Although Sysfs provides solid GPIO interrupt handling, there's
207+
// no interface to the internal pull-up resistors (this is by
208+
// design, being a hardware-dependent feature). It's necessary to
209+
// grapple with the GPIO configuration registers directly to enable
210+
// the pull-ups. Based on GPIO example code by Dom and Gert van
211+
// Loo on elinux.org
212+
213+
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0)
214+
err("Can't open /dev/mem");
215+
gpio = mmap( // Memory-mapped I/O
216+
NULL, // Any adddress will do
217+
BLOCK_SIZE, // Mapped block length
218+
PROT_READ|PROT_WRITE, // Enable read+write
219+
MAP_SHARED, // Shared with other processes
220+
fd, // File to map
221+
(board == 2) ?
222+
PI2_GPIO_BASE : // -> GPIO registers
223+
PI1_GPIO_BASE);
224+
close(fd); // Not needed after mmap()
225+
if(gpio == MAP_FAILED) err("Can't mmap()");
226+
gpio[GPPUD] = 2; // Enable pullup
227+
for(shortWait=150;--shortWait;); // Min 150 cycle wait
228+
gpio[GPPUDCLK0] = 1 << pin; // Set pullup mask
229+
for(shortWait=150;--shortWait;); // Wait again
230+
gpio[GPPUD] = 0; // Reset pullup registers
231+
gpio[GPPUDCLK0] = 0;
232+
(void)munmap((void *)gpio, BLOCK_SIZE); // Done with GPIO mmap()
233+
234+
// ----------------------------------------------------------------
235+
// All other GPIO config is handled through the sysfs interface.
236+
237+
sprintf(buf, "%s/export", sysfs_root);
238+
if((fd = open(buf, O_WRONLY)) < 0) // Open Sysfs export file
239+
err("Can't open GPIO export file");
240+
sprintf(buf, "%d", pin);
241+
write(fd, buf, strlen(buf)); // Export pin
242+
pinConfig("active_low", "0"); // Don't invert
243+
// Set pin to input, detect rise+fall events
244+
if(pinConfig("direction", "in") ||
245+
pinConfig("edge" , "both"))
246+
err("Pin config failed");
247+
// Get initial pin value
248+
sprintf(buf, "%s/gpio%d/value", sysfs_root, pin);
249+
if((p.fd = open(buf, O_RDONLY)) < 0)
250+
err("Can't access pin value");
251+
pressed = 0;
252+
if((read(p.fd, &c, 1) == 1) && (c == '0')) pressed = 1;
253+
p.events = POLLPRI; // Set up poll() events
254+
p.revents = 0;
255+
close(fd); // Done exporting
256+
257+
// ----------------------------------------------------------------
258+
// Monitor GPIO file descriptor for button events. The poll()
259+
// function watches for GPIO IRQs in this case; it is NOT
260+
// continually polling the pins! Processor load is near zero.
261+
262+
while(running) { // Signal handler can set this to 0 to exit
263+
// Wait for IRQ on pin (or timeout for button debounce)
264+
if(poll(&p, 1, timeout) > 0) { // If IRQ...
265+
if(p.revents) { // Event received?
266+
// Read current pin state, store in
267+
// 'pressed' state flag, but don't halt
268+
// yet -- must wait for debounce!
269+
lseek(p.fd, 0, SEEK_SET);
270+
read(p.fd, &c, 1);
271+
if(c == '0') pressed = 1;
272+
else if(c == '1') pressed = 0;
273+
p.revents = 0; // Clear flag
274+
}
275+
timeout = debounceTime; // Set timeout for debounce
276+
// Else timeout occurred
277+
} else if(timeout == debounceTime) { // Button debounce timeout
278+
if(pressed) {
279+
(void)system("shutdown -h now");
280+
running = 0;
281+
}
282+
}
283+
}
284+
285+
// ----------------------------------------------------------------
286+
// Clean up
287+
288+
cleanup(); // Un-export pins
289+
290+
puts("Done.");
291+
292+
return 0;
293+
}

0 commit comments

Comments
 (0)