Hello guys,
I have this situation: I am periodically receiving GPS data, which I store in a buffer.
The buffer is updated by ISR every 1 second and GPS data is received via DMA.
I have created a task that process the buffer every 5, 15 or 30 seconds.
The question is, how to avoid the buffer been updated by ISR while the task is processing it.
I know I could use a mutex to prevent one task updating the buffer while the other task is processing it, but for data received by ISR via DMA I am not clear on how to proceed.
please, any advice will be of help.
The big question is how are you storing that data. You say it is being updated via DMA, which means no one should be accessing that buffer while the transfer is happening, which means you need some careful control on accessing (since the data will come when it comes).
This is why normally that data doesn’t go directly into the “current” readings buffer, but is read into a temporary buffer which is “promoted” to be the current buffer when done (either copied when safe or using multiple buffers and updating a “Current” pointer.)
With multiple buffers, the simple answer is to make a copy of the “Current” buffer pointer at the beginning of the processing, and just use the data there. If new data comes in and updates the current pointer, you just ignore it because you already have what you are going to consider the current pointer.
As long as that processing task can’t take so long to process the data that your acquisition process doesn’t start writing into the data the processing task is using, you are fine.
Thank you for your reply,
It is clear that using mutex is out of question.
Currently I am receiving GPS data continuously using DMA in circular mode and a Full Transfer Complete interrupt.
The buffer size is 1024 Bytes. When the interrupt happens, ISR copy the data received to a global buffer, and it happens about every second, as the GPS frequency is set to 1 second.
My concern was that periodically the data needs to be processed, and while doing it, the buffer might have being updated by ISR, causing inconsistencies on the data.
The double buffer idea might be a good way to solve this.
Thank you again
What I tend to do is when the message complete interrupt comes in, the ISR will trigger a task to parse the text message into a more compact binary form for which a history is keep in another circular buffer (so you can keep the last N readings for processing). If N is small, you might synchronize that conversion with the data access, If it is large enough, the processing just needs (as I mentioned before) grab the “current” pointer when it starts, so data added doesn’t corrupt anything.
Interesting, it’s just the solution that I’m looking for. When sending data at different frequencies, it might be useful to select the latest data when frequency gets lower.
When frequency is higher though, lets say data is sent at the same frequency it’s received, processing needs to be highly optimized. Latency is an issue that needs to be dealt with in any case.
I handle the latency issue by having the task that converts the data post an Event (and a system EventGroup) to indicate that new data is available, then tasks that want to update on the new data as soon as it arrives can do so.
Yes, until now I haven’t try RTOS EventGroup feature. I’m just using direct to task notifications, which work fine for me, but most of time applications are not that simple
I find the EventGroup feature a good fit when something generates data that might have multiple consumers, especially if the consumer isn’t fundamentally fixed by the system design.
GPS data often falls into this category, as many pieces might want to know when new data is available.
I often have a system EventGroup to post such things to that tasks can block for their desired combination of events.