My next question is whether or not it’s necessary to use the FreeRTOS SPI driver in specific circumstances. In my test case, I see some fairly strange behaviour when making SPI-related calls from within FreeRTOS tasks, perhaps a result of tasks not blocking and SPI transactions being non-atomic.
Is there a means of making SPI work from within FreeRTOS tasks, perhaps by holding up the RTOS system long enough to complete these and then resuming RTOS?
Of course, begs the question as to why use FreeRTOS in the first place, but perhaps this question will reveal a simpler solution for me than having to re-write our HAL.
I generally find that the vendor supplied generic I/O functions, while normally useful for a ‘typical’ single threaded application, tend to be lacking for a multi-threaded applications like those using FreeRTOS. The exception being for those specificailly written for FreeRTOS or working with a generic OS wrapper. The biggest issues being they tend to ‘spin-wait’ for the I/O and have no protection for being used in multiple threads.
Sometimes you can live with these limitations, more often you need to adapt them (or at least wrap them) for use in a FreeRTOS application.
For my work the SPI is not used by multiple tasks.
My SPI drives a FTDI graphics controller, which requires a certain set of command transactions to be received in an established group (a start of command set message, followed by various LCD commands, and completed by an end of command set message). These are, ideally, sent in a contiguous stream. A timer-based xTask is running through the command set periodically as this updates the LCD screen.
I have two theories as to why my LCD results are variable. One has to do with how tasks are managed.
Question: is it possible that a timer-based task may be re-spawned before the other instance is complete? If this happens, it explains a lot. And if so, how can I block the task from re-spawning at the next timer event if it’s not done?
Another theory is that the event is put on hold for other tasks. The time unserviced somehow bothers the SPI, perhaps in mid-transmission, and bolluxes up the works.
Question: is this a possibility? If so, how to make the SPI stuff unhindered?
Also, I am a bit perplexed as to how to use the FreeRTOS SPI driver and its relation to FLEXCOM. FLEXCOM is what is being used presently. Would I continue to use FLEXCOM but just replace the init, read and write functions?
Question: is it possible that a timer-based task may be re-spawned
before the other instance is complete? If this happens, it explains a
lot. And if so, how can I block the task from re-spawning at the next
timer event if it’s not done?
By which, do you mean the SPI is managed inside a software timer
callback function? That might not be the best way in any case if it
prevents the callback function returning for a long time. Try to keep
callbacks short because, while the callback is executing, no other
callbacks can execute.
That answers your question too - no only one time callback function can
execute at once as all the timer callbacks execute in the context of the
same timer service task.
That answer is only valid if my assumption is correct - you are talking
about timer callbacks and not tasks.
Another theory is that the event is put on hold for other tasks. The
time unserviced somehow bothers the SPI, perhaps in mid-transmission,
and bolluxes up the works.
API is synchronous so it would only be an issue if the LCD device timed
out if the SPI clock was interrupted by a higher priority task.
The best way to do this would be create a buffer than contains the
message you want to send to the LCD, then DMA the buffer to the SPI port
and have the hardware manage the transmission. If you hardware does not
allow that then at least control the transmission using interrupts
(start a transmission, have the SPI interrupt send the next data, until
all data is sent, then disable the interrupt until the next transmission).
The task callback performs the periodic LCD screen refresh. It does so by issuing a series of commands, which eventually are sent over the SPI buss to the FTDI graphics controller. I’m not aware of any other way to make this stuff happen other than within a task which is triggered to run every [n] ticks, with the code that needs to be run within the callback function. If there’s another way, please lead me to a technique.
In your suggestion, where the SPI transmission is buffered to DMA and then handed off to the SPI driver, would this driver be the built-in ASF, or would I have to use the FreeRTOS driver?
An example of this, if you know of one, would save me a lot of agony