Вытяните штифт GPIO как последний акт до выключения

Я хочу сигнализировать о состоянии выключения питания, потянув вывод GPIO на 10 секунд. Я обнаружил уровни запуска в каталогах /etc/rc.*. В конце концов команда "остановка" запускается.

Я хотел бы отредактировать и перекомпилировать файл halt.c, но я не могу его найти. У меня есть два вопроса:

  1. Это правильный подход?
  2. Где находится исходный код? (в ожидании положительного ответа от Q1).

Спасибо. Джастин

2 ответа

Я не использовал Raspberry Pi, но в большинстве систем останов, выключение и перезагрузка - это ссылки на один и тот же двоичный файл. Еще один способ сделать это - написать программу, которая будет выполнять то, что вы хотите, и сделать ее последним, чтобы вызываться в /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*/

Другие вопросы по тегам