I’m using serial receive interrupt to receive MIDI and outputting the status via USB serial butg the code freezes very rarely.
When I investigated it, I found out that if a receive interrupt occurs during serial transmission, mbed stops.
I found the cause of the problem, but I can’t think of a specific way to deal with it.
Before and after the serial transmission.
void testSend(void){
serial.attach(NULL,Serial::RxIrq);
Sending process //----
serial.attach(receiveFunction,Serial::TxIrq );
}
but it moves a little at first and then doesn’t work after that.
Also.
__disable_irq();
__enable_irq();
had the same result.
In this case, how can I get the serial receive interrupt to not freeze when it occurs during serial transmission? Is it possible to continue the process to the
For serial transmissions, we are not looking for that much real-time.
Maybe you can utilize Condition Variable rather than interrupts. For example:
#include "mbed.h"
#define BUFF_LEN 32
BufferedSerial serial(STDIO_UART_TX, STDIO_UART_RX);
Mutex mutex;
ConditionVariable cond(mutex);
// These variables are protected by locking mutex
uint8_t serBuff[BUFF_LEN];
ssize_t dataLen;
void taskSend()
{
mutex.lock();
while (1) {
printf("Send: Waiting for serial data\r\n");
// Wait for a condition to change
cond.wait();
// serBuff and dataLen are safely accessible
printf("Send: %d bytes are available in serBuff\r\n", dataLen);
// Send data over USB
printf("Send: Sending data over USB\r\n");
// ...
}
}
int main()
{
Thread thread;
thread.start(taskSend);
while (1) {
if (serial.readable()) {
mutex.lock();
// Read serial (change the serBuff and dataLen variables)
dataLen = serial.read(serBuff, BUFF_LEN);
printf("Main: Serial data received\r\n");
printf("Main: %d bytes are available in serBuff\r\n", dataLen);
// Signal that serBuff and dataLen have changed
cond.notify_all();
mutex.unlock();
}
ThisThread::sleep_for(5);
}
}
I’m very sorry, I didn’t notice that you need a solution for NUCLEO-F303K8 (thank you Jan for noticing me). Unfortunately, the NUCLEO-F303K8 doesn’t support Mbed OS 6 with RTOS (only bare-metal) so condition variable and threads cannot be implemented on your board
There is MUTEX GUARD in stdio.h library and Serial.
So you cant use any put / print /get function in ISR.
So you need to use Rawserial library.Here I attached simple but useful code to read and write data in 2 way communication on UART.
Please check , it may be useful !!!
NEVER USE LONG CODE INSIDE ISR – IT pause other process, IF POSSIBLE use only flag or semaphore or signals.
Thanks for showing me a solution.
However, I use a separate serial interface for sending and receiving.
And I used RawSerial instead of Serial,but mbed os hangs.
Can you please show your code ?
RawSerial allow you to use any of library function inside ISR, but as I said use only flag inside ISR, this is because OS pause other processes while handling ISR block.
I think your OS hang not because serial interface, there is something other cause
You handle serial interrupts in the midi::receiveMessage ISR:
void midi::receiveMessage(void) {
uint8_t data = _serial.getc();
if (messageBuffer.size() > receiveMessageBufferSize - 1)messageBuffer.clear();
messageBuffer.push_back(data);
return;
}
Inside this ISR you call the messageBuffer.clear() and messageBuffer.push_back(data) functions. Both of these functions include a while(true) endless loop:
...
if (isLocked)
while (true);
...
However, the isLocked variable can be set to true also outside the ISR, for example when you call the messageBuffer.pull() function. If that happens (isLocked = true) and a serial interrupt occurs the program inside the ISR enters the while(true) endless loop and hangs.