Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
5 years, 8 months ago.
Reading serial from a new thread in RTOS?
I would like to have an interrupt which then starts up a thread which then reads from serial input, but it outputs the following error:
++ MbedOS Error Info ++
Error Status: 0x80020126 Code: 294 Module: 2
Error Message: CMSIS-RTOS error: ISR Queue overflow
Location: 0x4CBB
Error Value: 0x2
Current Thread: rtx_idle Id: 0x1000037C Entry: 0x5689 StackSize: 0x200 StackMem: 0x10000408 SP: 0x10007F70
For more info, visit: https://armmbed.github.io/mbedos-error/?error=0x80020126
MbedOS Error Info
Here is my code:
include the mbed library with this snippet
#include "mbed.h" Thread ISRthread(osPriorityAboveNormal); osThreadId ISRthreadId; RawSerial pc(USBTX, USBRX); Mutex serial_mutex; DigitalOut myled(LED1); void newInput(); void ISR_thread(); int main() { ISRthread.start(callback(ISR_thread)); pc.attach(&newInput); //interrupt to catch input while(1) { myled = 1; osDelay(1000); myled = 0; osDelay(1000); } } void newInput() { osSignalSet(ISRthreadId,0x01); } void ISR_thread() { ISRthreadId = osThreadGetId(); for(;;) { osSignalWait(0x01, osWaitForever); serial_mutex.lock(); while (pc.readable()) { pc.getc(); } serial_mutex.unlock(); } }
I'm using OS5. Any way to make this work? I've tried to use LPC_UART0->RBR instead of getc() but found no luck.
I'm working on an LPC1768.
1 Answer
5 years, 8 months ago.
Hello W K,
- The 'serial received' interrupt flag shall be cleared in the
newInput
ISR. Otherwise the ISR is kept triggered forever. This is usually done by reading from the receive register. Another method is to detach the ISR in the ISR and re-attach it in the tread when you finish reading. - Since both
readable()
andgetc()
lock the Mutex as their fist action you don't have to do it in your code
#include "mbed.h" Thread ISRthread(osPriorityAboveNormal); osThreadId ISRthreadId; RawSerial pc(USBTX, USBRX); Mutex serial_mutex; DigitalOut myled(LED1); void newInput(); void ISR_thread(); int main(void) { ISRthread.start(callback(ISR_thread)); pc.attach(newInput); //interrupt to catch input while (true) { myled = 1; osDelay(1000); myled = 0; osDelay(1000); } } void newInput() { pc.attach(NULL); //detach the ISR to prevent recursive calls osSignalSet(ISRthreadId, 0x01); } void ISR_thread() { ISRthreadId = osThreadGetId(); for (;;) { osSignalWait(0x01, osWaitForever); // serial_mutex.lock(); while (pc.readable()) { pc.getc(); } // serial_mutex.unlock(); pc.attach(newInput); // re-attach the ISR } }
Thank you for sharing this info https://os.mbed.com/questions/4878/what-exactly-are-signals/#.
This solution is even better because the ISR is very short and there is no buffer:
#include "mbed.h" class Comm : public Thread { RawSerial _pc; bool _RUN; volatile bool newChar; void serialISR() { _pc.attach(NULL); // detaching ISR prevents being called again and again newChar = true; } void commInFn() { while (_RUN) { if (newChar) { newChar = false; while (_pc.readable()) _pc.putc(_pc.getc()); _pc.attach(callback(this, &Comm::serialISR)); // re-attach ISR } } } public: Comm() : _pc(USBTX, USBRX), _RUN(0), newChar(false), Thread(osPriorityAboveNormal, 1024) { _pc.printf("Welcome.\r\n"); } void start_comm() { _RUN = true; _pc.attach(callback(this, &Comm::serialISR)); start(callback(this, &Comm::commInFn)); // reattach ISR } }; //Main int main() { Comm comm_plz; comm_plz.start_comm(); while (1) { } }
Hi , Thanks for solution interrupt in thread.
i just want to clarify about 'osSignalWait(0x01, osWaitForever);'. is it automatically clear the 0x01 flag ?.
posted by 27 Sep 2019Hello Ibn,
Yes, osSignalWait(0x01, osWaitForever)
automatically clears the 0x01 flag because the osFlagsNoClear
option is not used when it calls the osThreadFlagsWait
function:
cmsis_os1.c
// ... os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) { osEvent event; uint32_t flags; if (signals != 0) { flags = osThreadFlagsWait((uint32_t)signals, osFlagsWaitAll, millisec); } else { flags = osThreadFlagsWait(SignalMask, osFlagsWaitAny, millisec); } // ... }
options
for the osThreadFlagsWait:
cmsis_os2.h
// ... #define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default). #define osFlagsWaitAll 0x00000001U ///< Wait for all flags. #define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for. // ...