我正在用基于中断的版本替换我的 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!");
}
您在中断处理程序中做了太多工作,可能会阻止其他中断服务例程运行,从而触发中断 WDT。中断处理程序应执行尽可能少的计算量。
主要问题是中断处理程序内的日志消息,仅删除它们可能会解决您的问题,但您应该考虑将当前在处理程序中执行的所有处理推迟到单独的任务(例如,使用中断处理程序只是为了将数据发送到队列)。
如果您仍然需要更多时间并且绝对确定您正在做的事情的后果,您还可以考虑增加中断 WDT 的超时值(通过
menuconfig
)。