How to Use Interrupts to Handle Events Without Constant Polling

Polling is often the first tool firmware engineers use to detect events in their system. An always-running loop checks a pin or register and reacts when it changes. While this may work for simple board bring-up, polling loops are insufficient for a production system that requires high performance with limited resources. Polling wastes CPU time, increases power draw, and prevents the system from scaling.

Interrupts solve all of these problems. They work by letting the hardware notify the firmware exactly when something happens. Instead of continuously checking inputs, the microcontroller can sleep until an interrupt triggers. Interrupts allow the system to conserve its resources until it’s required to work, reducing power consumption and enabling engineers to scale their embedded systems efficiently.

In this guide, you’ll learn how interrupts work on the Texas Instruments CC2340 series and Nordic Semiconductor 54 L series development boards, and test them on these boards with existing sample code.

Why Replace Polling With Interrupts

Polling’s responsiveness to events heavily depends on the speed of the constantly running loop. If the polling loop runs slowly, you’ll experience increased latency and system delays. If the polling loop runs quickly, you’ll see increased power consumption. Interrupts allow you to bypass this impossible tradeoff entirely. Your hardware detects the signal edge on its own and invokes a handler immediately, regardless of what the main loop is doing.

Modern wireless embedded systems depend heavily on interrupts. Radios, timers, sensors, and GPIO events all rely on hardware-driven wakeups rather than continuous microcontroller activity. Once you start to use interrupts, your firmware naturally becomes event-driven rather than cycle-driven, making it more robust and adaptable.

Interrupt Examples on TI and Nordic Boards

The best way to learn about interrupts is to see them in action on your development board. Luckily, both the TI CC2340R5 LaunchPad and Nordic nRF54L15 boards have onboard buttons and LEDs connected directly to the microcontroller’s GPIO pins. With sample code from both vendors’ SDKs, you can test interrupts without any external hardware or wiring.

You will see the same workflow for both boards:

Press button -> Trigger interrupt -> LED responds (turns on or off)

In the sections below, you will learn more about how each board handles interrupts through their respective sample applications.

TI CC2340R5 Example

The TI CC2340R5 SDK comes with a GPIO interrupt sample application. It configures the onboard buttons BTN-1 and BTN-2 as interrupt sources and toggles different LEDs inside each callback. You can use it as-is to test interrupts on your board.

In TI’s Code Composer Studio, open the gpiointerrupt project. Build and flash this firmware onto your board. Once that completes, you should be able to press either BTN-1 or BTN-2 and see the corresponding onboard LED toggle on or off.

Test BTN-2

Below is an example of what you would see if you pressed BTN-2.

TI CC2340R5 LaunchPad with LED off before button press
TI CC2340R5 LaunchPad with green LED toggled on after pressing BTN-2

What actually happens behind the scenes? The sample project’s SysConfig maps BTN-2 to the associated interrupt service routine (ISR) and enables the interrupt automatically. When you press BTN-2:

  1. Hardware detects the falling edge from the button
  2. NVIC triggers the GPIO interrupt
  3. ISR executes
  4. Green LED toggles state
// BTN-2 ISR
void gpioButtonFxn1(uint_least8_t index)
{
    // Toggle an LED
    GPIO_toggle(CONFIG_GPIO_LED_1);
}

The result is that every time you press the button, the LED flips from off to on, or on to off. In between button presses, the microcontroller sleeps, waking only for the interrupt. No polling loop checks the button state.

Nordic nRF54L15 Example

The nRF Connect SDK includes a sample GPIO interrupt application called Button. Similar to the TI application, it configures the onboard BUTTON 0 as an interrupt source and toggles LED0 inside the callback. You can use it as-is to test interrupts on your board.

In nRF Connect, load the Button application from samples/basic/button. Add the appropriate build configuration, then build and flash this firmware onto your board. Once that completes, you should be able to press BUTTON 0 and see LED0 turn on.

Nordic nRF54L15 board with LED0 off before button press
Nordic nRF54L15 board with LED0 on while BUTTON 0 is pressed

Behind the scenes, the interrupt fires upon button press and turns the LED on. A corresponding release event in the main loop turns the LED off. The result is that the LED only stays on while you are actively pressing the button, rather than toggling between presses. Below are some key excerpts from the sample code that make this happen.

// Button 0 ISR
static void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
    // Turn on LED0
    gpio_pin_set_dt(&led, 1);
}

// Interrupt trigger
gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);

Like the TI example, the microcontroller sleeps most of the time and wakes only for interrupts. No polling occurs here either.

Common Interrupt Flow

Despite using different SDKs and LED behavior, both sample interrupt applications share the same overall design:

Hardware

  • GPIO configured with edge detection
  • Interrupt routed to the NVIC

ISR

  • Minimal handler
  • Update LED state

Main loop

  • Idle or sleep
  • No polling

This consistency across board types is why firmware interrupts can easily scale across platforms.

Wrapping Up

Polling works for small tests, but it wastes power and does not scale well. Interrupts fix this by letting the microcontroller sleep until hardware signals trigger code execution. The TI CC2340R5 and Nordic nRF54L15 SDKs both include ready-to-run button-interrupt sample applications that showcase this event-driven approach.

The TI sample toggles the LED on each press, while the Nordic sample lights the LED only while the button is held. Despite this difference, both use the same interrupt flow. The microcontroller sleeps until a button edge occurs, after which it wakes up, runs a small handler, and returns to idle. Once you understand this GPIO interrupt pattern, you can apply it to sensors, radios, motion signals, timers, and other hardware events, all of which form the basis of responsive, low-power IoT firmware.


Ready to connect your devices anywhere on Earth? Get started with Hubble Network for free →