Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Message

Re: GCC compiler generates wrong code for interrupt handler routines

2006-01-31 by unity0724

Hi, Experienced similar problem before.
Got it fixed with moving all local variables to global variables.
(I also kept every C statement in the ISR to be simple, such that
it does not create own local variables on stack)
I think ver GCC 3.4 and onwards has that bug fixed.
Regards

--- In lpc2000@yahoogroups.com, "c.barbaro" <c.barbaro@4...> 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.
>

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.