Hi, I wrote a simple PWM code and it was working fine. But when I tried to enable the match interrupts, the code just get gets stuck inside the interrupt handler while stepping in the debugger.
Can someone help on this, what is wrong with my interrupt initialization?
#include <LPC23xx.H> #include <stdio.h> #define I_Bit 0x80 #define F_Bit 0x40
#define SYS32Mode 0x1F #define IRQ32Mode 0x12 #define FIQ32Mode 0x11 static unsigned long sysreg; #define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode } #define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf, sysreg } #define PLOCK 0x04000000 #define PWMMR0I (1<<0) #define PWMMR0R (1<<1) #define PWMMR1I (1<<3) #define PWMMR2I (1<<6) #define PWMMR3I (1<<9) #define PWMMR4I (1<<12) #define PWMMR5I (1<<15) #define PWMMR6I (1<<18) #define MR1I_FLAG (1<<1) #define MR2I_FLAG (1<<2) void initClocks(void); void initTimer0(void); void setupPLL0(void); void feedSeq(void); void connectPLL0(void); void initPWM(void); void initClocks(void); __irq void PWM1Handler(void); void initPWM(void);
int main() { initClocks(); initPWM(); for(;1;); }
void PWM1Handler(void) __irq { unsigned int regVal; unsigned int i=0; regVal = PWM1IR; IENABLE; if (PWM1IR&PWMMR0I) { printf("match 0 occured"); i++; } else if (PWM1IR&PWMMR1I) printf("match 1 occured"); else if (PWM1IR&PWMMR2I) printf("match 2 occured"); else if (PWM1IR&PWMMR3I) printf("match 3 occured"); else if (PWM1IR&PWMMR4I) printf("match 4 occured"); else if (PWM1IR&PWMMR5I) printf("match 5 occured"); else if (PWM1IR&PWMMR6I) printf("match 6 occured"); PWM1IR = regVal; IDISABLE; VICVectAddr=0; }
void initClocks() { setupPLL0(); feedSeq(); //sequence for locking PLL to desired freq. connectPLL0(); feedSeq(); //sequence for connecting the PLL as system clock }
void initPWM(void) { PCONP |= (1<<6); PCLKSEL0 |= ((1<<12)|(0<<13)); PINSEL4 |= 0x00000555; PINSEL4 &= ~0x0000AAA; PWM1TCR = 0x02; PWM1PR = 59999; PWM1MCR = 0x0004924B; PWM1PCR = (1<<9)|(1<<10)|(1<<11)|(1<<12)|(1<<13)|(1<<14); PWM1MR0 = 10000; PWM1MR1 = 1000; PWM1MR2 = 2000; PWM1MR3 = 3000; PWM1MR4 = 4000; PWM1MR5 = 6000; PWM1MR6 = 7000; PWM1LER = 0x7F;
VICVectAddr8 = (unsigned)PWM1Handler; VICVectPriority8 = 0x0F; VICIntEnable |= (1<<8);
PWM1TCR = 0x09; }
//---------PLL Related Functions :---------------
void setupPLL0(void) { PLLCON = 0x01; PLLCFG = 0x04 | (1<<16); SCS |= 0x20; while( !(SCS & 0x40) ); CLKSRCSEL = 0x01; }
void feedSeq(void) { PLLFEED = 0xAA; PLLFEED = 0x55; }
void connectPLL0(void) { while( !( PLLSTAT & PLOCK )); PLLCON = 0x03; }
Your enable/disable IRQ can't work for this task.
As written, they might be used by the main loop to turn off interrupts when implementing a critical section.
With interrupt nesting you will corrupt LR if the enable/disable code doesn't make a copy - all interrupt handlers shares the same register. But you absolutely must not try to save state to a global variables - an int variable isn't able to store a new value for every level of nesting. That's what the stack is good for.
I think it might be that the Keil code was for their older compiler. Alas, I don't have access to the code I'm using right now.
If I understood correctly you mean to say that I should change the IENABLE/IDISABLE definitions as mentioned by John Linq. In that code the stack is used to store the state.
But When I do that, I get compilation error that LR and SP are undefined. How do we address this error??
Not sure I can help much more without access to my own code. But there is no way the code you are using can work. Nested interrupts means that you must be able to store multiple copies of the register values.