Best way to implement generic UART drivers?

lopatcbs wrote on Thursday, July 02, 2009:

Hello FreeRTOS forum!

I am in the process of designing a platform using FreeRTOS, and I am scratching my head about how to best implement the serial communication.

There are going to be as many as five UARTs live, and potentially communicating simultaneously. The baud rates are however not very high, typically 9600 baud, but I would like to have the opportunity to go faster one day. The chip is a HCS12XET256 with cpu clock = 73.7 MHz and 8 KB ram (without paging), and most time will be spend waiting for activity on UART(s).

I would like to have a modular design, such that I can hook my high level drivers to any of the UARTs.

My first thought was to simply implement the lowlevel UART drivers with FreeRTOS message queues. That would mean five transmit queues, and five receive queues that simply transfers the data bytes directly. I would get deferred processing and UART abstraction out of the box with minimum effort.

But then I read in the FreeRTOS book on page 89 that "passing individual characters through a queue is extremely inefficient … and not recommended for production code" and I began thinking about other ways to implement the lowlevel driver.

In any case I need to have a buffer that the receive ISR can dump bytes in. And, in any case, I need to make the ISR let other tasks know that there is fresh data in the buffer. So if I roll my own receive buffer and use a semaphore for signalling (which is a minimal message queue), am I not back to the same amount of overhead as the original message queue idea?

Any comments would be appreciated :slight_smile:

Best regards,

rtel wrote on Thursday, July 02, 2009:

I’m not sure what is available on your HCS12, but an efficient way would be to have a DMA pass data to and from the UART and a circular buffer.  Then have the DMA interrupt use a semaphore to unblock tasks when there is enough data to make it worth processing.  If no DMA is present then hopefully there are at least some FIFOs.

The best approach to take is naturally dependent on the characteristics of your application, these are just suggestions.


captnskydiver wrote on Wednesday, July 08, 2009:

I’m trying to use FreeRTOS port for PIC18F devices for past couple of weeks now. PIC18F65J50 has two UART’s and code I wrote for low and high level drivers works with no problems on 19200 on both ports using queues in two stages.
First stage writes/reads single characters from Tx/Rx ISR to queue.
Second stage writes/reads strings (ended with CR/LF or just CR) from one queue to corresponding queue on the first stage.
One ISR and two separate tasks for handling asynchronous serial communication works fine on PIC18F with 48MHz internal clock (12MIPS).

Besides this there is USB driver task, IO processing task and work dispatcher task that coordinates everything. It works.

The only thing that really slows down development are some FreeRTOS internal "bugs" probably related to PIC port, i.e. taskYIELD not working, timeout in queuesend and queuereceive not working etc.

I have lost a lot of time assuming these, and some other things, work as expected.

Anyway, I might post code for UART driver when I get time, best thing is that it is not platform specific (except in 3-4 lines of code) since it relies entirely on FreeRTOS architecture.