To make the difference between reading the line to detect a change of state and using the events, let’s consider another version of our button program given earlier. In this case the GPIO line is set up for input and a message to press the button is printed. Then the program waits for 20 seconds and finally tests the state of the line. Even if the user has pressed the button lots of times during the 20 seconds, all that matters is the final state of the line as read when the sleep(20) ends:
In this case the GPIO line is set up as an output with a pull-up and it fires an event on the falling edge of a signal. Notice that now the if statement tests not the state of the line, but the state of the event flag. The difference is that if the user presses the button at any time during the 20-second sleep, the flag is set and the program registers the button press. The flag is set no matter what the program is doing, so instead of sleeping it could be getting on with some work, confident that it won’t miss a button press. However, it cannot know exactly when the button was pressed and it cannot know how many times the button was pressed.
Events allow you to avoid missing a single input while polling, but cannot handle multiple inputs. You could implement a full queue-based event handling system, but this would only make sense on a multi-core machine like a Pi 4 and with the thread running the event detection locked into a separate core from the rest of the program. This probably isn’t worth the effort. A more reasonable alternative is to use the interrupt abilities of the GPIO character driver.
In chapter but not in this extract:
Interrupts And The GPIO Character Driver
An Interrupt Function Using A Thread
How Fast Is An Interrupt?
Events are a stored indication that something happened.
Interrupts are events that cause something to happen.
You can use an event with a polling loop to protect against missing input because the program is busy doing something else.
If an event occurs before the current event has been cleared then it might be missed. To avoid missing events, you can use an event queue which stores events in the order they happened until they are processed.
The BCM 2835 library supports GPIO events. You can enable a bit to be set if a GPIO line goes high, low or is high or low. Edge-triggered events are the easiest to work with.
If you use events then you have to turn off GPIO generated event handling or they system will crash.
Using events in a polling loop hardly slows things down at all.
You can use events to generate an interrupt that you can wait for using an epoll. To do this you need to use the GPIO character driver to provide the file that the epoll waits on.
The use of the GPIO character driver slows things down a lot.
When using epolls the thread simply waits for the interrupt to occur. If you want to continue processing until the interrupt occurs then you have to wait for the interrupt on a new thread. This is slow but it is the closest approach to a true interrupt that user mode allows.
The gpiod library has some commands that will wait for an event to occur and report the time stamp of the event.
Overall events are useful, but interrupts are not. Neither increases the throughput of a polling loop and an interrupt only decreases response time if the event is infrequent.
Although it didn't launch until 1985, Microsoft Windows was announced in November 1983. It signaled the move for users from the command line to a GUI environment, something that some programmers still [ ... ]