Question about serial.c and buffered IO

modiallen wrote on Tuesday, August 21, 2012:

the developer of FreeRTOS who made the Demo application said in the serial.c about the implemented ISR, that there Implementation of the ISR is not an efficient implementation.

they rocommended the DMA or a RAM ring Buffer.
i implement a ring buffer, and every time a siganl is received in the RS232, the ISR will be called and write the new byte in this ring buffer.

now my question, what is the advantage of the ring buffer, if every time the received byte will trigger an interrupt.
it can be send through a queue too. or it will take more time because the API-call of xQueueSendFromISR.

Thank you.

rtel wrote on Tuesday, August 21, 2012:

Ideally you would not generate an interrupt on each character if you have a FIFO, but even if you do interrupt on each character the overhead of just writing that to a buffer is much less than copying it into a queue using a function call.  Once there are enough characters received, or there is a break in transmission (if your UART has that functionality), you can unblock a task to process the characters using a semaphore.  While a semaphore ultimately uses a queue structure, it does not require any data to be copied.  Were a queue to be used you could potentially unblock a task on each received character, rather than just once when there was something to process.


modiallen wrote on Wednesday, August 22, 2012:

thank you for your reply.
and if i want to use the semaphor for protecting the ring buffer, because the ring buffer will be a shared data between the interrupt and the task, and therefor it must be protocted.

i.e. bevor any operation on the ring puffer, the semaphor must be checked.
in this case the semaphor will be checked in the ISR and then the received byte will be written in the ringbuffer.
after that the semaphor will be given again.

in this case the overhead is almost the same like sending this byte with a queue. or is it still much less than a queue?

Best Regards.

edwards3 wrote on Wednesday, August 22, 2012:

Ring buffers normally have separate read and write pointers. Write is accessed from the ISR, read from the task, so there is no need to use a semaphore from the interrupt particularly as the interrupt cannot wait for the semaphore.

modiallen wrote on Thursday, August 23, 2012:

thank you edwards.

but the problem of the shared ringbuffer stil be not handled.
because the read-function can be interrupted, and the result of this interrupting will be data-inconsistency.

richard_damon wrote on Friday, August 24, 2012:

The idea of having the ISR fill a buffer (ring or otherwise), and then signaling the task after a “block” of data is received is that while the ISR is filling, it “owns” that part of the data buffer, and after signaling the task “owns” that block and the ISR take control of a new section of the buffer. Since there then is no contention on access, the semaphore provides sufficient guarding.

It is also possible to be careful in how you do your operations and as long as the access to the buffer pointers are atomic , to avoid contention problems between ISR and task. This might need declaring the pointers as volatile to avoid improper optimizations.