Using uVision v5.27.1.0 (RTOS 1) with STM32L4xxx. In an ISR two different signals are sent to the same thread like below:
.
osSignalSet(myTask, SIGNAL_1);
osSignalSet(myTask, SIGNAL_2);
In the waiting task myTask, the following code is executed:
for (;;) {
osEvent evt = osSignalWait(0, osWaitForever);
u32 signals = evt.value.signals;
The "signals " will NOT contain SIGNAL_2. Only SIGNAL_1. In other words, the waiting task will wake up on the first of the two signals, even though both of them were posted in the same ISR at the same time.
I think it is a bug .
The work around would be, in general case, to add the following code to code above:
evt = osSignalWait(0, 0);
signals |= evt.value.signals;
Now both SIGNAL_1 and SIGNAL_2 are consumed, and are in the variable "signals " .
Cheers!
Maybe you shouldn't set the two signal in separate calls to osSignalSet to begin with, but rather:
osSignalSet(myTask, SIGNAL_1| SIGNAL_2);
Hi Broeker,
of course, in real code we do not send two signals back-to-back. But if you use a peripheral, for example a timer with 4 capture/compare channels, then the same ISR will process 4 totally independent requests from independent channels. The ISR would normally have 4 "if" statements to check each of the channel interrupt requests, and inside that 'If" code there will be an osSignalSet() call that would set its corresponding signal. If some requests happen to come at the same time, like in my case, there will be multiple independent osSignalSet calls within one ISR. Although it is possible to write the ISR code so that there is only one osSignalSet with the combination of signals, but it is not how it should be done normally, I think.
Also, if there are nested interrupts from whatever sources, it will be impossible to combine signals into one osSignalSet call, which will result, in essense, in side-by-side calls, as I indicated in my post.
You are correct in assuming that you cannot make any assumptions about when 2 different signals have been set. That is what you are trying to do and you really cannot do that and that is what is causing you your perceived issue.
Maybe you need to rethink your application code.
while (1) { TheEvent = osWaitEvent(0,osWaitForever); if (TheEvent.status == osEventSignal) { if (TheEvent.value.signals & SIGNAL1) { } if (TheEvent.value.signals & SIGNAL2) { } if (TheEvent.value.signals & SIGNAL3) { } if (TheEvent.valeu.Signals & SIGNAL4) { } }
This is exactly what I do. My issue was that I assumed (wrongly) that two signals set independently in the same ISR would be consumed and returned by the wait at the same time. Say, in a imaginary application a timer keeps track of hours_event and minutes_event using two output compare channels. The timer ISR would set two signals: s_hour and s_minute to signal that an hour has changed or the minute has changed. Every 60 minutes there will be two signals in the same ISR.
If in the application code there is error checking: "if s_hour came, assert that s_minute also came with it", then this assertion will fail if in the ISR the s_minute interrupt request was processed first.
My issue was caused by a perception that we normally treat interrupts as an atomic operation when related to a task level. That is why is seemed totally normal and natural to expect the RTOS to return both signals. The reason why it returns the first qualifying signal only is purely implementation specific, I think.