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 _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list