AVR Freaks

AVR GCC forum - UART+ISR_NOBLOCK=CRASH?

jalla2000 - Feb 22, 2008 - 02:44 AM
Post subject: UART+ISR_NOBLOCK=CRASH?
I have data coming in from gyros and accelerometers and I need to send and receive with the UART at 115k baudrate. Is it true that using ISR with the NOBLOCK-parameter will cause infinite recursion when receiving? How can I then receive data from the UART and still be sure to not miss my precious sensory data interrupts? Is my only option to check the receive-complete flag very often in my main loop? Shocked

Any thoughts are appreciated

And why do people keep saying that they don't like nested interrupts and that they should be avoided is possible? Question

(atMega64 running at 16MHz and AVR-GCC)
kmr - Feb 22, 2008 - 02:58 AM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
It can cause infinite recursive. The UART has at least a one byte buffer (ie, it holds the last received character in UDR until another character has completely finished). At 115.2Kbps, each character of 8N1 takes 87 usec. Assuming you are running your AVR at 8MHz, you have nearly 900 clock cycles between characters. I make my UART RX ISR's store into a circular buffer and the ISR takes less around 40 clock cycles. That gives you plenty of latency room responding to an interrupt (over 800 clock cycles). If you need more computaton, you can clock you AVR at 14.7456 or 18.432MHz.

Nested interrupts can be used, and I do use them in special circumstances. But, they have the potential for causing serious trouble (like infinite recursion that you mentioned) if you are not careful with your interrupt handling.
jalla2000 - Feb 22, 2008 - 01:21 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
Thanks Kevin! I was afraid that ISR(UART0_recv, NOBLOCK) would always generate interrupts before I could reset the UART-complete flag by reading out UDR. I think 900 cycles should be enough Smile
dl8dtl - Feb 22, 2008 - 01:56 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
Btw., you can nest interrupts after fetching UDR.
jalla2000 - Feb 25, 2008 - 02:59 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
I am not sure I understand properly...

If I define: ISR(USART0_RX_vect, ISR_NOBLOCK)

Will this ever block external interrupts on INTn? I get interrupts from my accelerometer and I can not afford to miss it...

Quote:
Btw., you can nest interrupts after fetching UDR.


Can't I nest interrupts before fetching UDR? Like jumping to an INTn interrupt between the prologue of the UART interrupt and the reading of UDR?
lfmorrison - Feb 25, 2008 - 03:20 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
Actually, the scenario you describe *WILL* result in infinite nested interrupts with no progress.

The USART Receive Complete interrupt perpetually triggers as long as there is new data available in the receive buffer waiting to be read. The only two ways to clear the receive complete interrupt flag are by:
- reading the UDR to flush the byte out of the receive register, or
- shutting off the USART's receive subsystem entirely.

The CPU's act of jumping through the USART receive interrupt vector DOES NOT automatically clear the interrupt flag; therefore, if the ISR begins execution with interrupts initially enabled, the result will be that there will be perpetually recursive interrupts.

The solution, as Joerg suggested, is to start the USART with interrupts initially disabled (which is the default behaviour). Then read the UDR to clear the receive buffer (do so repeatedly, because newer AVRs have a multi-byte receive buffer), before re-enabling the global interrupt flag manually.

In fact, if out-of-order byte reception is a potential problem (it usually is), then you'll probably also want to temporarily disable the receive interrupt mask inside the ISR, just after flushing the receive buffer, and just before re-enabling the global interrupt mask.
curtvm - Feb 25, 2008 - 03:24 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
With the RXC flag not cleared until reading UDR, it may be better to use a 'normal' interrupt with an 'sei()' after reading UDR.

If irq's are enabled before reading UDR, and INT0 fires, you will still have RXC set, which means when INT0 is done you are back to the rxc irq for one instruction, then since irq's are back on (INT0 irq turned them back on) the RXC flag causes another rx interrupt. Now you are into the rxc interrupt twice for the same RXC flag. Don't ask me to think this through any farther, as I'm now getting confused.

The ISR_NOBLOCK would be 'ok' for irq's that automatically clear the irq flag.

I think.

(out-typed by Luke's post in both speed and content)
jalla2000 - Feb 25, 2008 - 04:37 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
i guess i cant use interrupts for the UART reception then, since nesting will cause infinite recursion and not-nesting will cause loosing some other interrupts... right?
lfmorrison - Feb 25, 2008 - 04:53 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
How frequently is sensory data being provided? How much time are you spending inside the serial interrupt? Could some of the data processing be taken out of the serial interrupt and moved to the main loop?
jalla2000 - Feb 25, 2008 - 05:12 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
i got 3 gyros and a triple accelerometer and one compass connected to the SPI bus. i think all off them will have new data somewhere around 100Hz. i am using some voltage dividers on the accelerometer, but i think i still will be able to read out data from all slaves pretty quickly. i dump all captured data to UART0 connected to a bluetooth device. i also want to forward all strings received from a GPS on UART1. i bet you might have a clue about what i am making now Smile thank you for your help guys!
kmr - Feb 25, 2008 - 05:19 PM
Post subject: RE: UART+ISR_NOBLOCK=CRASH?
Since you'll be receiving other (non-UART) interrupts around 100Hz, you have 10ms between non-UART interrupt. That's plenty of time to have interrupts off during your UART RX ISR. You won't loose any interrupts unless two or more of the same interrupts get flagged during your ISR. If there are any interrupt flagged during your ISR, then'll those interrupts will be fired after the RETI instruction at the end of your UART ISR.
jalla2000 - Feb 25, 2008 - 05:35 PM
Post subject: Re: RE: UART+ISR_NOBLOCK=CRASH?
kmr wrote:
You won't loose any interrupts unless two or more of the same interrupts get flagged during your ISR. If there are any interrupt flagged during your ISR, then'll those interrupts will be fired after the RETI instruction at the end of your UART ISR.


Thank you kmr! this was very clarifying! So if I use a blocking ISR for the UART, then the INTn interrupt will be handled after the RETI? That sounds good! I don't think any of the external interrupts flags will be set twice during the UART routine. Hmmm... So an interrupt occurring between cli() and sei() will not be lost right? Thats good news. Tell me if i got it wrong.
kmr - Feb 25, 2008 - 05:45 PM
Post subject: RE: Re: RE: UART+ISR_NOBLOCK=CRASH?
That's right. Read the datasheet to see show interrupt flag bits get set and processed as well as interrupt handling in general. Basically, most sources of interrutps will set a flag that will cause an interrupt to be generated when the global interrupt bit in SREG is 1. You can do processing on those flags to clear pending interrupts (assuming that the I bit in SREG is cleared -- otherwise the interrupt would have already been set) or to create software interrupts. So, you other interrupts should set a flag of some sort that will cause an interrupt to be generated when the I bit in SREG is set to 1. But, do read the datasheet about those sources of non-UART interrupts you'll be processing.
All times are GMT + 1 Hour
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits