1
\$\begingroup\$

I would like to know what would happen if a Serial Terminal were to send a large amount of data to a PIC/AVR, for example over USART interrupt, which was then interrupted by a higher priority interrupt like a timer, which would postpone the data transfer. Would the data be lost? Or does the Serial Terminal have a buffer before sending, and hold on to the data until we go back to the receive interrupt?

For exmaple I am using an atxmega128a1, and am using this interrupt to receive bytes:

//interrupt to receive a byte 
ISR(USARTC0_RXC_vect){                      //ISR for when receive flag is set
if(FIFO_Put(&RxFIFO, USARTC0_DATA)){        //put data into receive FIFO
    USARTC0_STATUS |= USART_RXCIF_bm;       //write 1 to clear bit
}
}

If I send a large amount of bytes over a serial terminal at one time, this interrupt will trigger many times to receive every byte.

I also have a timer interrupt of a higher priority which may take a long time to complete:

ISR(TCC0_OVF_vect){
    AXISid n = X;
    static BOOL cycle;
    TimerAxisInterrupt(n, &cycle);
} 

To re-iterate, my question is, if the higher priority interrupt occurs during a large data receive transfer, will any data be lost?

If relevant: I am sending the USART data over rs232 using a max3232 logic converter. I have the handshaking lines and RTS CTS lines looped such that i am only using the Rx and Tx lines.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Assuming no handshaking, you will not lose any data if the UART interrupt is serviced often enough to keep whatever hardware buffer it has from overflowing. Typically that's at least one character, but it may be many characters depending on the chip (more powerful chips tend to have more bytes of buffer).

In my experience you cannot depend on XON/XOFF handshaking when the buffer size is small and the sender is a PC- it may send quite a few characters before it gets around to choking off the flow.

So if the buffer depth is one character, and the baud rate is such that one character takes 1msec then you must not take away more than 1msec in your higher priority interrupt or you could lose data (a bit less because you have to account for the time in the UART ISR to respond and pluck the incoming character from the buffer, and you also should account for the situation where the UART interrupt is in progress when interrupted (look at it occurring just before and just after the incoming character was read)

There are various ways of dealing with the situation where you have to have two interrupts with fast response. One way (usually the best way) would be to not do so much in your timer interrupt- interrupt service routines are best used for getting into and out of briskly). Another would be to implement a buffer in memory and set your UART interrupt to the highest priority (just stuff the received character into a circular queue, increment the write pointer modulo buffer size and return- you can check the equality if read and write pointers to see if the queue is empty). There are still other approaches depending on the requirements and the processor- maybe you don't need to have the timer routine with such high priority, or maybe you dynamically change the priority once it has finished the critical stuff then change it back to high priority, allowing it to be interrupted by the UART ISR.

More powerful processors will have larger buffers or DMA that will allow the processor to go walkabout for a great many characters before data loss occurs.

TL;DR You can predict this by profiling your timer interrupt and ISR interrupt code to find the maximum execution time and comparing with the minimum time to fill the buffer (at the maximum baud rate).

\$\endgroup\$
6
  • \$\begingroup\$ If the timer interrupt is being used for timing functions like pulse generation,timeouts etc, Shouldnt timer interrupt be given the highest priority? \$\endgroup\$
    – AlphaGoku
    Apr 6, 2016 at 6:36
  • \$\begingroup\$ @AkshayImmanuelD Totally application dependent. If you can stand a bit of jitter from the UART interrupt maybe not. Sometimes it's non-intuitive. For example, I have a very complex controller with many critical operations, but the highest priority interrupt is to toggle a sound transducer. The other operations are far more important but not as urgent and a few microseconds jitter has no practical effect on them (but you'd hear it in the sound). \$\endgroup\$ Apr 6, 2016 at 6:48
  • \$\begingroup\$ I agree. If u can allow a timeout tolerance, i see no reasin why timer interrupt must be highest priority. But then again, totally application specific \$\endgroup\$
    – AlphaGoku
    Apr 6, 2016 at 7:25
  • \$\begingroup\$ @SpehroPefhany thanks for your reply. So to make sure I understand, I have a baud rate of 19200 with 10 bits per character (1 start 1 stop 8 data bits). So thats roughly 521us per character. Therefore to prevent data loss, my higher priority interrupt(s) should take no longer than 521us, or with a 32MHz clock, should not be more than 16667 instructions. Correct? \$\endgroup\$
    – Sam Bucca
    Apr 8, 2016 at 3:21
  • \$\begingroup\$ @SamBucca More like the sum of the two ISR execution times inclusive of latency and context save, if you have only one buffer byte. Also some instructions may take more than one cycle. \$\endgroup\$ Apr 8, 2016 at 11:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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