avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] Atmega168: __vector_18 interruptible


From: Julius Luukko
Subject: Re: [avr-gcc-list] Atmega168: __vector_18 interruptible
Date: Thu, 27 Sep 2007 08:36:16 +0300
User-agent: KMail/1.9.7

On Wednesday 26 September 2007, Felipe Hernan wrote:
>    __attribute__((interrupt)) allows to a vector to be interrupted
> re-enabling the global interrupt flag.
>  ┬┐Why I need this?
>
>  During __vector_18 (SIG_USART_RECV | USAR_RX_vect in libc) execution
> I need TIMER0_OVF_vect interruption.
>
>  The reason
>
>  My program implement a communication protocol for microcontrollers
> over RS232/485. The implementation should
> discard any frame (frame is in bytes) malformed or incomplete.
> Actually the way to detect incomplete frame is reading the last byte's
> timestamp and compare it against current, if that delta is
> greater than RX_TIMEOUT, then bytes isn't continuous, if delta isn't
> greater and frame is complete, an user callback is called.
> Additionally the protocol support an send option of  Acknowledge that
> needly use TIMER0 and maybe a _send_
> is called from a user callback.
>
>   Here a possible call stack
>
> __vector_18->rx_protocol->user_callback->send_frame
>
> Where send_frame has Acknowledge option.
>
> The project goal is a subsystem based in events, We dont want to add
> poll functions on main thead nor to add additional loop.
>
> The problem
>
> interrupt attribute not WORKS!. When a RX interrupt is done, the program
> dead.
>
>  I use "naked" attribute in __vector_18 and I add a __asm__("sei" ::)
> as prologue,  __asm__("reti ::") as epilogue and WORKS!
>
> #if defined(__AVR_ATmega168__)
> void USART_RX_vect(void) __attribute__((naked));
> void USART_RX_vect(void)
> #else
> void USART_RXC_vect(void) __attribute__((naked));
> void USART_RXC_vect(void)
> #endif
> {
>         sei();
> #if defined(__AVR_ATmega168__)
>         unsigned char c = UDR0;
> #else
>         unsigned char c = UDR;
> #endif
>         hal_rx_cb(c);
>         asm("reti" ::);
> }
>
> output with -O3:
>
> 00000078 <__vector_18>:
>   78:   78 94           sei
>   7a:   80 91 c6 00     lds     r24, 0x00C6
>   7e:   e0 91 00 00     lds     r30, 0x0000
>   82:   f0 91 00 00     lds     r31, 0x0000
>   86:   09 95           icall
>   88:   18 95           reti
>
> Why happens with __attribute__((interrupt))?!
>

Your approach only works since interrupts are enabled one clock cycle after 
the sei instruction. The USART device's interrupt request is cleared after 
you read UDR/UDR0. With __attribute__((interrupt)) the sei instruction 
propably gets executed a few instructions before you read UDR and therefore 
you will have an infinite loop of USART interrupts.

You can enable interrupts with a normal interrupt

ISR(your_vector_name) 
{
        c=UDR;
        sei();
        /* ISR continues with interrupts enabled */
}

Or did I miss something?

-- 
Julius




reply via email to

[Prev in Thread] Current Thread [Next in Thread]