Skip to content

Contributed by 爱笑, organized by Ai-Thinker

[Ai-WB2 Getting Started] GPIO Usage

The GLB (Global Register) of the Ai-WB2 (BL602) is the chip's general global configuration module, which mainly includes clock management, reset management, bus management, memory management and GPIO management functions. This article introduces how to use the GPIO management functions of the Ai-WB2, including GPIO input, GPIO output and GPIO interrupt. 1. GPIO Introduction General-purpose input/output (usually referred to as GPIO). The GPIO management function provides GPIO control registers that allow software to configure GPIO properties so that users can operate the GPIO conveniently. Each GPIO can be configured in three modes: input, output and alternative function. In each mode (except analog alternative functions), three port states are available: pull-up, pull-down and floating. In addition, the GPIO provides an interrupt function that can be configured for rising edge, falling edge, or high/low level triggering.

The main features of the Ai-WB2 GPIO are as follows:

Click to expand full code
c
**·** 可以配置为普通输入输出功能,该模式下可以设定上拉,下拉或者浮空输入输出
**·** 可以配置为可选功能,搭配外设功能使用,该模式下亦可以设定上拉,下拉,在使用模拟功能时,必须设置为浮空
**·** 可以设置驱动能力,以提供更大的输出电流
**·** 可以设置施密特触发器功能,提供简单硬件防抖功能

Each GPIO can be configured by software as:

Click to expand full code
c
**·** 高阻输入
**·** 上拉输入
**·** 下拉输入
**·** 上拉中断输入
**·** 下拉中断输入
**·** 高阻中断输入
**·** 上拉输出
**·** 下拉输出
**·** 高阻输出
**·** 模拟输入可选功能
**·** 模拟输出可选功能
**·** 数字可选功能

The GPIO functional block diagram is as follows:

The functions that can be set for the GPIO include:

Click to expand full code
c
**·** Flash/QSPI:设定GPIO为QSPI功能,可以连接Flash,作为程序存储/运行介质
**·** SPI:设定GPIO为SPI功能
**·** 12C:设定GPI0为I2C功能
**·** UART:设定GPIO为UART功能
**·** PWM:设定GPIO为PWM功能
**·** ANA:设定GPI0为Analog功能
**·** SWGPIO:设定GPI0为通用I0功能
**·** JTAG:设定GPIO为JTAG功能

Basically, each GPIO can select any of the alternative functions above. When an alternative function is selected, the GPIO and its corresponding function signals are shown in the table below:

In the table above, when the UART function is selected, only one UART signal is chosen for the pin; the specific function of the pin (e.g., UART TX or UART RX) is not yet specified. The specific UART signal and its corresponding function need to be further selected via UART_SIGx_SEL (x=0-7). The signals that can be selected for each UART_SIGx_SEL include:

Click to expand full code
c
**·** 0:UARTO RTS
**·** 1:UARTO CTS
**·** 2:UARTO TXD
**·** 3:UARTO RXD
**·** 4:UART1 RTS
**·** 5:UART1 CTS
**·** 6:UART1 TXD
**·** 7:UART1 RXD

Taking GPIO0 as an example: when UART is selected for fun_sel, GPIO0 is mapped to UART_SIG0. By default, the value of UART_SIG0_SEL is 0, which is UART0_RTS, meaning the GPIO functions as UART0_RTS. If the application wants to use the GPIO as UART1_TXD, simply set UART_SIG0_SEL to 6, and GPIO0 will function as UART1_TXD.

GPIO Output Configuration By setting func_sel to SWGPIO, the GPIO can be used as an ordinary GPIO input/output. Setting IE to 0 and OE to 1 configures the GPIO as an output, and the output value is set through the GPIO_O register group. When the corresponding bit of GPIO_O is 0, the GPIO outputs a low level; when it is 1, the GPIO outputs a high level. The output drive capability can be set through the DRV control bit.

GPIO Input Configuration By setting func_sel to SWGPIO, IE to 1 and OE to 0, the GPIO can be configured as an input. The SMT control bit enables or disables the Schmitt trigger, and the PD and PU control bits set the pull-down/pull-up attributes. The value input externally can be obtained by reading the corresponding bit of the GPIO_I register.

GPIO Alternative Function Configuration By setting func_sel to the corresponding peripheral function, the GPIO can be connected to the peripheral to realize peripheral input/output. As can be seen from the GPIO basic functional block diagram, when an alternative function is selected, IE must be set to 1 and OE to 0, which disconnects the ordinary GPIO output control. In this way, for peripherals with fixed input functions, the peripheral OE signal is always 0, realizing the input function; for peripherals with fixed output, the OE signal is always 1, so the output is controlled by the peripheral, and the input signal at this time is the output signal but will not be sampled by the peripheral that is outputting. When a peripheral needs both input and output, controlling the peripheral's OE signal realizes both.

GPIO Interrupt Configuration To use the GPIO interrupt function, the GPIO must first be set to input mode. The interrupt trigger mode is configured through the GPIO_INT_MODE_SET register group. The configurable interrupt modes include:

Click to expand full code
c
**·** 上升沿触发中断
**·** 下降沿触发中断
**·** 高电平触发中断
**·** 低电平触发中断

Every GPIO can be configured for interrupt functionality. Whether a particular GPIO interrupt is enabled is set through the GPIO_INT_MASK register. When an interrupt occurs, the GPIO pin number that generated the interrupt can be obtained in the interrupt handler via the GPIO_INT_STAT register, and the corresponding interrupt signal can be cleared through GPIO_INT_CLR. 2. GPIO Management API Introduction The low-level definitions related to BL602 GPIO management are defined in the following file: bl iot sdk/components/platform/soc/bl602/b1602 std/bl602 std/StdDriver/inc/bl602 gpio.h This file mainly defines the GPIO numbers, GPIO modes and GPIO functions of the BL602. The high-level APIs related to BL602 GPIO management are defined in the following file: bl iot sdk/components/platform/hosal/bl602 hal/bl gpio.h This file defines the low-level GPIO operation functions.

Click to expand full code
c
typedef struct _gpio_ctx_desc {
struct _gpio_ctx_desc *next;
void (*gpio_handler)(void *);
void *arg;
uint8_t gpioPin;
uint8_t intCtrlMod;
uint8_t intTrgMod;
} gpio_ctx_t;
int bl_gpio_enable_output(uint8_t pin, uint8_t pullup, uint8_t pulldown); // 设置GPIO为输出
int bl_gpio_enable_input(uint8_t pin, uint8_t pullup, uint8_t pulldown); // 设置GPIO为输入
int bl_gpio_output_set(uint8_t pin, uint8_t value); // 设置GPIO电平值,0表示低电平;1表示高电平
int bl_gpio_input_get(uint8_t pin, uint8_t *value); // 读取GPIO电平值,0表示低电平;1表示高电平
int bl_gpio_input_get_value(uint8_t pin);// 读取GPIO电平值,0表示低电平;1表示高电平
int bl_gpio_int_clear(uint8_t gpioPin,uint8_t intClear);// 清除中断标志
void bl_gpio_intmask(uint8_t gpiopin, uint8_t mask); // 中断掩码
void bl_set_gpio_intmod(uint8_t gpioPin, uint8_t intCtrlMod, uint8_t intTrgMod); // 设置中断模式
void bl_gpio_register(gpio_ctx_t *pstnode); // 注册gpio

At the same time, further encapsulated definitions are provided in the system abstraction hardware layer of bl_iot_sdk, as follows: bl iot sdk/components/platform/hosal/include/hosal gpio.h This file defines the hardware abstraction layer operations on GPIO at the RTOS level

Click to expand full code
c
typedef struct hosal_gpio_ctx {
struct hosal_gpio_ctx *next;
hosal_gpio_irq_handler_t handle;
void *arg;
uint8_t pin;
uint8_t intCtrlMod;
uint8_t intTrigMod;
}hosal_gpio_ctx_t;
typedef struct {
uint8_t        port;         /**< @brief gpio port */
hosal_gpio_config_t  config; /**< @brief gpio config */
void          *priv;         /**< @brief priv data */
} hosal_gpio_dev_t;
int hosal_gpio_init(hosal_gpio_dev_t *gpio);
int hosal_gpio_output_set(hosal_gpio_dev_t *gpio, uint8_t value);
int hosal_gpio_input_get(hosal_gpio_dev_t *gpio, uint8_t *value);
int hosal_gpio_irq_set(hosal_gpio_dev_t *gpio, hosal_gpio_irq_trigger_t trigger_type, hosal_gpio_irq_handler_t handler, void *arg);
int hosal_gpio_irq_mask(hosal_gpio_dev_t *gpio, uint8_t mask);
int hosal_gpio_finalize(hosal_gpio_dev_t *gpio);

3. Hardware Preparation The following hardware will be used in this example:

Click to expand full code
c
**·** Ai-WB2-32S开发板
**·** RGB LED
**·** 470欧姆电阻
**·** 按键
**·** 连接线
**·** 面板包板
**四:软件准备**

In previous articles, we described in detail how to set up the Ai-WB2 development environment: 5. Code Implementation The following uses an LED and button input as an example to show how to use the GPIO input, output and interrupt functions of the Ai-WB2. 1. GPIO Output The example code is as follows:

Click to expand full code
c
#include <stdio.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <bl_gpio.h>
#define GPIO_LED_RED   0
#define GPIO_LED_GREEN  1
#define GPIO_LED_BLUE   2
void blink_task(void *param){
uint8_t r_value = 1;
uint8_t g_value = 1;
uint8_t b_value = 1;
bl_gpio_enable_output(GPIO_LED_RED, 0, 0);
bl_gpio_enable_output(GPIO_LED_GREEN, 0, 0);
bl_gpio_enable_output(GPIO_LED_BLUE, 0, 0);
while(1) {
bl_gpio_output_set(GPIO_LED_RED, r_value);
r_value = !r_value;
vTaskDelay(200);
bl_gpio_output_set(GPIO_LED_GREEN, g_value);
g_value = !g_value;
vTaskDelay(200);
bl_gpio_output_set(GPIO_LED_BLUE, b_value);
b_value = !b_value;
vTaskDelay(200);
}
}
void main(void)
{
xTaskCreate(blink_task, "blink_task", 1024, NULL, 15, NULL);
}

In the example code, we defined a FreeRTOS task blink_task that performs the LED blinking task. In blink_task, bl_gpio_enable_output sets the GPIO to output mode, and then the pin level is set by calling bl_gpio_output_set. 2. GPIO Input The example code is as follows:

Click to expand full code
c
#include <stdio.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <bl_gpio.h>
#include <stdio.h>
#include <hosal_gpio.h>
#include <hosal_dma.h>
#include <blog.h>
#include <stdbool.h>
#define LED_PIN 0
#define KEY_PIN 3
#define TAG "gpio_exti"
static bool led_state = false;
static hosal_gpio_dev_t led;
static hosal_gpio_dev_t key;
static int32_t counter = 0;
static void init_led(void) {
led.port = LED_PIN;
led.config = OUTPUT_OPEN_DRAIN_NO_PULL;
hosal_gpio_init(&led);
hosal_gpio_output_set(&led,0);
printf("led inited\r\n");
}
static void init_key() {
key.port = KEY_PIN;
key.config = INPUT_PULL_UP;
hosal_gpio_init(&key);
printf("key inited\r\n");
}
void key_task(void* params) {
printf("key task started\r\n");
static uint8_t key_state = 0;
while (true) {
if (hosal_gpio_input_get(&key, &key_state) == 0) {
if (key_state) {
vTaskDelay(10 / portTICK_PERIOD_MS);
if (hosal_gpio_input_get(&key, &key_state) == 0) {
if (key_state) {
hosal_gpio_output_set(&led, 1);
printf("key pressed\r\n");
}
else {
hosal_gpio_output_set(&led, 0);
}
}
}
}
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
void main(void) {
init_led();
init_key();
xTaskCreate(key_task, "key_task", 1024, NULL, 15, NULL);
}

In the example code, we used the RTOS abstraction layer API. First, a hosal_gpio_dev_t instance is defined to configure the LED pin and the button pin. Then the hosal_gpio_init function is called to initialize the pin configuration. The button value is read by calling the hosal_gpio_input_get function, and according to the button level, the level value of the LED pin is set by calling the hosal_gpio_output_set function. 3. GPIO Interrupt The example code is as follows:

Click to expand full code
c
#include <stdio.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <bl_gpio.h>
#include <stdio.h>
#include <hosal_gpio.h>
#include <hosal_dma.h>
#include <blog.h>
#include <stdbool.h>
#define LED_PIN 3
#define KEY_PIN 4
#define TAG "gpio_exti"
static bool led_state = false;
static hosal_gpio_dev_t led;
static hosal_gpio_dev_t key;
static int32_t counter = 0;
static void init_led(void) {
led.port = LED_PIN;
led.config = OUTPUT_OPEN_DRAIN_NO_PULL;
hosal_gpio_init(&led);
printf("led inited\r\n");
}
static void key_irq_callback(void* arg) {
printf("key pressed:%d\r\n",counter++);
led_state = !led_state;
hosal_gpio_output_set(&led, led_state);
}
static void init_key() {
key.port = KEY_PIN;
key.config = INPUT_PULL_UP;
hosal_gpio_init(&key);
hosal_gpio_irq_set(&key, HOSAL_IRQ_TRIG_NEG_PULSE, key_irq_callback, NULL);
printf("key inited\r\n");
}
void main(void) {
init_led();
init_key();
}

In the example code, the initialization of the LED pin and the button pin is the same as in the GPIO input example above. After the button pin initialization is complete, the button interrupt is configured by calling hosal_gpio_irq_set.

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