Hello.
I have a thread which must be waked-up from multiple sources - 3 different message box for example. How I can organize this in CMSIS-RTOS? Currently in revision 4.00 of CMSIS, there is a osWait() function. But in RTX 4.74 (which comes with latest CMSIS), this function is not implemented.
So what I can do like a workaround of this problem? Wake-up regularly via timer and check all message boxes? Working but not efficient.Currently the only multi-object wake-up source implemented in CMSIS-RTOS seems to be the signals. But it's not really cool to use message box and signals in parallel for waking up. Did I'm missing something?
Has anyone attempted to implement and add this feature in RTX?
Looking at the CMSIS-RTOS API it seems the API is designed to support waiting on a signal and simultaneously on one (not multiple) message queues and getting unblocked by either one. Both the osSignalWait and the osMessageGet functions return the same structure an osEvent which contains osStatus that can be used to tell the caller what type of an unblock reason it was if they should interpret the structure as an osEventSignal or an osEventMessage.
A pretty common use case in an RTOS world is to use one or more Signals as the best way to communicate from IRQs to a Task A and then use a message queue to communicate from other Tasks to Task A.
If you looking the RTX 4.74 source code it really seems to me that this feature is quite simply not implemented, I guess ARM open sourced a legacy RTOS that only partially implements the CMSIS-RTOS API. Lets say that something is better than nothing...
I'm considering an alternate implementation where each IRQ uses only a signal while other Tasks send a message and then a signal - the receiving Task A would then block only on signals using osSignalWait(waitforever) and then check either its message queue or do an action particular to the specific signal from the IRQ.
Note to the OP - if you had a signal per message queue the receiving Task A could know which message queue to check and make sure to use osMessageGet with a timeout of 0.
This isn't super elegant but would probably be similar but not quite as efficient as how the OS itself would implement it internally.
/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. /// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag. /// \param[in] millisec timeout value or 0 in case of no time-out. /// \return event flag information or error code. /// \note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS. os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec);
Beware even though the signal field is defined as int32_t the RTX source code it is only a U16.
/// Get a Message or Wait for a Message from a Queue. /// \param[in] queue_id message queue ID obtained with \ref osMessageCreate. /// \param[in] millisec timeout value or 0 in case of no time-out. /// \return event information that includes status code. /// \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS. os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
typedef struct { osStatus status; ///< status code: event or error information union { uint32_t v; ///< message as 32-bit value void *p; ///< message or mail as void pointer int32_t signals; ///< signal flags } value; ///< event value union { osMailQId mail_id; ///< mail id obtained by \ref osMailCreate osMessageQId message_id; ///< message id obtained by \ref osMessageCreate } def; ///< event definition } osEvent;
Should check status to know how to interpret the osEvent.
typedef enum { osOK = 0, ///< function completed; no error or event occurred. osEventSignal = 0x08, ///< function completed; signal event occurred. osEventMessage = 0x10, ///< function completed; message event occurred. osEventMail = 0x20, ///< function completed; mail event occurred. osEventTimeout = 0x40, ///< function completed; timeout occurred. ....snip..... os_status_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization. } osStatus;
I am in a similar situation where I need to send a signal (from multiple IRQ) to a single task. After reading the API and going through examples I don't think that there is any elegant way of doing this.
A task can just wait for a single signal.
I noticed that there used to be a function called osSignalGet which has now being taken out. This would actually solve the problem.
So I can do something like this:
<code>
for(;;){ osSignalWait(0,osWaitForever); // wait for any signal, sent from a multiple sourcse of IRQ; currentSignal = osSignalGet(currentThread); //not sure the exact syntax, but this returns the current signal switch(currentSignal){ case BUTTON1: .... break; ... ... } }
</code>
Thomas, not sure I follow 100% of your alternate implementation. Are you suggesting that if we have 10 IRQs then we should have 10 different tasks to receive (one each). Then from there send messages etc after that?
I am quite stuck with this at the moment. Any suggestions / tips would be great. !
That's very strange removing that, as you point it makes osSignalWait for any signal rather useless. But I think having a task per IRQ which deals with whatever has to be done straight away and then sending off a message for anything longer which is dealt with in a serial fashion is the cleaner way to do it. It does make prioritization rather difficult though.
Hey,
I managed to get it to work without osSignalGet. Basically I await any signal forever using osSignalWait(0x00, osWaitForever). Once it is recevied, i confirm using the osEvent returned that it is a signal event then I get the signal value from osEvent.value.signals variable and using a switch case to determine what I to do. More details I did on the tech bits: How to await several events using CMSIS 4 in-built RTOS. I am yet to expound more on how I did it but I think it will be rather straight forward. Hope it helps
I got 'Blog has been removed' when I visited that link
It seems that the new URL is : https://maxwellweru.com/how-to-await-several-events-using-cmsis-4-in-built-rtos/
Thanks