Interrupts: responding to events
Let the hardware call your function when an event occurs, and follow the rules that keep this safe.
Explanation
So far, the main loop checks everything by asking repeatedly: is the button pressed, has a byte arrived. This is called polling, and it fails when the loop is busy or the event is short. An interrupt reverses this: the hardware pauses the main loop, runs a function of yours called an interrupt handler or ISR, and then resumes the loop exactly where it stopped.
On Cortex-M, a handler is an ordinary C function with a fixed name that comes from the chip maker's startup file, such as TIM2_IRQHandler or EXTI0_IRQHandler on STM32. It takes no arguments and returns nothing. You enable the interrupt in the peripheral and in the NVIC, the interrupt controller, and from then on the hardware calls the handler.
The main design rule is to keep the handler short. Record what happened, set a flag or put a byte in a buffer, then return. Do the slow work in the main loop. Anything that waits inside a handler, such as a delay or a printf over a slow UART, stalls every interrupt at the same or lower priority, and often the whole system.
A flag that a handler sets and the main loop reads must be declared volatile. Without volatile, the compiler may read the flag once into a register and never read memory again, so the loop waits forever for a value the handler has already changed. Volatile tells the compiler that the value can change outside the normal program flow and must be read from memory every time. It does not make anything atomic; atomicity is a separate topic.
Key points
- Polling asks repeatedly. An interrupt is the hardware calling your function.
- A handler is a void function with no parameters and a fixed name.
- Keep handlers short: record the event, and do the work in the main loop.
- A flag shared with a handler must be volatile, so every read goes to memory.
Check your understanding
4 questions on this lesson. An explanation follows each answer.
Sign in to answer the questions. Your answers count towards your level.
You can read the lesson and the project without an account.
Project
Button interrupt and a reaction timer
What you need
- Your board, the debounced button and the LED.
- Serial output working.
Steps
- 1Configure the button pin to raise an interrupt on the falling edge. In the handler, only set a volatile flag and record the millisecond tick.
- 2In the main loop, when the flag is set, clear it. If the recorded tick is within 30 ms of the previous accepted press, ignore it: this is the contact bounce from lesson 3 arriving as several interrupts. Otherwise, print the time and toggle the LED. Confirm that a press is detected even while the loop is busy in a long delay.
- 3Build a reaction timer: switch the LED on after a random delay, then measure the time until the button interrupt fires. Print it in milliseconds.
- 4Remove the volatile keyword, build with optimization enabled, and check whether the program still responds. Then restore the keyword.
Done when
The reaction time prints correctly, the handler contains no delay and no print, and you have seen what happens without volatile.