乐鑫技术交流
直播中

龙献益

7年用户 959经验值
私信 关注
[问答]

在examples中,用uart_isr_register注册中断函数uart1_irq_handler后,就会报错是怎么回事?

-问题由来:在examples中,有uart_event的具体使用方法,但我想用串口中断读取GPS数据,我用uart_event模式在解析GPS数据时,会出现FIFO Overflow的问题,虽然examples中有nmea0183_parser案例来解析GPS数据,但是这个example对我来说太复杂了,于是我想用最原始的串口中断方法来解析GPS数据,但是我在做串口中断测试时,发现一旦我用uart_isr_register注册中断函数uart1_irq_handler后,就会报错Guru Meditation Error: Core  0 panic'ed (Interrupt wdt timeout on CPU0),我不明白为什么我的中断函数这么简单,看门狗还能跑飞,以下是我的代码。

代码解释:UART1与GPS模块相连,UART0与USB相连,UART1触发中断后,标志位rx_flag置1,在main中从UART1 FIFO中读取数据,用UART0向电脑的串口调试助手打印数据。

[Codebox]
#include
#include
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"

#define EX_UART_NUM UART_NUM_1
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)

int rx_flag;

static void IRAM_ATTR uart1_irq_handler(void *arg)
{
    rx_flag = 1;
}

void uart2_init(void)
{
    //串口一些基本参数的配置
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE};

    uart_param_config(EX_UART_NUM, &uart_config);
    uart_param_config(UART_NUM_0, &uart_config);
    //设置串口使用的引脚
    uart_set_pin(EX_UART_NUM, GPIO_NUM_17, GPIO_NUM_18, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //先uart_driver_install安装驱动,再把中断服务给释放掉
    uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0);
    uart_driver_install(UART_NUM_0, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0);
    uart_isr_free(EX_UART_NUM);
    //重新注册中断服务函数
    uart_isr_handle_t handle;
    uart_isr_register(EX_UART_NUM, uart1_irq_handler, NULL, 0, &handle);
    //使能串口接收中断
    uart_enable_rx_intr(EX_UART_NUM);
}

void app_main(void)
{
    uart2_init();
    uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);
    while (1)
    {
        if (rx_flag == 1)
        {
            rx_flag = 0;
            bzero(dtmp, RD_BUF_SIZE);
            int len = uart_read_bytes(EX_UART_NUM, dtmp, RD_BUF_SIZE, portMAX_DELAY);
            uart_write_bytes(UART_NUM_0, (const char *)dtmp, len);
        }
    }
}
[/Codebox]
                                                                                                                                              

回帖(2)

郑玉兰

2024-6-5 09:24:54
 这个是触发了 Task 看门狗问题。你这里在中断中给全局变量赋值,然后在 app_main 中检查全局变量,不是事件同步的好方式。问题就出在你 while(1) 去检查上,这会导致 CPU 一直陷入空循环。

解决方案:
1. 使用 semaphore,中断发生时 give 信号量,app_main 中 wait 信号量。这样 CPU 就不会无意义的空循环。
2. 如果难以理解 semaphore 的方式,请在 while(1) 中添加 vTaskDelay,等待期间让出一些 CPU 事件给其它 Task
                                                                 
举报

人走了

2024-6-5 16:05:34
这个问题可能是由于中断服务程序(ISR)没有正确处理中断,导致看门狗定时器超时。以下是一些建议来解决这个问题:

1. 确保中断服务程序(ISR)正确处理中断:检查你的`uart1_irq_handler`函数,确保它正确地处理了UART中断。例如,检查是否正确地读取了接收到的数据,并且清除了中断标志。

2. 检查中断优先级:确保你的中断优先级设置正确。如果中断优先级设置得太低,可能会导致中断被其他高优先级的中断抢占,从而无法及时处理。

3. 检查看门狗定时器配置:检查你的看门狗定时器配置,确保它没有设置得过短。如果看门狗定时器设置得太短,可能会导致在中断处理过程中,看门狗定时器已经超时。

4. 确保看门狗定时器在中断服务程序中被喂狗:在你的`uart1_irq_handler`函数中,确保在处理完中断后,调用`esp_task_wdt_reset()`来重置看门狗定时器。这样可以防止看门狗定时器超时。

5. 检查代码中的其他问题:检查你的代码中是否有其他可能导致看门狗定时器超时的问题,例如死循环、阻塞操作等。

6. 使用调试工具:如果问题仍然存在,可以尝试使用调试工具(如GDB)来调试你的代码,以便更好地了解问题所在。

7. 查阅相关文档和社区:如果你仍然无法解决问题,可以查阅ESP32的官方文档和社区论坛,看看是否有其他人遇到了类似的问题,并寻求解决方案。

希望这些建议能帮助你解决问题。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分