Hi guys,
Just a quick one, can anyone confirm the behaviour of os_evt_get?
I'm wishing to share a buffer between two threads of different priority. When the thread of higher priority wishes to use the buffer, it sends a cease and desist event signal to the other thread.
I'm using Mutex locks but am concerned about the remote possibility of the cease and desist signal arriving in-between the lower priority thread waking up and locking the Mutex.
My thoughts were to lock the Mutex then re-check the event signaling, however the manual states:
"You can use the os_evt_get function to identify the event that caused the os_evt_wait_or function to complete."
Can I be sure that this function will always return the latest set of events, even if they've not yet been used to wake a thread?
Many thanks
Thanks for the response guys.
To clarify, I have a Send thread, Receive thread, a command decode thread and one (eventually more) low priority task thread.
The device itself communicates over multi-drop half-duplex EIA485 with a single master issuing commands. As many devices may need to be accessed at the same time, I took an approach that allowed some level of multiplexing, eliminating any form of unpredictable response delay.
Master issues short commands (segmenting them if necessary), whilst the slave must provide an immediate acknowledgement so that the master can move on to communicating with other slaves, however I'm also RAM limited.
So I have two small buffers, one for comms and one for the running task to prepare its response.
What takes place is once a new complete command is received, the buffer is swapped, exposing the new command to the task (and for the task to prepare its response in), meanwhile an ack response is prepared in parallel in the other buffer.
The concern was that I could have triggered a send response, whilst a higher priority receive came in before send had locked the buffers. Receive then fills the buffer with a few bytes, only for send to go ahead and swap them whilst the receive fifo was busy filling up again. Simple solution was to check that receive hadn't changed its mind since locking the buffers, hense the os_evt_get query. Certainly another approach would have been to use a mutex protected boolean between the two threads but I thought it would be nice to signal as the system was already in place.
Ultimately I moved the swapping of my buffers to a different thread that had higher priority than receive, eliminating the issue, but I could just as easily have not been in a position to do this and there are certainly other times I've thought that the ability to check event signals mid-flight would be handy.
So as Trevor says, it would certainly be nice to know and maybe have it clarified in the manual.
I don't see what information you want clarified.
The manual does say about os_evt_get() that:
You can use the os_evt_get function to identify the event that caused the os_evt_wait_or function to complete.
So the answer to your question
is no. The function will not return the latest set of events. It will return the event that woke up the thread. Any more events happening will (and must) be held back until next time you wait. Because you want to make sure that you don't accidentally lose events.
os_evt_wait_or() should be seen as an "dequeue" function, that "checks out" pending events.
The documentation for os_evt_wait_or() does say:
The event flag or flags that caused the os_evt_wait_or function to complete are cleared before the function returns. You can identify those event flags with os_evt_get function later.
If os_evt_get() could pick up extra flags, then they would not pass that "clear" stage. While os_evt_get() must return old events that has already been cleared by os_evt_wait_or().
So the way to poll for current event state is to call os_evt_wait_or() with zero timeout and see if you got a timeout or not.
Makes sense, hadn't occurred to me os_evt_wait_or() could be used with zero timeout.
FYI: Remember also that only 1 wait/delay RTOS routine can be used per task:
You cannot mix the wait method os_itv_wait and os_dly_wait (or any other delay wait method) in the same task."
http://www.keil.com/support/man/docs/rlarm/rlarm_os_dly_wait.htm
Although this statement does not specifically state os_evt_wait_or() it does have a generic disclaimer within the parenthesis (and os_evt_wait_or() DOES require some type of RTOS timer).
reading through this stuff I come to think of one REAL concern re comms: "You can NOT pause reading" In most cases you can pause sending. I have seen schemes that were guaranteed to allowpausing reading and all have failed
Erik
Thanks for the concern, but no problem, there's a hardware fifo of 16 bytes and receive has priority over send, the only task that's of a higher priority is triggered only when the fifo is empty and sleeps within O(1) time, which is considerably less than the time it takes to fill the FIFO.
Originally I was using DMA, which was so much simpler, however I had a need to detect parity bits and so had to avoid this ultimately :S
You can have multiple wait/delay routines in the task.
But os_itv_wait() consumes the only timing resource for the thread, disallowing any other delay methods for the task. But a task that doesn't use os_itv_set()/os_itv_wait() and have multiple os_dly_wait(), os_evt_wait_or(), ... without a problem. This is because os_dly_wait(), os_evt_wait_or(), ... only needs a timing resource during that specific function call. After call ends, the task-specific variables are available for reuse.
os_itv_set()/os_itv_wait() on the other hand makes permanent use of the task-specific delay variables, to make sure that the thread gets a wake up call again and again and again like a metronome. So when os_itv_wait() returns, the task variables are still used to keep track of when the task should wake up next time.