Wait for message and signal simultaneously using CMSIS RTX call
Hi All,
I am using CMSIS RTX V4.80.0. I need to wait for a message and a signal simultaneously in a single thread.
In the CMSIS RTOS API, I came across a function osWait() which meets my requirement. Is there any methods to achieve the same using the CMSIS RTX API.
In CMSIS RTX, both the osSignalWait and the osMessageGet functions return the same structure an osEvent which contains osStatus that contains the information for unblock(an osEventSignal or an osEventMessage). I tried using osSignalWait/osMessageGet function in the thread and identify whether message or signal is received using the return status. But for osSignalWait only osEventSignal is received as status and for osMessageGet only osEventMessage is received as status.
Is there any other alternatives to meet the requirement.
Thank you.
Note that you can implement an arbitrarily complex "wait for multiple" with some own code.
Implement code where you in a critical section change one or more of your n state variables. Then evaluate your wakeup condition - if it is satisfied then signal this using a "summary" event.
So an interested thread waits for this "summary" event. When the thread wakes up, it enters a critical section to decide if it wants to reset one or more of all your individual state variables.
Just quick mock-up of a wait_complex() that can wait for one of multiple events, or for a specific state combination.
And the individual state variables doesn't need to be traditional signal resources in the OS - but they must contain some form of state that can be (reasonably cheaply) polled when evaluating if the summary event should be signalled or not. Alas, there is no osMailPoll() and osMessagePoll() to make it easier to create a wait function that could wait for both mails, messages and signals.
void signal_a() { crit(x) { a = true; if (a && b) signal(summary); } } void signal_b() { crit(x) { b = true; if (a && b) signal(summary); } } void signal_c() { crit(x) { c = true; signal(summary); } } void signal_d() { crit(x) { d = true; signal(summary); } } /** * \brief Wait for event a+b both raised, or for event c or for event d or for timeout. */ int wait_complex(unsigned timeout) { res = wait(summary,timeout); if (res == timeout) return timeout; if (res == error) return error; crit(x) { if (a && b) { a = false; b = false; return EVENT_A_AND_B; } if (c) { c = false; return EVENT_C; } if (d) { d = false; return EVENT_D; } } return EVENT_OOPS; }
Just a footnote - if the wait-complex can't consume all "ready" event information in a single call, then it should be written like:
int wait_complex(unsigned timeout) { res = wait(summary,timeout); if (res != timeout && res != error) { crit(x) { if (a && b) { a = false; b = false; res = EVENT_A_AND_B; } else if (c) { c = false; res = EVENT_C; } else if (d) { d = false; res = EVENT_D; } else { res = EVENT_EMPTY; } if (a&&b || c || d) signal(summary); // so next wait() doesn't hang } } return res; }
It then needs to "restart" the summary signal, in case there are more state information ready to process.
You could augment the communications between the two tasks in the following manner. Task A will wait forever for a signal. Task B can send a message to task A and then it would also send a "message" signal. Task A would wake with the "message" signal and then know to get a message. You could also tie in mail the same way. The other signals in Task A could be used just for signalling.
We've implemented this with a health manager task which initially waits forever for any signals. If any task has an emergency, then it sends a 911 signal to the health manager which deals with the crisis. If a task wishes to schedule a regular checkup, then it sends a mail with the details and sets the "register" signal. The health manager gets the "register" signal, reads the mail and then schedules an appointment. The time to the appointment is now used in the signal timeout as opposed to waiting forever.