Forum: ARM programming with GCC/GNU tools GCC Multi_VIC_Channel IRQ Example Code?

Rate this post
 0 ▲ useful ▼ not useful
Greetings:

I am experiencing interrupt detection failures with multiple LPC2103
timer IRQs assigned to different VIC channels. My installation is from
the Olimex ARM-USB-OCD distribution CD. The GCC compiler version is
4.0.2.

With "timer0", match register 0 interrupt assigned to IRQ0 the timer0
interrupt works as expected. When I add a second IRQ, in this case
"timer3", match register 1 to IRQ1 then the IRQ0 interrupt is no longer
detected.

I have read the VIC registers and confirmed both interrupt channels are
enabled and have the proper VIC channel vector addresses. I have swapped
interrupt channels and found the timer0 interrupt still works by itself
but stops when the timer3 IRQ is placed in this case on IRQ0.

The code execution does seem to exit the first handler OK and return to
the main program but then the second pending interrupt is not detected.
If I disable the "timer3" IRQ then the original timer0 interrupt again
works normally. Sometimes the execution becomes trapped within the
"UnDef" forever loop.

For reference I have included my interrupt related code to the end of
this post.

I noticed there is an outstanding GCC bug registered for "arm-elf-gcc"
regarding incorrect IRQ code generation but I don't understand GCC well
enough to determine if it might apply to this case.

It would be most helpful if I could find examples of GCC code for
multiple LPC2xxx VIC IRQs. The examples I have seen so far are for
single interrupt sources. I wonder if anyone in this group knows of
working GCC code with multiple VIC IRQ interrupts that I could study? If
so please either point me to it or post the initialization code and the
associated IRQ handler routines here.

Many thanks in advance for any enlightenment!

Here are some snips of my interrupt related code:

#define VICVectCntl_ENABLE (1<<5)
#define VIC_Channel_Timer0  4
#define VIC_Channel_Timer3  27
#define TxTCR_COUNTER_ENABLE (1<<0)
#define TxTCR_COUNTER_RESET  (1<<1)
#define TxEMR_MAT0_Toggle    ((1<<5)|(1<<4)) //
#define TxEMR_MAT1_Toggle    ((1<<6)|(1<<7)) //

//Function declarations
void tc0_cmp(void)  _attribute_   ((interrupt("IRQ")));
void tc3_cmp(void)  _attribute_   ((interrupt("IRQ")));

/*************************ISR Functions*******************************/
/* Timer0 Compare-Match Interrupt Handler (ISR) */
void tc0_cmp(void)
{
timeval++;
T0_IR = MR0Int; // Clear interrupt flag by writing 1 to Bit 0
VICVectAddr = 0xff;       // Acknowledge Interrupt (rough?)
}
/* Timer3 Compare-Match Interrupt Handler (ISR) */
void tc3_cmp(void)
{
unsigned int a,b,c,d,e,f;
b = T0_IR;
c = T3_IR;
if (T3_IR && MR1Int){//end of 1200 baud period
phaseStepPntr_ui16=0;//point to phase 0 degree 50% duty cycle datum
T3_MR0 = lowToneSinPW_ui16[phaseStepPntr_ui16++];// next set output
high count               // Phase 0 set high count 50% duty cycle
T3_IR = MR1Int;  // Clear match register 1 interrupt flag (by
writing 1 to it)
}
if (T3_IR && MR0Int){
//  else {
T3_MR0 = lowToneSinPW_ui16[phaseStepPntr_ui16++];// set next toggle
count
T3_IR = MR0Int; // Clear match register 0 interrupt flag (by writing
1 to it)
}
VICVectAddr = 0xff;       // Acknowledge Interrupt (rough?)
a = T0_MR0;
b = T0_IR;
c = T3_IR;
}
/********************************Initialization*************************
*************/
/* Setup Timer0 Compare-Match Interrupt         */
/* no prescaler timer runs at cclk = FOSC*PLL_M */
void init_timer0 (void) {
T0_MR0 = ((FOSC*PLL_M)/(1000/10))-1;     // Compare-hit at 10mSec (-1
reset "tick")
T0_MCR = MR0I | MR0R;             // Interrupt and Reset on MR0
T0_TCR = TxTCR_COUNTER_ENABLE;            // Timer0 Enable
VICVectAddr1 = (unsigned long)tc0_cmp;   // set interrupt vector ISR
VICVectCntl1 = VICVectCntl_ENABLE | VIC_Channel_Timer0; // use it for
Timer 0 Interrupt:
T0_IR = 0xff; // clear the interrupt register
VICIntEnable |= (1<<VIC_Channel_Timer0);    // Enable Timer0 Interrupt
}

/* no prescaler timer runs at cclk = FOSC*PLL_M */
/* MR1 used to generate an interrupt at the baud rate */
/* MR0 used to toggle the output pin*/
void init_timer3 (void) {
//  unsigned int a,b,c,d,e;
T3_TC  =  0;
T3_PC  =  0;
T3_PR  =  100; // go slow for initial testing
T3_MR1 = ((FOSC*PLL_M)/1200)-1;       // Compare-hit at baud rate (-1
reset "tick")
T3_MCR = MR1I | MR1R | MR0I;      //Interrupt and Reset on MR1, int
only MR0
phaseStepPntr_ui16 = 1;
T3_MR0 = 1024;               // Phase 0 set high count 50% duty cycle
T3_EMR = TxEMR_MAT0_Toggle;       //Output I/O P0.21, MPU pin #3
T3_TCR = TxTCR_COUNTER_ENABLE;      // Timer3 Enable

for the vector channel
VICVectCntl0 = VICVectCntl_ENABLE | VIC_Channel_Timer3; // use it for
Timer 3 Interrupt:
//  VICIntSelect = (1<<VIC_Channel_Timer3); // classify Timer3 Int as
FIQ
T3_IR  =  0xff; // clear the interrupt register
VICIntEnable |= (1<<VIC_Channel_Timer3);
/*
a = VICIntEnable;   // check
b = T3_TC;
c = T3_IR;
*/
}

Rate this post
 0 ▲ useful ▼ not useful
Thomas m. Alldread wrote:
> ...
> With "timer0", match register 0 interrupt assigned to IRQ0 the timer0
> interrupt works as expected. When I add a second IRQ, in this case
> "timer3", match register 1 to IRQ1 then the IRQ0 interrupt is no longer
> detected.

Shoot in the dark: Did you add a default interrupt-handler (an ISR to
which VICDefVectAddr points to which just acknowledges the interrupt)?
If yes, is this handler called (set breakpoint in it, blink led,
increase a counter...)? Did you test with Timer0 and Timer1 (not 3)? Did
you read the Errata? I don't know it the "timer issue"-errata has been
corrected in the LPC2103 (So far I have not worked the "small" LPCs).

>...
> I noticed there is an outstanding GCC bug registered for "arm-elf-gcc"
> regarding incorrect IRQ code generation but I don't understand GCC well
> enough to determine if it might apply to this case.

Did you compile the complete code in ARM-Mode (no thumb/thumb-iw)? So
far I have not had any problems with this bug as long as the complete
code is build for ARM-mode.

> It would be most helpful if I could find examples of GCC code for
> multiple LPC2xxx VIC IRQs. The examples I have seen so far are for
> single interrupt sources. I wonder if anyone in this group knows of
> working GCC code with multiple VIC IRQ interrupts that I could study? If
> so please either point me to it or post the initialization code and the
> associated IRQ handler routines here.

There should be several codes available which use more than on
interrupt. For example there is Bill Knight's / R O Software LPC2000
UART code. Where both UARTs can be served in "interrupt-mode". Bill's
unmodified code is in the lpc2000 yahoo-group file-archive. Slightly
modified versions are available from my web-page
www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects.
Also see the newlib-lpc code. Both codes also demonstrate using the
naked-attribute and macros to work around the GCC problem with the IRQ
attribute.

Martin Thomas

Rate this post
 0 ▲ useful ▼ not useful
Greetings Martin:

Thank you very much for responding to my post!!!

Martin Thomas wrote:
>
> Shoot in the dark: Did you add a default interrupt-handler (an ISR to
> which VICDefVectAddr points to which just acknowledges the interrupt)?
> If yes, is this handler called (set breakpoint in it, blink led,
> increase a counter...)?

I now have VICDefVectAddr set to an IRQ_Routine forever loop trap. So
far the code has never ended up in the trap. Here is a dump i did of
some of the key VIC registers after initialization. They appear exactly
correct to me:

a = VICIntEnable;   //   0x30 = (timer0 | timer1) int flag bit
positions
b = T1_TC;       //  0x1
c = T1_IR;       //  0x0
d = VICVectCntl0;  //  0x25  = vector slot 0 enabled and timer1 is on
channel 5
e = VICVectAddr;   //  0x2ec = timer 1 ISR entry
f = VICVectAddr0;   //  0x2ec = timer 1 ISR entry
g = VICVectAddr1;   //  0x294 = timer 0 ISR entry
h = VICVectCntl1;  //  0x24  = vector slot 1 enabled and timer0 is on
channel 4
i = VICDefVectAddr; //  0x9a4 = IRQ_Routine    -    forever loop trap
entry

>Did you test with Timer0 and Timer1 (not 3)?

I have now moved over to Timer1 and have the same problem.

>Did  you read the Errata? I don't know it the "timer issue"-errata has been
> corrected in the LPC2103 (So far I have not worked the "small" LPCs).

The Feb 2007 Errata refers to a problem with Timer1 when used in counter
mode. It has to do with the timer counter reset not happening until the
second input pulse. I don't think it is related to this problem.

> Did you compile the complete code in ARM-Mode (no thumb/thumb-iw)? So
> far I have not had any problems with this bug as long as the complete
> code is build for ARM-mode.

As far as I know the program is all in ARM-Mode. The startup file has
the ".arm" statement. I do not know if possibly Thumb could be specified
elsewhere. The word "thumb" does not appear in any of my project files.
I am not sure how to do a positive check. Any suggestions where I should
look? In Eclipse?

>
> There should be several codes available which use more than on
> interrupt. For example there is Bill Knight's / R O Software LPC2000
> UART code. Where both UARTs can be served in "interrupt-mode". Bill's
> unmodified code is in the lpc2000 yahoo-group file-archive. Slightly
> modified versions are available from my web-page
> www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects.
> Also see the newlib-lpc code. Both codes also demonstrate using the
> naked-attribute and macros to work around the GCC problem with the IRQ
> attribute.
>
> Martin Thomas

I must get these examples and study them. Many thanks!!!

With the latest tests I have done the IRQ detection fails for both
vector 0 and 1 when I enable the Timer1 interrupt.

I wonder if I need additional IRQ mode stack size for multi interrupts?
I guess I can find out by taking a look at the examples and doing some
more tests.

I will do some more tests tomorrow.

Thanks again for the help!
Tom Alldread

Rate this post
 0 ▲ useful ▼ not useful
Hi,
from timer match) and the other one from USB on LPC2148. Well, after
trying many things like increasing the call stack for IRQs I did my last
try turning off optimizations (-O0) with gcc 4.2.2. And the problem has
gone. I also tried gcc 4.1.1 and the same happens when optimizations
(even -O1) are on.
I know very well about using volatile variables related things for
avoiding incorrect optimizations and I'm sure my code is not having such
problems. I'm thinking about disabling one optimization at a time and
maybe moving back to older gcc versions.
Well, I suggest you try rebuilding your code with -O0 and see what
happens. Please let me know what you find out.

> Greetings Martin:
>
> Thank you very much for responding to my post!!!
>
>
> Martin Thomas wrote:
>>
>> Shoot in the dark: Did you add a default interrupt-handler (an ISR to
>> which VICDefVectAddr points to which just acknowledges the interrupt)?
>> If yes, is this handler called (set breakpoint in it, blink led,
>> increase a counter...)?
>
> I now have VICDefVectAddr set to an IRQ_Routine forever loop trap. So
> far the code has never ended up in the trap. Here is a dump i did of
> some of the key VIC registers after initialization. They appear exactly
> correct to me:
>
>    a = VICIntEnable;   //   0x30 = (timer0 | timer1) int flag bit
> positions
>    b = T1_TC;       //  0x1
>   c = T1_IR;       //  0x0
>   d = VICVectCntl0;  //  0x25  = vector slot 0 enabled and timer1 is on
> channel 5
>   e = VICVectAddr;   //  0x2ec = timer 1 ISR entry
>   f = VICVectAddr0;   //  0x2ec = timer 1 ISR entry
>   g = VICVectAddr1;   //  0x294 = timer 0 ISR entry
>   h = VICVectCntl1;  //  0x24  = vector slot 1 enabled and timer0 is on
> channel 4
>   i = VICDefVectAddr; //  0x9a4 = IRQ_Routine    -    forever loop trap
> entry
>
>
>>Did you test with Timer0 and Timer1 (not 3)?
>
> I have now moved over to Timer1 and have the same problem.
>
>>Did  you read the Errata? I don't know it the "timer issue"-errata has been
>> corrected in the LPC2103 (So far I have not worked the "small" LPCs).
>
> The Feb 2007 Errata refers to a problem with Timer1 when used in counter
> mode. It has to do with the timer counter reset not happening until the
> second input pulse. I don't think it is related to this problem.
>
>> Did you compile the complete code in ARM-Mode (no thumb/thumb-iw)? So
>> far I have not had any problems with this bug as long as the complete
>> code is build for ARM-mode.
>
> As far as I know the program is all in ARM-Mode. The startup file has
> the ".arm" statement. I do not know if possibly Thumb could be specified
> elsewhere. The word "thumb" does not appear in any of my project files.
> I am not sure how to do a positive check. Any suggestions where I should
> look? In Eclipse?
>
>>
>> There should be several codes available which use more than on
>> interrupt. For example there is Bill Knight's / R O Software LPC2000
>> UART code. Where both UARTs can be served in "interrupt-mode". Bill's
>> unmodified code is in the lpc2000 yahoo-group file-archive. Slightly
>> modified versions are available from my web-page
>> www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects.
>> Also see the newlib-lpc code. Both codes also demonstrate using the
>> naked-attribute and macros to work around the GCC problem with the IRQ
>> attribute.
>>
>> Martin Thomas
>
> I must get these examples and study them. Many thanks!!!
>
> With the latest tests I have done the IRQ detection fails for both
> vector 0 and 1 when I enable the Timer1 interrupt.
>
> I wonder if I need additional IRQ mode stack size for multi interrupts?
> I guess I can find out by taking a look at the examples and doing some
> more tests.
>
> I will do some more tests tomorrow.
>
> Thanks again for the help!
> Tom Alldread

• $formula (LaTeX syntax)$