rtel wrote on Monday, February 14, 2005:
> Receiving is simple: to avoid race-conditions, only a single task should be
> receiving at any time.
> Xmitting is more interesting. Several tasks should be able to transmit data
> through a single uart. The output of these tasks might (will!) be mixed up.
> Of course, this is not desirable. These are the scenarios I came up with:
Really this is an application design issue - and also very dependent on your available resources. On very resource restrained systems is may be best to design so only one task transmits and one receives (can be the same task of coarse).
If this is not possible then an alternative might be to have a ‘Tx task’. The Tx task has sole control over the COM port and no other task can access it directly. With this scheme tasks that want to send data send the data to the Tx task (this can just be a pointer to a buffer of coarse) via a queue. The Tx task removed data from the queue one message at a time and sends it to the COM port. The queue mechanism ensures mutual exclusion as data is posted to the queue. Having one task move data between the queue and the COM port ensure mutual exclusion of the hardware and ensure one message does not start to be transmitted before the last has finished.
> Before a task can start sending data to the xmit-queue, a semaphore has to be
> taken. After a not-to-be-interrupted chunk has been queued, the semaphore is
> released. At this point another task can take it’s turn by taking the semaphore.
> - small datasize on queue
> - small ram-overhead on sending task
> - simple
> - possibly many messages to queue
> - It may take long for a task to generate it’s chunk
This is a good solution for the reasons you say. It can result in difficult application design - priority inversion and the like.
> The xmitqueue contains a pointer to the data a task wants to xmit. An entry
> in the queue will be processed in it’s entirety before the next queue-entry
> is retrieved. A method must be found so a task knows it’s message has been processed
> and the buffer can be re-used.
> - small datasize on queue
> - few messages on the queue
> - tasks may write to the queue any time
> - (much) more ram needed
> - buffer-free mechanism
I think this is similar to the mechanism I suggest with the Tx task? This is good in that you don’t have to copy too much data around as well. I think this is how I did the I2C driver for the WizNET demo (I would have to refresh my memory).
> How would you do this?
Not the answer you wanted…because its not really an answer…but it really does depend on the particular application needs. My approach with the demo applications is to provide a sample driver, and then note that it is not necessarily the best solution because one solution will never fit all. I would suggest you do the same. Have a driver using either of the mechanisms as a sample, but then you can say in the comments that there are obviously other solutions.