The goalMake a gpio interrupt in kernel space, send signal to any program.
UsabilityEducational. Hardware ultra-kill button.
With this code, you can connect 'some thing' to gpio pin which gives an impulse (button, clock, whatever), and High-to-Low on this gpio pin will send signal to any pid on your system.
For example, you can send SIGKILL(9) to some pid, by pressing button connected to gpio pin.
m_gpioSignal has 2 parameters:
gpio_pin // default value is 17and
signal_to_pid // default value is 34If you want to change this, load module with parameters:
pi@raspberrypi ~/progs/cpp/gpioSignal $ sudo insmod m_gpioSignal.ko gpio_pin=27 signal_to_pid=35After module is load, special device is registred in '/dev' directory. You must create it from root by command displayed in /var/log/messages.
pi@raspberrypi ~/progs/cpp/gpioSignal $ sudo insmod m_gpioSignal.ko pi@raspberrypi ~/progs/cpp/gpioSignal $ tail -n 2 /var/log/messages May 1 20:07:25 raspberrypi kernel: [ 2198.765275] Info: signal_to_pid is 34, gpio_pin is 17 May 1 20:07:25 raspberrypi kernel: [ 2198.765303] 'mknod /dev/m_gpioSignal c 248 0' pi@raspberrypi ~/progs/cpp/gpioSignal $ pi@raspberrypi ~/progs/cpp/gpioSignal $ sudo mknod /dev/m_gpioSignal c 248 0And enable write by others.
pi@raspberrypi ~/progs/cpp/gpioSignal $ sudo chmod o+w /dev/m_gpioSignalTo set pid to which signal will be send, just write it to device. Now you can do it as a regular user.
echo "2117" > /dev/m_gioSignalOn kernel messages in /var/log/messages you will see:
May 1 20:12:43 raspberrypi kernel: [ 2516.988983] send_to_pid set: 2117After this, interrupt flag is enabled and if High-to-Low occurs on gpio17, signal 34 will be send to pid 2117, and interrupt flag will be disabled until pid will be again written to device.
May 1 20:14:19 raspberrypi kernel: [ 2613.210739] Signal 34 was send to pid 2117
User space application
User space program is very simple, it send his own pid to /dev/m_gpioSignal device, and then attach own function to signal 34.
When signal arrives (High-to-Low on gpio pin 17), function is executed and pid is written to device once again (to enable interrupt).
Interrupt in kernel is active all time. By writing and executing interrupt we only enable/disable own flag so you must be sure, that your trigger (clock, button etc.) is not generating noise. If you use a button gpio pin should be pulled-up to 3.3V from raspberry pi.
I did small performance test, to check how much time last from falling edge on GPIO pin to user space function call. User space application was extened and now after every signal sets GPIO pin 22 to HIGH (bcm2835_gpio_write) for about 10us, so I can measure time between falling edge on GPIO pin 17 and HIGH state on GPIO pin 22.
Atmega32, connected to Raspberry, triggers an interrupt on GPIO pin 17 by generating falling edge condition HIGH->LOW on pin PD5.
- Raspberry Pi is under load of:
- 7 ssh client sessions
- transmission-daemon (idle)
- mpd (playing audio stream from http)
- two while(true); do true; done; loops
- vim x 3
- tail -f /var/log/messages
- our user space application
- PD5 pin is connected to Raspberry's GPIO pin 17
- every 250us flips PD5 state, HIGH, LOW in endless loop
- Oscilloscope connected to Raspberry:
- First channel is connected to GPIO pin 17
- Second channel is connected to GPIO pin 22
On several trials, average time was close to 130us, even just before freeze - I've generated to much load on other sessions. We could assume, that heavy load has less impact in our test. But remember, that we've generated only CPU load, IO (SD card) was untouched.
However 5% on 100 samples was completely out of timing, 460us, 690us even 1.8ms.
|Average time from falling edge on gpio pin to user space function call.|
I do not know how to assess the reliability of this test, so let's treat this only as an approximation.
User space function body had bcm2835_gpio_write at first line, if we put something more before it, the INT->SIGNAL delay will be much bigger.