我想通过将 GPIO 引脚拉低 10 秒来表示电源关闭状态。我在 /etc/rc.* 目录中发现了运行级别。最终,“停止”命令开始运行。
我想编辑并重新编译halt.c 文件,但我找不到它。我有两个问题:
- 这是正确的方法吗?
- 源代码在哪里?(等待 Q1 的肯定回答)。
谢谢你。贾斯汀
我想通过将 GPIO 引脚拉低 10 秒来表示电源关闭状态。我在 /etc/rc.* 目录中发现了运行级别。最终,“停止”命令开始运行。
我想编辑并重新编译halt.c 文件,但我找不到它。我有两个问题:
谢谢你。贾斯汀
我没有使用过 Raspberry Pi,但在大多数系统上halt、poweroff和reboot都是指向同一个二进制文件的链接。另一种方法是编写一个程序来做你想做的事,并使它成为在 /etc/rc.d/rc0.d 中调用的最后一件事。 运行级别 0是系统关闭时执行的操作。
这是我对这个问题的看法'powerctl_pin' https://pastebin.com/BdzGM5TJ
/*
Raspi3B Power Control Pin Raspbian Jessie
Bilgus -- 2017 CC-BY-SA 3.0
Requires WiringPI http://wiringpi.com/
Compiling:
gcc -o powerctl_pin powerctl_pin.c -l wiringPi && chmod +x powerctl_pin &&
sudo cp powerctl_pin /bin/
Install:
sudo /bin/powerctl_pin 21 install
Uninstall:
sudo /bin/powerctl_pin 21 uninstall
Shutdown:
sudo /bin/powerctl_pin 21 poweroff
/bin/powerctl_pin Broadcom_pin#, mode
Valid Modes: poweroff, poweron, install, uninstall
Works with mosfet latch switch
https://easyeda.com/Bilgus/New_Project-4ce1316bb1f6402985f8d1c4f196448d
Original Circuit:
http://www.mosaic-industries.com/embedded-systems/microcontroller-projects
/raspberry-pi/on-off-power-controller
*/
/*
Raspi3B Power Control Pin Raspbian Jessie
Bilgus -- 2017 CC-BY-SA 3.0
Requires WiringPI http://wiringpi.com/
Compiling:
gcc -o powerctl_pin powerctl_pin.c -l wiringPi && chmod +x powerctl_pin &&
sudo cp powerctl_pin /bin/
Install:
sudo /bin/powerctl_pin 21 install
Uninstall:
sudo /bin/powerctl_pin 21 uninstall
Shutdown:
sudo /bin/powerctl_pin 21 poweroff
/bin/powerctl_pin Broadcom_pin#, mode
Valid Modes: poweroff, poweron, install, uninstall
Works with mosfet latch switch
https://easyeda.com/Bilgus/New_Project-4ce1316bb1f6402985f8d1c4f196448d
Original Circuit:
http://www.mosaic-industries.com/embedded-systems/microcontroller-projects
/raspberry-pi/on-off-power-controller
*/
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <signal.h> //sigterm, sigint()
#include "wiringPi.h"
#define WIRINGPI_CODES 999 /* enable error checking on setup */
#define POWEROFF_SVC "PwrCtl_Pin.service"
#define POWEROFF_SVC_PATH "/lib/systemd/system/"POWEROFF_SVC
#define REQUIRES "shutdown.target umount.target final.target poweroff.target"
#define AFTER "shutdown.target umount.target final.target"
#define BEFORE "systemd-poweroff.service"
#define WANTEDBY "poweroff.target"
#define POWERINT_SVC "PwrCtl_Pin-Interrupt.service"
#define POWERINT_SVC_PATH "/lib/systemd/system/"POWERINT_SVC
static void poweroff_ISR_INIT(int pin);
static int g_pin = 0;
/* enables pullup - unneeded to hold latch */
static void poweron_pin(int pin)
{
pullUpDnControl(pin, PUD_UP);
pinMode(pin, INPUT);
}
/* pulls pin low in short loop to turn power off */
static void poweroff_pin(int pin)
{
pullUpDnControl(pin, PUD_OFF);
int c;
for(c=0;c<20;c++)
{
//pinMode(pin, INPUT);
//pullUpDnControl(pin, PUD_DOWN);
digitalWrite(pin,LOW);
pinMode(pin, OUTPUT);
digitalWrite(pin,LOW);
delay(500);
}
}
/* ISR Called when pin goes from high to low debounce checks that still low */
static void poweroff_ISR(void)
{
delay(100);
if (digitalRead(g_pin) == LOW) /* pin debounce */
{
openlog ("Poweroff ISR", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
syslog (LOG_NOTICE, "ISR Triggered - Shutdown -h now");
closelog();
system("shutdown -h now");
exit(0);
}
else
poweroff_ISR_INIT(g_pin);
}
/* signal handler recieves shutdown signals */
static void signal_handler(int signal_0)
{
if (signal_0 == SIGINT || signal_0 == SIGTERM || signal_0 == SIGSTOP)
exit(0);
}
/* Initialize Poweroff ISR handler */
static void poweroff_ISR_INIT(int pin)
{
g_pin = pin;
pinMode(pin, INPUT);
pullUpDnControl(pin, PUD_UP);
wiringPiISR(pin, INT_EDGE_FALLING, &poweroff_ISR);
while(1)
{
delay(100);
;;
}
}
/* creates service daemons */
static void install(int pin, char *prog_path)
{
FILE *f = fopen(POWEROFF_SVC_PATH, "w");
if (f == NULL)
{
fprintf(stderr, "Error opening file! %s\n", POWEROFF_SVC_PATH);
exit(-6);
}
fprintf(f, "# POWER CONTROL PIN SERVICE \n# %s\n\n", prog_path);
fprintf(f, "[Unit]\nDescription=PowerCtl_Pin pulls GPIO pin %i LOW\n", pin);
fprintf(f, "DefaultDependencies=no\n");
fprintf(f, "Requires=%s\n", REQUIRES);
fprintf(f, "After=%s\nBefore=%s\n\n", AFTER, BEFORE);
fprintf(f, "[Service]\nType=oneshot\n");
fprintf(f, "ExecStart=%s %i poweroff\n\n", prog_path, pin);
fprintf(f, "[Install]\nWantedBy=%s\n\n", WANTEDBY);
fclose(f);
printf("Service file created: %s\n", POWEROFF_SVC_PATH);
system("systemctl enable " POWEROFF_SVC);
FILE *f1 = fopen(POWERINT_SVC_PATH, "w");
if (f1 == NULL)
{
fprintf(stderr, "Error opening file! %s\n", POWERINT_SVC_PATH);
exit(-7);
}
fprintf(f1, "# POWER CONTROL PIN INTERRUPT SERVICE \n");
fprintf(f1, "# %s\n\n", prog_path);
fprintf(f1, "[Unit]\nDescription=PowerCtl_Pin Interrupt watches GPIO ");
fprintf(f1, "for pin %i LOW calls shutdown now\n", pin);
fprintf(f1, "DefaultDependencies=no\n");
fprintf(f1, "After=network.target\n\n");
fprintf(f1, "[Service]\nType=simple\n");
fprintf(f1, "ExecStart=%s %i interrupt &\n", prog_path, pin);
fprintf(f1, "TimeoutSec=0\nRestart=always\n\n");
fprintf(f1, "[Install]\nWantedBy=multi-user.target\n\n");
fclose(f1);
printf("\n\rService file created: %s\n", POWERINT_SVC_PATH);
system("systemctl enable " POWERINT_SVC);
printf("Attempting to start: %s\n\r", POWERINT_SVC_PATH);
system("systemctl start " POWERINT_SVC);
}/*install*/
/* disables/stops service daemons */
static void uninstall(int pin, char *prog_path)
{
system("systemctl disable " POWEROFF_SVC);
printf("Service file still exists: %s\n\n", POWEROFF_SVC_PATH);
system("systemctl stop " POWERINT_SVC);
system("systemctl disable " POWERINT_SVC);
printf("Service file still exists: %s\n", POWERINT_SVC_PATH);
}
int main(int argc, char **argv)
{
int pin = 0;
if (geteuid() != 0)
{
fprintf (stderr, "You need to be root to run this program. (sudo?)\n") ;
exit(-1);
}
putenv("WIRINGPI_CODES=WhOkNoWs??");
if (wiringPiSetupGpio() != 0) /* change to wiringPiSetup() for WiringPi Pins*/
{
fprintf(stderr, "wiringPiSetup error\n");
exit(-2);
}
if(argc < 3)
{
fprintf (stderr, "not enough args poweroff_pin(brcm_pin# mode)\n") ;
fprintf (stderr, "Valid Mode [power[off/on], interrupt, install, uninstall]])\n") ;
exit(-3);
}
else if (sscanf (argv[1],"%i", &pin) != 1)
{
fprintf (stderr, "invalid pin number, poweroff_pin(brcm_pin# mode) ");
fprintf (stderr, "Valid Mode [power[off/on], interrupt, install, uninstall]])\n") ;
exit(-4);
}
else if(strncmp(argv[2],"interrupt",10) == 0)
{
openlog (argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
syslog (LOG_NOTICE, "%s - interrupt mode pin = %s", argv[0], argv[1]);
closelog();
if (signal(SIGINT, signal_handler) == SIG_ERR)
{
fprintf(stderr, "Unable to register signal handler\n");
exit(-5);
}
poweroff_ISR_INIT(pin);
}
else if(strncmp(argv[2],"poweroff",10) == 0)
{
poweroff_pin(pin);
}
else if(strncmp(argv[2],"install",10) == 0)
{
openlog (argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
syslog (LOG_NOTICE, "%s - install pin = %s", argv[0], argv[1]);
closelog();
install(pin, argv[0]);
}
else if(strncmp(argv[2],"uninstall",10) == 0)
{
openlog (argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
syslog (LOG_NOTICE, "%s - uninstall pin = %s", argv[0], argv[1]);
closelog();
uninstall(pin, argv[0]);
}
else
{
poweron_pin(pin);
}
return 0;
}/*main*/