著者:米田聡
小型コンピュータボード「Raspberry Pi」(ラズパイ)向けにさまざまな拡張ボードが発売されています。その拡張ボードとラズパイを組み合わせれば、ラズパイでいろいろなことが簡単に試せます。第3回は、電源断でもラズパイを正常終了するための拡張基板を扱います。
シェルスクリプトマガジン Vol.70は以下のリンク先でご購入できます。![]()
![]()
図3 ADRSZUPコマンドのソースコード(ADRSZUP.c)
#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ファイルの内容
[Unit]
Description=Auto shutdown process for ADRSZUP
[Service]
Type=simple
Restart=no
User=root
ExecStart=/usr/local/bin/ADRSZUP
[Install]
WantedBy=multi-user.target