Skip to content

Concepts First

  • Interrupt (EXTI): like a doorbell — when the event happens, the chip stops what it is doing to respond, then resumes; no need to keep watching the pin (polling).
  • Trigger mode: falling edge (high→low), rising edge (low→high), low level, or high level. A button grounded produces a falling edge.
  • Interrupt callback: the system calls your registered function when triggered (this example prints Interrupt Trigger!); keep it short.

Example Overview

This page is based on the gpio_interrupt example in the official Bouffalo SDK (examples/peripherals/gpio/gpio_interrupt), which demonstrates GPIO external interrupts (EXTI):

  • The serial shell command gpio_int_test <gpio> <mode> configures a pin as an interrupt input;
  • 4 trigger modes are supported: 0 falling edge, 1 rising edge, 2 low level, 3 high level;
  • When the pin change meets the trigger condition, the interrupt callback runs and prints Interrupt Trigger!.
  • Sibling examples (examples/peripherals/gpio/): gpio_input_output (basic I/O), gpio_output_with_input (output with input), gpio_validation_cli (CLI validation).

Operation Steps

1
Prepare the Hardware

On all Ai-M6x boards the button is wired to GPIO2, so just use the onboard button; for an external button/jumper wire: one end to GPIO2, the other end to GND, to manually simulate level changes that trigger the interrupt.

2
Enter the Example Directory

Open a terminal and enter the GPIO interrupt example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):

cd examples/peripherals/gpio/gpio_interrupt
3
Build the Project

Run the build command. The Ai-M62 (BL616) and Ai-M61 (BL618) belong to the same series, so both use bl616:

make CHIP=bl616 BOARD=bl616dk
4
Flash the Firmware

Connect the board with a USB cable, hold the BOOT button (IO2 on the Ai-M61-32S-Kit), briefly press EN/RST to enter download mode, then flash (replace the serial port with the one on your computer):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
5
Configure and Trigger the Interrupt

Open a serial tool (baud rate 2000000). The example prints gpio interrupt at startup. Type gpio_int_test 2 0 and press Enter to configure GPIO2 (onboard button) for falling-edge interrupt, then press the button (or ground the jumper wire and release) — the serial port prints Interrupt Trigger!.

Code Execution Flow

The complete execution flow from startup to running is shown below (loop arrows mean repeated execution):

More trigger modes

Try gpio_int_test 2 1 (rising edge), gpio_int_test 2 2 (low level), or gpio_int_test 2 3 (high level); you can also use another pin, e.g. gpio_int_test 3 0 for GPIO3.

APIs Used by the Example

bflb_device_get_by_name("gpio")

Gets the GPIO device handle.

Parameters:

  • name: device name string, always "gpio" for GPIO

Return: struct bflb_device_s * device handle

bflb_gpio_init(gpio, pin, mode)

Configures a pin as input (for interrupts: GPIO_INPUT | GPIO_PULLUP | GPIO_SMT_EN).

Parameters:

  • gpio: GPIO device handle
  • pin: pin number, e.g. GPIO_PIN_2 (the button on Ai-M6x boards)
  • mode: mode flags, e.g. GPIO_INPUT with GPIO_PULLUP

Return: 0 on success; negative error code on failure

bflb_gpio_int_init(gpio, pin, mode)

Initializes the interrupt trigger mode of a pin.

Parameters:

  • gpio: GPIO device handle
  • pin: pin number
  • mode: trigger mode, GPIO_INT_TRIG_MODE_SYNC_FALLING_EDGE / SYNC_RISING_EDGE / SYNC_LOW_LEVEL / SYNC_HIGH_LEVEL

Return: 0 on success; negative error code on failure

bflb_gpio_irq_attach(pin, isr)

Registers the interrupt callback for a pin; the system calls it when the interrupt fires.

Parameters:

  • pin: pin number
  • isr: callback function, e.g. void isr(uint8_t pin)

Return: none

bflb_irq_enable(irq_num)

Enables the peripheral interrupt. The example disables it first with bflb_irq_disable(gpio->irq_num) while configuring, then enables it.

Parameters:

  • irq_num: peripheral interrupt number, gpio->irq_num for GPIO

Return: none

Complete Code

The complete source below matches the effect described on this page. It is based on the official example (examples/peripherals/gpio/gpio_interrupt); the LED pins are adapted to the Ai-M61/62-32S-Kit onboard RGB LED. Collapsed by default, click to expand:

📜 Click to expand gpio_interrupt/main.c full code
c
#include "bflb_gpio.h"
#include "bflb_mtimer.h"
#include "board.h"
#include "shell.h"
#include "bflb_uart.h"

struct bflb_device_s *gpio;
struct bflb_device_s *uart0;
static uint8_t gpio_int_pin = GPIO_PIN_2; /* button on Ai-M6x boards */

void gpio0_isr(uint8_t pin)
{
    if (pin == gpio_int_pin) {
        printf("Interrupt Trigger!\r\n");
    }
}

int gpio_int_test(int argc, char **argv)
{
    printf("Set gpio interrupt triggle mode\r\n");

    if ((argc != 3) || (atoi(argv[1]) >= GPIO_PIN_MAX) || (atoi(argv[2]) > 3)) {
        printf("Usage: gpio_int_test <gpio> <mode>\r\n"
               "    0: GPIO_INT_TRIG_MODE_SYNC_FALLING_EDGE\r\n"
               "    1: GPIO_INT_TRIG_MODE_SYNC_RISING_EDGE\r\n"
               "    2: GPIO_INT_TRIG_MODE_SYNC_LOW_LEVEL\r\n"
               "    3: GPIO_INT_TRIG_MODE_SYNC_HIGH_LEVEL\r\n");
        return 1;
    }

    printf("Set gpio%d interrupt triggle mode to %d\r\n", atoi(argv[1]), atoi(argv[2]));

    bflb_irq_disable(gpio->irq_num);
    gpio_int_pin = atoi(argv[1]);
    bflb_gpio_init(gpio, atoi(argv[1]), GPIO_INPUT | GPIO_PULLUP | GPIO_SMT_EN);
    bflb_gpio_int_init(gpio, atoi(argv[1]), atoi(argv[2]));
    bflb_gpio_irq_attach(atoi(argv[1]), gpio0_isr);
    bflb_irq_enable(gpio->irq_num);

    return 0;
}

int main(void)
{
    int ch;
    board_init();

    gpio = bflb_device_get_by_name("gpio");
    uart0 = bflb_device_get_by_name("uart0");
    printf("gpio interrupt\r\n");

    shell_init();

    while (1) {
        while ((ch = bflb_uart_getchar(uart0)) != -1) {
            shell_handler(ch);
        }
    }
}
SHELL_CMD_EXPORT_ALIAS(gpio_int_test, gpio_int_test, shell gpio_int_test.);

FAQ

Nothing happens after typing the command

Set the serial baud rate to 2000000; the command format is gpio_int_test <gpio> <mode>, e.g. gpio_int_test 2 0 (GPIO2 falling edge), with spaces between arguments and Enter at the end.

Pressing the button does not trigger the interrupt

Check that the trigger mode matches the signal direction: grounding the pin with a button produces a falling edge, so use mode 0; for active-high wiring use rising edge or high level.

The interrupt triggers multiple times / bounces

Mechanical buttons bounce when pressed and released, which can trigger the interrupt several times. In a real project, add debounce (re-read the level after a short delay) or use low-level triggering.

Have questions?

For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23