I am also using GCC v3.3.1 integrated in Ashling IDE
and I don't have problems with the code generated for
ISR.
You should use:
__attribute__ ((interrupt("IRQ")))
or
__attribute__ ((interrupt("FIQ")))
for your ISR's.
Regards
Zdravko Dimitrov
--- "c.barbaro" <c.barbaro@...> wrote:
> Hi,
> I'm working with LCP2138 using the Keil demo board
> and the UVision IDE
> with GNU compiler 3.3.1.
> When I switched from examples to a little more
> complicated interrupt
> handler for the UART0 I started experiencing strange
> problems: hangs,
> reboots, function in the main program called out of
> order...
> Giving a look to the asm listing I see that the GCC
> compiler insert an
> extra 'sub lr, lr, #4' opcode in the isr entrypoint,
> and at the end of
> isr uses the 'subs pc, lr, #4'
> In this way the main program continues the execution
> not from were was
> interrupted, but at an instruction before.
> Here is the isr code and the partial assembler
> listing:
>
> /**
> * Interrupt service routine for UART0 device
> */
> void Uart0_isr(void)
> {
> WORD rxnewend;
> BYTE IrqIdent;
> BYTE i, c;
>
> IrqIdent = U0IIR & 0x0F;
> switch(IrqIdent) {
> case 0x02: // Transmit holding register
> empty.
> IOSET1 = LED1;
> break;
> case 0x04: // RX Data available
> for(i=0;i<4;i++) {
> c = U0RBR;
> rxnewend = rxbufend+1;
> if(rxnewend >= RXBUFSIZE)
> rxnewend = 0;
> if(rxnewend == rxbufini) {
> // Buffer full
> ComStatus |= COM_FULL;
> }
> else {
> rxbuffer[rxbufend] = c;
> rxbufend = rxnewend;
> }
> }
> ComStatus &= ~COM_EMPTY;
> IOSET1 = LED2;
> break;
> case 0x06: // RX Line status Interrupt
> IOSET1 = LED3;
> i = U0LSR;
> break;
> case 0x0C: // Character time out
> c = U0RBR;
> rxnewend = rxbufend+1;
> if(rxnewend >= RXBUFSIZE)
> rxnewend = 0;
> if(rxnewend == rxbufini) {
> // Buffer full
> ComStatus |= COM_FULL;
> }
> else {
> rxbuffer[rxbufend] = c;
> rxbufend = rxnewend;
> }
> ComStatus &= ~COM_EMPTY;
> IOSET1 = LED4;
> break;
> default:
> IOSET1 = LED8;
> break;
> }
> }
>
>
> 241:**** /**
> 242:**** * Interrupt service routine for UART0
> device
> 243:**** */
> 244:**** void Uart0_isr(void)
> 245:**** {
> 459 .loc 1 245 0
> 460 @ Interrupt Service Routine.
> 461 @ args = 0, pretend = 0, frame =
> 0
> 462 @ frame_needed = 0,
> uses_anonymous_args = 0
> 463 03e4 04E04EE2 sub lr, lr, #4
> 464 03e8 7F502DE9 stmfd sp!, {r0, r1, r2, r3, r4,
> r5, r6, ip, lr}
> 465 .LCFI8:
> 248: ****
> 249: **** WORD rxnewend;
> 250: **** BYTE IrqIdent;
> 251: **** BYTE i, c;
> 252: ****
> 253: **** IrqIdent = U0IIR & 0x0F;
> 466 .loc 1 253 0
> 467 .LBB6:
> 468 03ec 0339A0E3 mov r3, #49152
> 469 03f0 8E3283E2 add r3, r3, #-536870904
> 470 03f4 0030D3E5 ldrb r3, [r3, #0] @
> zero_extendqisi2
> 471 03f8 0F3003E2 and r3, r3, #15
>
> ......
> ......
>
> 296: **** default:
> 297: **** IOSET1 = LED8;
> 609 .loc 1 297 0
> 610 059c 0E32A0E3 mov r3, #-536870912
> 611 05a0 0A3983E2 add r3, r3, #163840
> 612 05a4 143083E2 add r3, r3, #20
> 613 05a8 0225A0E3 mov r2, #8388608
> 614 .L71:
> 615 05ac 002083E5 str r2, [r3, #0]
> 298: **** break;
> 299: **** }
> 300: ****
> 301: ****
> 302: **** }
> 616 .loc 1 302 0
> 617 .L50:
> 618 05b0 7F50BDE8 ldmfd sp!, {r0, r1, r2, r3, r4,
> r5, r6, ip, lr}
> 619 05b4 04F05EE2 subs pc, lr, #4
>
> Note that if I slighty semplify the handler (ex.
> removing the for()
> loop), the compiler needs to use less registers,
> don't save the LR
> register, does not insert the sub lr,lr,#4 opcode
> and the code work!!
> Anyone experienced similar problems and has a
> solution?
> Thank you.
>
>
>
>
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.comMessage
Re: [lpc2000] GCC compiler generates wrong code for interrupt handler routines
2006-01-31 by 3gpabko
Attachments
- No local attachments were found for this message.