我的基于UART中断的读取代码使ESP32崩溃

问题描述 投票:0回答:1

我正在用基于中断的版本替换我的 UART 轮询代码,但我得到如下

interrupt wdt on CPU1

Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1). 

Core  1 register dump:
PC      : 0x40098df4  PS      : 0x00060935  A0      : 0x80097d66  A1      : 0x3ffbf15c  
A2      : 0x3ffcd3b8  A3      : 0x3ffd0d6c  A4      : 0x00000004  A5      : 0x00060923  
A6      : 0x00060923  A7      : 0x00000001  A8      : 0x3ffd0d6c  A9      : 0x00000018  
A10     : 0x3ffd0d6c  A11     : 0x00000018  A12     : 0x3ffc8734  A13     : 0x00060923  
A14     : 0x007bf318  A15     : 0x003fffff  SAR     : 0x0000001e  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x400860a1  LEND    : 0x400860a9  LCOUNT  : 0x00000027  
Core  1 was running in ISR context:
EPC1    : 0x40109c5b  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x00000000


Backtrace:0x40098df1:0x3ffbf15c |<-CORRUPTED

删除所有日志没有什么区别。

[更新]我将缺少的 IRAM_ATTR 添加到中断处理程序中,没有任何效果,仍然是 wdt 超时。

如果有人指出我正确的方向,那就太好了。

我的代码如下,

processIncomingByteToForgeAMessage
定义为静态:


#define BMS_UART_VERSION2 true

#define RXD GPIO_NUM_34
#define TXD GPIO_NUM_14

#define BmsSerial Serial2

const int MESSAGE_LENGTH = PACKET_LENGTH;
const byte START_BYTE = 0xA5;

/// The queue where we push incoming UART messages from the BMS
QueueHandle_t BmsUart :: incomingMessageQueue = xQueueCreate(100, PACKET_LENGTH);


/// @brief  Installs interrupt handler
void BmsUart :: setupInterrupt() {

    log("Installing UART interrupt handler");

    attachInterrupt(digitalPinToInterrupt(RXD), BmsUart :: processIncomingByteToForgeAMessage, FALLING); 
}

/// @brief Process incoming byte to forge a coherent message and push to the queue
void IRAM_ATTR BmsUart :: processIncomingByteToForgeAMessage() {
    static byte message[MESSAGE_LENGTH];
    static int messageIndex = 0;

    const int receivedInt = BmsSerial.read();

    // Nothing available?
    if (receivedInt<0) return;

    const byte receivedByte = receivedInt&0xff;

    // Waiting for start of message byte
    if (messageIndex == 0 && receivedByte != START_BYTE) {
        // Discard bytes until the start byte is found
        bmsUart.log("Start byte is wrong: %02x, discard till it is right (%02x)", receivedByte, START_BYTE);
        return;
    }

    bmsUart.log(">%02x ", receivedByte&0xff);

    // Add the received byte to the message buffer
    message[messageIndex++] = receivedByte;

    if (messageIndex>PACKET_LENGTH) {
        // Reset the index for the next message
        messageIndex = 0;
        bmsUart.error("Buffer overflow at %d bytes, resetting to 0", messageIndex);
    }

    if (messageIndex == MESSAGE_LENGTH) {

        const byte messageId = message[PACKET_MESSAGE_ID_OFFSET];


        const esp_err_t err = xQueueSend(BmsUart :: incomingMessageQueue, message, RS485_QUEUE_MAX_TICKS_DELAY);
        
        switch (err){
        // Ok, posted in the queue?
        case pdTRUE: break;
        // Queue is full?
        case errQUEUE_FULL:
            bmsUart.warn("Queue is full: unable to post the message %02x to the queue", messageId);
            break;  
        default:
            bmsUart.warn("Error %02x: Unable to post the message %02x to the queue, even after %d ticks", err, messageId, RS485_QUEUE_MAX_TICKS_DELAY);
            break;
        }

        // Reset the index for the next message
        messageIndex = 0;
    }
}



/// @brief Gets pending message if any
/// @param message A PACKET_LENGTH -sized byte buffer to hold the next message, if nay
/// @return true if a message is there otherwise false

bool BmsUart :: getNextMessage(byte *message) {
    // If a message is available, process it
    
    if (xQueueReceive(incomingMessageQueue, &message, RS485_QUEUE_MAX_TICKS_DELAY) == pdPASS) {
    
        // Log the available message
        logMessage("Pending message", message);

        return true;
    }

    return false;
}





void BmsUart :: setup() {
    /// Stack depth
    stackDepth = 4000;

    /// Every 300 mseconds
    taskExecutionPeriod = 300;


    log("Serial connection thru UART2 (pins %d/%d)…", RXD,TXD);



    #if BMS_UART_VERSION2
    // ==  Installs interrupt handler
    setupInterrupt();
    #endif

    // == driver output enable
    //pinMode (ENABLE_PIN, OUTPUT); 
    BmsSerial.begin(9600, SERIAL_8N1, RXD, TXD);



    while (!BmsSerial) {
        log(">.");
    }

    log("BmsSerial began!");

}

arduino interrupt esp32 uart
1个回答
0
投票

您在中断处理程序中做了太多工作,可能会阻止其他中断服务例程运行,从而触发中断 WDT。中断处理程序应执行尽可能少的计算量。

主要问题是中断处理程序内的日志消息,仅删除它们可能会解决您的问题,但您应该考虑将当前在处理程序中执行的所有处理推迟到单独的任务(例如,使用中断处理程序只是为了将数据发送到队列)。

如果您仍然需要更多时间并且绝对确定您正在做的事情的后果,您还可以考虑增加中断 WDT 的超时值(通过

menuconfig
)。

© www.soinside.com 2019 - 2024. All rights reserved.