一、移植背景
本文档记录将 AT32F423 的 GPIO 按键中断功能移植到 Zephyr RTOS 的完整过程。移植完成后,按键使用 Zephyr 标准 GPIO 中断 API,支持按下和松开两种中断触发方式。二、硬件连接
开发板: AT32F423-START按键: PA0(Wakeup 按键)
三、移植过程3.1 设备树修复问题: 设备树中 GPIO 地址不正确根据 AT32 官方头文件 `at32f423.h`,GPIO 实际地址为:
修复文件: `zephyr/drivers/gpio/gpio_at32.c`
3.2.1 添加 EXTI 寄存器定义
文件: `test_at32/main.c`
问题 1: GPIO 地址错误
现象: `gpio_pin_get()` 始终返回 0原因: 设备树中 GPIO 基地址错误解决: 修正为 0x40020000(根据 AT32 官方头文件) 问题 2: 回调未触发现象: EXTI 中断触发,但回调函数未执行原因:1. EXTI 源选择未配置2. ISR 中无法通过 `device_get_binding()` 获取设备解决:1. 添加 EXTI_EXINTx 寄存器配置2. 使用全局数组存储设备指针
问题 3: 按键状态读取错误现象: 中断触发后读取的状态不正确原因: 中断清除后读取的 IDT 值已被清除解决: 在清除中断标志前先读取 GPIO 状态 五、使用方法5.1 Shell 命令
按下按键: 打印 `BUTTON: PRESSED`松开按键: 打印 `BUTTON: RELEASED`
六、代码修改汇总
七、总结
本次移植成功实现了 AT32F423 的 GPIO 按键中断功能,完全使用 Zephyr 标准 API:- `gpio_pin_configure()` - 配置 GPIO- `gpio_pin_interrupt_configure()` - 配置中断- `gpio_pin_get()` - 读取引脚状态- `gpio_init_callback()` / `gpio_add_callback()` - 管理回调
这使得应用层代码具有良好的可移植性,与其他 Zephyr 支持的芯片保持一致。
本文档记录将 AT32F423 的 GPIO 按键中断功能移植到 Zephyr RTOS 的完整过程。移植完成后,按键使用 Zephyr 标准 GPIO 中断 API,支持按下和松开两种中断触发方式。二、硬件连接
开发板: AT32F423-START按键: PA0(Wakeup 按键)
电路特性: 外部下拉电阻到地,按下时 PA0 为高电平

三、移植过程3.1 设备树修复问题: 设备树中 GPIO 地址不正确根据 AT32 官方头文件 `at32f423.h`,GPIO 实际地址为:
- GPIOA: 0x40020000 - GPIOB: 0x40020400 - GPIOC: 0x40020800 - GPIOD: 0x40020C0修复文件: `zephyr/dts/arm/at32/at32f423.dtsi`
- gpio_a: gpio@40021000 {
- reg = <0x40021000 0x400>;
+ gpio_a: gpio@40020000 {
+ reg = <0x40020000 0x400>; 3.2 GPIO 驱动完善问题: AT32 GPIO 驱动缺少中断配置功能需要实现以下函数:- `gpio_at32_pin_interrupt_configure()` - 配置 GPIO 引脚中断- EXTI 中断处理函数- EXTI 源选择配置修复文件: `zephyr/drivers/gpio/gpio_at32.c`
3.2.1 添加 EXTI 寄存器定义
#define EXINT_BASE 0x40013C00 #define EXINT_INTEN (*(volatile uint32_t *)(EXINT_BASE + 0x00)) #define EXINT_EVTEN (*(volatile uint32_t *)(EXINT_BASE + 0x04)) #define EXINT_POLCFG1 (*(volatile uint32_t *)(EXINT_BASE + 0x08)) #define EXINT_POLCFG2 (*(volatile uint32_t *)(EXINT_BASE + 0x0C)) #define EXINT_INTSTS (*(volatile uint32_t *)(EXINT_BASE + 0x14))3.2.2 实现引脚中断配置
static int gpio_at32_pin_interrupt_configure(const struct device *port,
gpio_pin_t pin,
enum gpio_int_mode mode,
enum gpio_int_trig trig)
{
// 1. 获取端口索引
// 2. 配置 EXTI 源选择(类似 STM32 的 AFIO)
// 3. 配置触发边沿
// 4. 使能 EXTI 中断
// 5. 使能 NVIC 中断
}3.2.3 添加 EXTI 中断处理ISR_DIRECT_DECLARE(gpio_exti0_isr)
{
gpio_at32_exti_isr(0);
ISR_DIRECT_PM();
return 0;
}3.3 应用层代码文件: `test_at32/main.c`
/* 定义按键引脚 */
#define BUTTON_PIN 0
/* 按键回调函数 */
static struct gpio_callback button_cb_data;
void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
int pressed = gpio_pin_get(gpioa_port, BUTTON_PIN);
if (pressed > 0) {
printk("BUTTON: PRESSED\n");
} else {
printk("BUTTON: RELEASED\n");
}
}
int main(void)
{
// 配置按键为输入
ret = gpio_pin_configure(gpioa_port, BUTTON_PIN, GPIO_INPUT);
// 配置双边沿中断
ret = gpio_pin_interrupt_configure(gpioa_port, BUTTON_PIN,
GPIO_INT_EDGE_BOTH);
// 初始化并注册回调
gpio_init_callback(&button_cb_data, button_pressed, BIT(BUTTON_PIN));
gpio_add_callback(gpioa_port, &button_cb_data);
while (1) {
k_sleep(K_FOREVER);
}
}四、关键问题与解决问题 1: GPIO 地址错误
现象: `gpio_pin_get()` 始终返回 0原因: 设备树中 GPIO 基地址错误解决: 修正为 0x40020000(根据 AT32 官方头文件) 问题 2: 回调未触发现象: EXTI 中断触发,但回调函数未执行原因:1. EXTI 源选择未配置2. ISR 中无法通过 `device_get_binding()` 获取设备解决:1. 添加 EXTI_EXINTx 寄存器配置2. 使用全局数组存储设备指针
问题 3: 按键状态读取错误现象: 中断触发后读取的状态不正确原因: 中断清除后读取的 IDT 值已被清除解决: 在清除中断标志前先读取 GPIO 状态 五、使用方法5.1 Shell 命令
# 查询按键状态 uart:~$ button Button (PA0): RELEASED # 控制 LED uart:~$ led on 2 LED2 ON uart:~$ led off 2 LED2 OFF uart:~$ led toggle 3 uart:~$ led status5.2 中断触发
按下按键: 打印 `BUTTON: PRESSED`松开按键: 打印 `BUTTON: RELEASED`
六、代码修改汇总
| 文件 | 修改内容 |
| zephyr/dts/arm/at32/at32f423.dtsi | 修复 GPIO 地址 |
| zephyr/drivers/gpio/gpio_at32.c | 实现 `pin_interrupt_configure`、EXTI 中断处理 |
| test_at32/main.c | 按键初始化和回调处理 |
七、总结
本次移植成功实现了 AT32F423 的 GPIO 按键中断功能,完全使用 Zephyr 标准 API:- `gpio_pin_configure()` - 配置 GPIO- `gpio_pin_interrupt_configure()` - 配置中断- `gpio_pin_get()` - 读取引脚状态- `gpio_init_callback()` / `gpio_add_callback()` - 管理回调
这使得应用层代码具有良好的可移植性,与其他 Zephyr 支持的芯片保持一致。
我要赚赏金
