Hi,
This has come up a couple of times recently, I’ve searched for an elegant solution and I’ve been down several avenues and I have a solution, but it does make me wonder why it’s not possible to achieve using more lightweight solutions.
Essentially I have this kind of arrangement:
“Work Task”.
The work task consists of a loop, that continually runs (yielding as necessary), it has to run in a “spin loop” because it’s accepting data via SPI and the bus is running at 24MHZ and there’s a reasonable amount of data coming in that I have to shift out over USB.
I’ll use CDC as an example, but any bulk interface will do with the appropriate “scaffolding”.
When there is no host connected to the CDC port I want the task to effectively sleep, I don’t need to know what’s coming over the SPI because I’m bot sending it on.
This obviously minimises the load, while CDC is not connected, the worker task is not looping.
The worker task needs to loop because of the speed of the SPI bus, I’m using an STM32FX07 CPU and because of the data rate, I’m using DMA to transfer it into a circular buffer.
Now the STM32 only has half and full complete messages and as I don’t know how many bytes are going to be sent, my only real way of dealing with this is to have a large buffer which the DMA writes to, and for me to continually check to see if new data is available and if so, put it into a packet and shove over USB.
All good.
But, it’s the case where the CDC port is not connected, I want the task to block, there’s no need for it to run, no need to attempt to put anything over the CDC port or read.
Now vTaskSuspect and vTaskResume go out the window, I’ve read plenty about them and lots of posts from Richard about using them and potential race conditions, so they’re out.
The next best solution looked to be Task Notifications, they’re lightweight and they look ideal, however, there’s no “xTaskNotifyStateClearIndexedFromISR” which means I can’t block the task from an ISR.
My intention was to have a notification bit for “Connected”, this bit could be set and cleared from an ISR (i.e the CDC line state packet) and then all that the worker task needs to do is check if that bit is set, in the check it would be set to not clear it.
So I got stuck there.
Finally I did manage to use an event group to create this logic because I can both set and clear from an ISR context and in my worker task I can wait for that bit to be set and at the same time not have it automatically cleared, so in this case the task simply waits for that bit and as long as the host is connected to CDC then the task will run, the moment it disconnects, the ISR clears that bit in the event group and back to sleep we go.
This works really well, but I can’t help but wonder if there is some underlying reason why the more lightweight notifications don’t have the ability to clear the notification from an ISR context, since the behaviour is similar to event groups.
Have I missed something obvious?
Is there a better way of approaching this paradigm?
Thanks