3
\$\begingroup\$

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?

\$\endgroup\$
  • \$\begingroup\$ I think this question is more about software engineering. Yet too broad. \$\endgroup\$ – Eugene Sh. Jul 14 '17 at 16:47
  • \$\begingroup\$ Next time put software questions on Stackoverflow. \$\endgroup\$ – Jeroen3 Jul 14 '17 at 17:28
  • \$\begingroup\$ Will do. Sorry about that @Jeroen3 \$\endgroup\$ – h3y4w Jul 14 '17 at 17:30
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ I only have one writer and reader. I have a function that reads data from the buffer. It is of course a small case, but in situations where data is being read and an interrupt occurs, depending on the amount of data, it could be overwritten. But wouldn't disabling the interrupt cause me to lose data that is sent? Is there another way? \$\endgroup\$ – h3y4w Jul 14 '17 at 17:51
3
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ A queue is definitely the right way to handle this. \$\endgroup\$ – brhans Jul 14 '17 at 22:23
1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.