Blink: CHIP program to blink status light and shut down when reset button is pressed


#1

Since CHIP runs Linux, it should be shut down gracefully, not abruptly by removing power or a hard reset. But CHIP is often used as an embedded system without any user interface. In those cases, it can be difficult to know if it has successfully booted, and is difficult to trigger a graceful shutdown. This program solves both problems.

When started by at boot time, the blinking status LED indicates a successful boot. Its continuing blinking indicates that CHIP hasn’t crashed.

When the reset button is briefly pressed, the blink program will initiate a graceful shutdown. DO NOT PRESS AND HOLD THE RESET BUTTON! That cuts power without a graceful shutdown.

Blink is now more flexible than before. It can blink an external LED (or whatever) on a GPIO output pin, either instead of or in addition to CHIP’s status LED. It can also monitor an external button (or whatever) on a GPIO input pin, either instead of or in addition to CHIP’s reset button. It can also add monitoring the battery charge level so that it does a graceful shutdown when the battery level goes below a given percentage. It can also monitor the AXP209’s temperature and do a shutdown when it exceeds a threshold. Finally, both battery and temperature monitoring can configure a warning threshold and trigger a configured GPIO.

Since blink can be disabled from monitoring the reset button, I think it is more PocketCHIP-friendly now.

You can find blink at: https://github.com/fordsfords/blink/tree/gh-pages

(Edited to reflect new version.)


C.H.I.P. fails to boot after weeks of uptime and flash fix applied
Adventures in Circuitry: The service LED
Initial problems and observations (mostly os & kernel related)
Fun facts about CHIP!
Commands and libraries for manipulating IO and serial port in C
[SOLVED]Why is CHIP so tempermental?
HOW-TO compile Chip's Linux kernel and modules on Chip itself
Starting point for a complete newb?
How to configure reset button?
Installing VNC on CHIP
Status Light Functionality
Is there an RTC?
Graceful shutdown v.s. power off
[SOLVED] Waiting for FEL error while flashing with live linux USB Ubuntu 15
Minty plastic case
Soldering to the bottom of headers
Q: Totally Cut the power of CHIP? [SOLVED]
#2

Looks great, TY! Much better then starting a VNC/ssh session, running sudo shutdown, waiting for LED off to finally unplug before I can use my cellphone charger again.
I’m a Linux noob, so. Why do I have to compile it myself?
@computermouth And why is CHIPs power button not used for exactly this?


#3

I’m sincerely curious as to why write this is in C vs a [Shell] Script, other than to exercise C skill or reduce overhead just a bit.

I would naturally want to knock this out with a script and be done with it - no pointers, strfmt, type declarations, etc. being such a perfect simple solutions for an important problem.

  1. It will be running as root anyway - unless you want to be able to SetUID for root. But again it’s set to run in root’s crontab . Having a while loop, it might be better as a system startup script and it can start sooner then too.
  2. Shell can /bin/cat and echo /proc/ and /sys/ file handles
  3. To further reduce scripting overhead (thought not as small as C) - so Shell isn’t spawning binaries constantly - it could leverage busybox (ash, cat, echo, etc.) or another language such as Lua.
  4. Since i2cset has to be externally called, that adds to overhead being a child process unless the C program was re-written to use the shared I2C libraries.

Here’s what I mean. This does the same thing:

#!/bin/sh

gpio=/sys/class/gpio
gpio415=${gpio}/gpio415
sec=1 # seconds to sleep - ease of altering
flip=2 # modulus for seconds to achive flip-flop

ledon='/usr/sbin/i2cset -f -y 0 0x34 0x93 0x1'
ledoff='/usr/sbin/i2cset -f -y 0 0x34 0x93 0x0'

# export XIO-P7. set for input
[[ ! -e ${gpio415} ]] && echo '415' > ${gpio}/export

[[ $(cat ${gpio415}/direction) != "in" ]] && echo 'in' > ${gpio415}/direction

while true
do
  [[ $(cat ${gpio415}/value) != "1" ]] && break

  (( flop = $(date +%S) % ${flip} ))
  [[ ${flop} -eq 0 ]] && $ledoff || $ledon

  sleep ${sec}
done

echo '415' > ${gpio}/unexport # may not be necessary. here to be clean.

/sbin/shutdown now

And for those folks without a switch, just use jumper or paperclip between gnd next to XIO-P7 (same jumper I used for flashing :smiley: )


#4

The chip does come equipped with its own power button. There is very likely a way to map the power button to any script we want and then we might not even have to monitor anything(at least not something that isn’t already monitored one way or another by the system).


#5

The biggest reason? I’m a C programmer. :slight_smile:

You mentioned overhead, which is one advantage over shell, but not significant in this case. But another advantage (not used in this program) is the ability to set the executable to “SUID root”. This allows non-root accounts to access privileged resources, like /proc/ and /sys/. I have a different project that allows a web browser to turn the status LED on and off, and that project does make use of SUID root.

But more than anything else, I want to write C code for CHIP, and this was a good introductory project.

I did consider writing to the I2C libraries, but I wanted a solution reasonably quickly. I’ll probably look at those libraries in the near future, and may re-write this program to use them.


#6

I have not been able to locate any hooks yet for the power button. I must be missing something… has anyone else located somewhere to hook into the power button press event?

I did however stumble across another solution for using an external button(which in all fairness is well documented). If you use your button between PWRON (U13 Pin 10) and GND (I used U13 Pin 12) you can turn off (and turn on!!!) the chip without any add-on programs. You can still run your blink program to show you the system has not crashed, just remove the GPIO related code.


#7

Does it do a graceful shutdown?


#8

I neglected to address your question. There’s kind of three answers, which I will provide in the form of an imagined conversation.

SF: You have to compile the program because it is written in C, and C programs need to be compiled to machine code before you can run them.

CS: Why did you write it in C? Writing it in shell, perl, python, etc would allow a user to just download and run without first installing gcc.

SF: I wrote it in C because I wanted to. This is my hobby. :slightly_smiling:

CS: OK, I can see that. But why not put up the binary as well?

SF: I … um … Hey, is anybody else hungry? I’m hungry! Let’s go get a pizza!

CS: Steve? Hello?

UPDATE: I’ve since uploaded the binary to the github project.


#9

If I read all the code properly. From what I can tell it runs the shutdown command, same as your program. I believe the actual syntax was:

shutdown -H now

I did not have any displays or connections open at the time of jumpering PWRON to GND but it took about 5 or so seconds to have the lights go out (it wasn’t instantaneous) which is comparable to sending the command via ssh. I don’t think it just cut the power out.


#10

Isn’t this a serious security flaw? Am I missing something here?


#11

I believe the shutdown command defaults to powering off. The “-H” is optional.

As for PWRON to GND, I tried it and compared it to entering shutdown. The “/var/log/syslog” file shows the differences. A graceful shutdown logs many messages tracing the progress of various services stopping. Using PWRON doesn’t trigger any messages to syslog.

I think PWRON is the same as the little button, and they are like the power switch on a laptop: pressing it momentarily does not shut it down, but holding it down for some number of seconds forces power off. Used when the system becomes unresponsive.

So neither the button nor PWRON does a clean shutdown.

All that said, I don’t know if there is a software method fo reading the button before it forces a power off.

Steve

P.S. - if you experiment with it and examine the syslog file, I believe you will find some initially confusing results. Syslogd is an interesting service that buffers messages and tries very hard to make sure they are all recorded. After an ungraceful reboot, syslogd will try to recover messages from the buffer, and often ends up writing blocks of messages twice. You can see evidence of it by looking at the timestamps; you can see time jump backwards. This typically only happens after an ungraceful shutdown.


#12

It would be a serious security flaw if an unprivilaged user could enable “SETUID root” on an executable. But only root can do that.

Consider the following:

chip@chip:~$ which ping
/bin/ping
chip@chip:/bin$ ls -l /bin/ping
-rwsr-xr-x 1 root root 34752 Nov  8  2014 /bin/ping

Note the “s” in “-rws…”. That means “SETUID” is enabled. The owner if the file is root. So when a normal user executes “ping”, the program runs as root. When it completes and returns to the user, it removes root privilege. The reason ping needs to be “SUID root” is that it access the network interface in low-level ways which is not allowed for normal users.

So why is this not a severe security hole? Because the authors of “ping” made sure that it can’t be used in dangerous and damaging ways.

But consider this:

chip@chip:/bin$ which rm
/bin/rm
chip@chip:/bin$ ls -l /bin/rm
-rwxr-xr-x 1 root root 38640 Mar 14  2015 /bin/rm

Instead of “-rws…” it’s “-rwx…”. It’s an executable withOUT “SETUID”. This is critical! If the “rm” command ran as root, you could delete any file and render the system unusable.

So SETUID needs to be used rarely and with great care. Only 4 programs in /bin have it. Only users who already have root access are allowed to grant SUID. So never grant it to any program that you don’t fully trust.


#13

For the shutdown command, the man shutdown on debian indicates -P, --poweroff is the default. -H, --halt is optional. But -h is equal to --poweroff unless --halt is specified.

You could also use poweroff or the classic init 0 – all perfectly fine under Linux.

The great thing about using shutdown is:

  1. with -k you can issue a system wide console message to all open terminals
  2. if used with a time delay like +10, you can issue a shutdown -c before the reboot to cancel the shutdown command.

If you’re curious about details of shutdown vs poweroff vs reboot vs init 6 or init 0, you should check out StackExchange. That used to be (still is) a big issue for legacy Unix systems - but not really an issue for Linux hosts for some time. If ever in doubt, you’re safest best is to init 6 for reboots or init 0 for shutdowns - but that won’t get you any features of the shutdown command.

Cheers, Mark S.


#14

Thanks for the kick in the @ss. I did and found it instructive.

One thing it reminded me of is that there are two kinds of problems that can happen if you frequently do non-graceful shutdowns of your CHIP:

  1. Possible file system corruption due to kernel buffers not being properly flushed and dismounted.
  2. Application-level corruption due various daemons not saving internal state (either user-mode buffers maintained by buffered I/O calls, or application data that needs to be written).

There’s a way to do a semi-graceful shutdown (using a “force” flag) which is nice and fast and does avoid #1, but still leaves you vulnerable to #2. So the preferred method is fully-graceful.

The (very rare) risk of a fully-graceful shutdown is that it is possible for it to hang during the cleanup phase (it happened to me earlier this week on a very sick server at work). So to be maximally safe, one should first do a graceful shutdown, and if it takes too long, do a forced shutdown. I may work that into my “blink” program.


#15

OK, tried to get this to work but all I get is -./bld.sh: command not found.
I have installed gcc make and build essentials, am I missing something?


#16

Got it working by running sudo gcc -o /usr/local/bin/blink blink.c
Then worked out it was a permission thing. chmod +x bld.sh fixed it.


#17

DOH! I always forget that! I will update the quickstart guide. Thanks!

BTW, if you look higher up, you will see a pure shell script method of accomplishing the same thing. I don’t know if it is fully-baked, but it does avoid the whole “gcc” thing.


#18

FYI - I updated the blink project. It now includes a pre-compiled binary, so you don’t have to build it yourself. There are several minor improvements as well.


#19

Is halt only a shortcut for shutdown now -H?


#20

Google it and become as confused as the rest of us. :slight_smile: It appears to depend on the flavor of Unix, the distro of that flavor, and the time frame of that distro. My vague recollection is that halt does a graceful kernel shutdown, but does not send kill signals to processes to allow them to clean themselves up first. Thus, you are protected from actual disk corruption, but at your next startup you could have processes come up and say, “all right, where was I?” and get incorrect information. Well-written applications are generally able to handle that reasonably well (e.g. “vi” saves a journal that can be replayed), but it’s just plain better to do a “fully” graceful shutdown.