使用mBed OS Serial接收中断时运行期触发Mutex错误排查
串口中断触发Mutex报错问题分析
在B-L475E-IOT01A1开发板上运行旧版本Mbed OS,未手动使用任何线程或Mutex,编写了仅读取并存储串口缓冲区的测试代码,触发接收中断时抛出Mutex相关错误,即使清空中断函数内容仍报错。更新Mbed至最新版本并改用无缓冲串口类后问题解决,以下是旧版本报错的具体原因:
测试代码
#include "mbed.h" Serial device(USBTX, USBRX); // tx, rx DigitalOut led1(LED1); void Rx_interrupt(); // Circular buffers for serial TX and RX data - used by interrupt routines const int buffer_size = 255; // might need to increase buffer size for high baud rates char rx_buffer[buffer_size+1]; // Circular buffer pointers // volatile makes read-modify-write atomic volatile int rx_in=0; volatile int rx_out=0; // main test program int main() { device.baud(9600); // Setup a serial interrupt function to receive data device.attach(&Rx_interrupt, Serial::RxIrq); while (1) { } } // Interupt Routine to read in data from serial port void Rx_interrupt() { led1=1; // Loop just in case more than one character is in UART's receive FIFO buffer // Stop if buffer full while ((device.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) { rx_buffer[rx_in] = device.getc(); rx_in = (rx_in + 1) % buffer_size; } led1=0; return; }
触发的错误信息
++ MbedOS Error Info ++ Error Status: 0x80010133 Code: 307 Module: 1 Error Message: Mutex: 0x1000158C, Not allowed in ISR context Location: 0x800A64D Error Value: 0x1000158C Current Thread: main Id: 0x20000354 Entry: 0x8007BF5 StackSize: 0x1000 StackMem: 0x10000418 SP: 0x20017EA8 -- MbedOS Error Info --
旧版本报错原因
旧版本的Serial类内部实现依赖带缓冲的串口机制,为了保证多线程下的缓冲区操作安全,底层会使用Mutex做同步控制。当你调用device.attach()注册中断回调后,中断触发时会进入ISR(中断服务程序)上下文,而Mbed OS的Mutex明确禁止在ISR中被操作——哪怕你的中断函数里没显式调用Mutex,Serial类的底层中断处理逻辑(比如维护内部缓冲区)会自动尝试获取Mutex,这直接违反了ISR的操作规则,因此触发错误。
即便清空Rx_interrupt函数内容,Serial类的底层中断处理流程依然会执行,依然会触发Mutex的非法调用,所以错误无法消除。
解决逻辑验证
更新到最新版本Mbed OS后改用无缓冲串口类(如RawSerial或UnbufferedSerial),这类串口类内部不依赖Mutex做同步,完全适配ISR上下文的操作场景,因此不会触发该错误。
内容的提问来源于stack exchange,提问作者Jonathan wheadon
相关产品推荐
相关产品推荐

