Raspberry Pi Pico RP2040 UART发送时无限中断,如何应答?
Raspberry Pi Pico RP2040 UART发送无限中断问题修复
问题描述
在Raspberry Pi Pico RP2040开发板上,UART发送数据时会触发无限中断。修改官方示例"uart_advanced"复现该问题,无论是否启用FIFO,问题都会出现。为了在示波器上观测问题,在中断处理函数中切换GPIO电平:
- 通道1:UART TX线路GPIO(引脚8)
- 通道2:中断触发指示GPIO(引脚16)
问题代码如下:
#include "pico/stdlib.h" #include "hardware/uart.h" #include "hardware/irq.h" #include "hardware/gpio.h" #define UART_ID uart1 #define BAUD_RATE 115200 #define DATA_BITS 8 #define STOP_BITS 1 #define PARITY UART_PARITY_NONE #define UART_TX_PIN 8 #define UART_RX_PIN 9 #define D_GPIO_TEST 16 // interrupt handler void on_uart_interrupt() { for( int i = 0; i < 8; ++i ) { gpio_put( D_GPIO_TEST, true ) ; } gpio_put( D_GPIO_TEST, false ) ; } int main() { gpio_init( D_GPIO_TEST ) ; gpio_set_dir( D_GPIO_TEST, GPIO_OUT ) ; gpio_pull_up( D_GPIO_TEST ) ; gpio_put( D_GPIO_TEST, false ) ; // Set up our UART with a basic baud rate. uart_init(UART_ID, 2400); // Set the TX and RX pins by using the function select on the GPIO // Set datasheet for more information on function select gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART); gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART); // Actually, we want a different speed // The call will return the actual baud rate selected, which will be as close as // possible to that requested int __unused actual = uart_set_baudrate(UART_ID, BAUD_RATE); // Set UART flow control CTS/RTS, we don't want these, so turn them off uart_set_hw_flow(UART_ID, false, false); // Set our data format uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY); // Turn on FIFO's //uart_set_fifo_enabled(UART_ID, true); // Set up a interrupt // We need to set up the handler first // Select correct interrupt for the UART we are using int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ; // And set up and enable the interrupt handlers irq_set_exclusive_handler(UART_IRQ, on_uart_interrupt); irq_set_enabled(UART_IRQ, true); // Now enable the UART interrupts uart_set_irq_enables(UART_ID, false, true); sleep_ms( 10 ) ; uart_puts(UART_ID, "Hello uart\n"); while (1) tight_loop_contents(); }
问题原因
你启用了UART的TX中断(uart_set_irq_enables(UART_ID, false, true)的第二个参数为true),但中断处理函数中没有清除对应的中断标志位。RP2040的UART中断触发后,必须手动清除中断状态,否则中断控制器会认为中断事件仍未处理,会持续触发中断,导致无限循环调用中断处理函数。
修复方案
在中断处理函数中,需要读取并清除UART的中断标志。可以直接清除所有已触发的UART中断,或者针对性清除TX相关的中断标志。
基础修复版本
// interrupt handler void on_uart_interrupt() { // 清除当前UART的所有已触发中断标志 uart_clear_interrupts(UART_ID); for( int i = 0; i < 8; ++i ) { gpio_put( D_GPIO_TEST, true ) ; } gpio_put( D_GPIO_TEST, false ) ; }
精准处理版本(可选)
如果你只想清除TX相关的中断,可以先读取中断状态,再针对性清除:
// interrupt handler void on_uart_interrupt() { uint32_t ints = uart_get_interrupt_status(UART_ID); // 检查是否是TX FIFO空中断触发 if (ints & UART_IRQ_TX) { // 清除TX中断标志 uart_clear_interrupt_status(UART_ID, UART_IRQ_TX); } for( int i = 0; i < 8; ++i ) { gpio_put( D_GPIO_TEST, true ) ; } gpio_put( D_GPIO_TEST, false ) ; }
额外说明
如果你的需求是在TX发送完成后触发一次中断(而非TX FIFO空时触发),可以调整UART的中断触发条件,启用UART_TX_DONE_IRQ(发送完成中断),但需注意对应的配置和标志清除逻辑。
内容的提问来源于stack exchange,提问作者teach me
相关产品推荐
相关产品推荐

