著者:米田聡
小型コンピュータボード「Raspberry Pi」(ラズパイ)向けにさまざまな拡張ボードが発売されています。その拡張ボードとラズパイを組み合わせれば、ラズパイでいろいろなことが簡単に試せます。第3回は、電源断でもラズパイを正常終了するための拡張基板を扱います。
シェルスクリプトマガジン Vol.70は以下のリンク先でご購入できます。
図3 ADRSZUPコマンドのソースコード(ADRSZUP.c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
#include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <poll.h> #include <string.h> #include <time.h> #include <linux/reboot.h> #define TRUE 1 #define FALSE 0 /* エラーメッセージ */ void error(char *s) { fputs(s, stderr); } /* GPIO初期化 */ int initGpio(unsigned int gpio) { char buf[256]; int i, fd; // export fd = open("/sys/class/gpio/export", O_WRONLY); if( fd < 0 ) { error("/sys/class/gpio/export cant be opened \n"); return FALSE; } sprintf(buf,"%d",gpio); write(fd, buf, strlen(buf)); close(fd); // direction sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio); for( i=0; i < 10000; i++) { fd = open(buf,O_WRONLY ); if(fd >= 0) break; } if(fd < 0) { error("Direction cant opened\n"); return FALSE; } sprintf(buf,"in"); write(fd, buf, strlen(buf)); close(fd); // High -> Low falling edge sprintf(buf, "/sys/class/gpio/gpio%d/edge", gpio); for( i=0; i < 10000; i++) { fd = open(buf,O_WRONLY ); if(fd >= 0) break; } if( fd < 0 ) { error("Edge cant opended\n"); return FALSE; } sprintf(buf, "falling"); write(fd, buf, strlen(buf)); close(fd); return TRUE; } /* GPIO開放 */ int deinitGpio(unsigned int gpio) { char buf[256]; int fd; sprintf(buf, "%d", gpio); fd = open("/sys/class/gpio/unexport", O_WRONLY); if(fd < 0 ){ error("GPIO cant opened"); return FALSE; } write(fd, buf, strlen(buf)); close(fd); return TRUE; } /* シャットダウン */ int shutdown(void) { sync(); sync(); return reboot(LINUX_REBOOT_CMD_POWER_OFF); } #define PWDN_GPIO 6 // 電源断通知GPIO番号 int main(int argc, char *argv[]) { int retval = 0; int fd; char buf[256]; char c; if(! initGpio(PWDN_GPIO) ) { error("GPIO cant be initialized\n"); return 0; } // GPIOオープン sprintf(buf,"/sys/class/gpio/gpio%d/value", PWDN_GPIO ); fd = open(buf, O_RDONLY); if(fd < 0) { error("Value cant opened"); return 0; } // 空読み read(fd, &c, 1); while(1) { struct pollfd pfd; pfd.fd = fd; pfd.events = POLLPRI; pfd.revents = 0; // GPIO fallingイベント待ち lseek(fd, 0, SEEK_SET); int r = poll(&pfd, 1, -1); fputs("Power down detected\nWait for 5 seconds\n", stdout); // 5秒待つ sleep(5); read(fd, &c, 1); if( c == '0' ) { close(fd); deinitGpio(PWDN_GPIO); fputs("Shutdown now\n",stdout); retval = shutdown(); break; } } return retval; } |
図4 /etc/systemd/system/adrszup.serviceファイルの内容
1 2 3 4 5 6 7 8 9 10 11 12 |
[Unit] Description=Auto shutdown process for ADRSZUP [Service] Type=simple Restart=no User=root ExecStart=/usr/local/bin/ADRSZUP [Install] WantedBy=multi-user.target |