I have a [circular] buffer that is written with incoming data from the USART using IRQ. I also have other tasks reading data from the buffer as well. What should I do in a scenario where a task has the mutex for the buffer but IRQ executes with incoming data? Should I create a tmp variable which stores the data and sets a flag in IRQ so that data gets written to the buffer after the mutex is given?
A FIFO buffer should not have a concurrency problem.
Obviously it will have when used with multiple writers or readers. But this device is not suitable for that purpuse. Use packets instead of streams if that is what you are after.
However, the implementation might have. Therefore the interrupt may not be executed during manipulations on the buffer.
In other words, the read/modify/write of the pointers may not be interrupted by the uart irq.
Other answers suggest that you should use the functions provided my FreeRTOS.
This is excellent advice. The FIFO or queues in an RTOS should have been made to be atomic to all relevant threads to prevent issues.
If you are afraid you will lose data you have two options:
- Increase size of buffer.
- Slow down data rate.
The "atomic" operation of the buffer operation should be less than the time required to receive one new byte, otherwise you will lose data. It may also need to survive the jitter induced by higher priority events. This shouldn't be a problem though, uart interrupts are supposed to be very short and should be able to preempt everyting else.
FreeRTOS queues can handle it. There may be some overhead - I don't know how much data are your receiving. Just make sure to use
xQueueSendFromISR or other function ending FromISR when doing something to the queue from interrupt context.
Consider not letting the UART IRQ execute while the buffer is being manipulated by another task. In other words, disable the UART interrupt while another task is reading from the buffer.
Then ensure that the reading task doesn't leave the UART interrupt disabled for so long that the UART would drop a character. The only thing the reading task should do while the interrupt is disabled is copy the character from the buffer and adjust the buffer pointer. Don't try to read multiple characters and parse them while the interrupt is disabled.
If you only have one task that reads from the buffer and only the interrupt handler that writes to the buffer then consider whether you really need the mutex. If the reading task disables the interrupt then nothing else will interrupt and possibly corrupt the buffer until the reading task has finished. And the interrupt handler cannot be interrupted by the reading task so it's buffer access cannot be interrupted/corrupted. I suspect the mutex is only necessary if you have multiple readers.