I am thinking of using the queuing mechanism described in Blocking On Multiple RTOS Objects (http://www.freertos.org/Pend-on-multiple-rtos-objects.html) to send commands and (optionally) data to a driver. To avoid needing excessive queue memory, data will be passed by reference (pointer). However, the task which posted the command (which owns the data buffer and constructed the data) needs to know when the driver has finished with the data (and hence when it can re-use the buffer). The solution that sprang to mind is to queue a semaphore handle along with the data pointer. The posting task could block on the semaphore (by trying to ‘take’ it) until the driver has finished with the data and unblocked (’given’) the semaphore. However, semaphores don’t work like that (they seem to be set up to indicate that something is ‘available’ not ‘busy’), and it is not allowed for a task to ‘give’ a semaphore if it did not originally ‘take’ it. Any thoughts? I suspect that there is an elegant solution, but I can’t see it… Thanks in advance, Eddie.
Sounds like a reasonable solution, and yes, a task can give a binary or counting semaphore without first taking it. That is how interrupt -> task synchronization works. Maybe it can’t if it is a mutex or recursive semaphore. You probably don’t need to send a semaphore with each message. Instead you can use a bitmap or array to represent each buffer, with some method of mapping buffers to the bit or array position. Have the sending semaphore set the bit to say the buffer is in use before sending it on the queue and blocking on the single semaphore. Have the receiving task clear the bit to say it has finished with the buffer before giving the semaphore to wake the sending task. When the sending task wakes it can check the bitmap or array positions to see which buffers it can recycle.
Thanks for your quick reply! I tried it and it works, but since it isn’t in the spirit of the design (or documentation), I’m worried that I may come unstuck later. When I have a little more time I’ll publish the code… The bitmap array is interesting, and I’ll have a think on it, but I suspect it wouldn’t be general enough.
The “spirit” of a semaphore is to indicate that something is ready, it’s NORMAL usage is for one thing to give it and something else to take it. While it can be used for exclusion by having a task take it, and when done with the resource give it back, that is really the domain for a mutex. Using a semaphore to do a mutex’s job has the problem of priority inversion (which mutexes have code to avoid). One method I have used in cases like this is to have a queue holding pointers to available buffers, When the producer needs a buffer it gets one from the queue, fills it, then sends the pointer to a consumer. When the consumer is done with the buffer, it puts the address back on the “free” queue.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.