Hi everybody,
Could you please help me: i need to use an uart interrupt routine in a RTX code. I've already found some examples for the uart interrupt routine, but i cannot make it work using tasks. Has anybody an example to show me how to use it. Thanks
When your only buffer is the receive buffer (single-character, double-buffered or full FIFO) in the UART, then it doesn't matter if you turn off the interrupt. If the task isn't consuming the data fast enough and turns on the interrupt again (and the ISR has time to run) before the hw in the UART suffers a overrun, you will lose data.
When you have buffer space in RAM, then keeping the interrupt enabled means that the UART can generate a new interrupt and more data can be buffered in your RAM even if the task hasn't had the time to consume the previous data. But this only works if the interrupt is kept enabled - with interrupts disabled, you are removing the ability to buffer a burst of data into RAM.
Some protocols can't stand any jitter in processing, so it doesn't matter. But many protocols are packet-based and don't care if 1, 10 or 100 characters are buffered, as long as the device has a reasonable response time from the end of the packet until the receiver reacts with an acknowledge or other response data.
When you only allow one character/interrupt and turns off interrupts between receive and processing, then your receive task must run with very high priority. When the receive task is allowed to process data in bursts, you can reduce the receive priority as long as all higher-prio tasks are guaranteed to leave leave some CPU time with a reasonable max interval.
Next thing is that you often have both receive and transmit. And then you normally have interrupts to inform that the UART can accept more data - normally using FIFO or at least double-buffering. With interrupts disabled, you will not keep the outgoing channel full. And not all protocols have a 1:1 relation between incomming and outgoing data.
If you make use of hardware handshake signals, you may want to get interrupts for modem control line changes too, allowing you to block transmission of more characters if the other side isn't ready. Having interrupts disabled, will slow down the detection of these modem control line signals until your receive task have had time to run.
Another thing to consider here is that if you activate a receive FIFO in the UART, then a single receive interrupt need not mean that you have one character available. You may have one (in case of a FIFO timeout), but you might just as well have filled the FIFO past the receive watermark. So with receive FIFO enabled, the ISR would have to continue to pick up characters until the UART status claims it doesn't have any more characters.
Thanks Per and Tamir,
I see your points and I think I probably should change some of my UART setups.
On another on of my setups I'm using a custom protocol where the data in one message could be larger than my buffer (in RAM). This is were I got to disabling the interrupt...
Basically my example was a little mis-leading because what I really do is use the receive interrupt as a start message interrupt and the task than polls for the rest of the message and processes as it receives the message (basically writes a large file to 'disk'. Because the processing is faster than the double-buffered receive I never really missed data.
But the problem with having the read task polling for the rest of the characters, is that the read task must have a high enough prio to poll the UART so you don't miss characters. But if the task busy-loops while polling, then it would starve lower-prio tasks.
A better way is to have a state machine, where read task consumes the number of characters that are available and then wait for more data and continue. So instead of polling by checking the UART directly, you poll by calling the RTOS wait function.
Polling by using a timer would also be "wrong", since that would still give a poll frequency that must be done faster than the maximum character receive speed but without guaranteeing that there is a character available on next poll. Keeping the interrupts enabled and using the RTOS wait function means the task only gets enabled after a timeout (if specified) or when there are one (or more) character available.
Hi everybody, i left this thread for a couple of days and i'm very pleased. I've learnd a lot of thing reading your posts. But i still have a problem with my code. I cannot receive anything from the Uart. I wrote a very simple code: i want to receive a character sended from Hyperterminal (it works, i'v already tested it), read it and managed it in a specific task which print it on the LCD. I'm using an STM32F103ZE. I've looked at many example and i'm quite sure that the code is right and i make some mistakes in the settings, i've putted a flag inside the UART interrupt handler but it is never set to 1. What should i check?