LPC P2148 interrupt issues!

Hi,

for a project here at Ghent University, our group has been instructed to build a laser projector. We are using an Olimex LPC P2148 prototype board to do all the processing and modulation but we are very unexperienced at programming or designing an ARM project. For the next step we need to get interrupts working on the P2148 but this is causing us some problems.

I am trying to run interrupts and I am using [this topic as a guideline. I basically copied the code and made a few adjustments to see if I can get everything to work as I want, which is not the case right now. The main code is running a small SOS script flashing the onboard LED2. The interrupt code is flashing an LED externally connected to pin P1.20 every second. When I upload this code (I am using Crossworks), everything works great: SOS is fine and the external LED is flashing as well, but the thing is: everything stops after 8 interrupts!

After the 8th interrupt (the external LED flashes 8 times) the board gets locked up into some eternal loop because the LED2 stays on (no action anymore) and the external LED won’t flash anymore. I have really no idea what is causing this, but I think it has something to do with interrupt registers or flags not set correctly?

I am hoping that somebody can take the time to find out what is wrong and tell me what mistake I made so I can understand this problem? Below is the code I use: one thing, the VIClowlevel.c wouldn’t compile until I replaced arm volatile … (line 6 and 12) with __asm volatile … Does this have anything to do with the problem?

Also: to set or clear a pin I have written a function called setPin and clrPin. Is this a good way of working or is there a good reason why not to do it like this? It’s very convenient since it takes a pin number as input and enables or disables that pin but it has been causing me some trouble, maybe I should start looking there?

Thank you very much in advance!

Nils

/* *********************************************************
               Function declarations
  ********************************************************* */

void Initialize(void);
void feed(void);

void IRQ_Routine (void)   __attribute__ ((interrupt("IRQ")));
void FIQ_Routine (void)   __attribute__ ((interrupt("FIQ")));
void SWI_Routine (void)   __attribute__ ((interrupt("SWI")));
void UNDEF_Routine (void) __attribute__ ((interrupt("UNDEF")));

/**********************************************************
                  Header files
 **********************************************************/

#include <math.h>
#include "LPC214x.h"
#include "VIClowlevel.h"
#define PLOCK 0x400

/**********************************************************
                       FUNCTIES
**********************************************************/

// BEREKEN 2 TOT DE INPUT MACHT
int macht(int input)
{
	int resultaat = 1;
	resultaat = resultaat << input;
	return resultaat;
}

// ZET EEN BEPAALDE OUTPUT PIN AAN
void setPin(int groep, int nummer)
{
	if(groep == 0)
	{
		//IODIR0 |= macht(nummer);
		IOSET0 = macht(nummer);
	}

	else if(groep == 1)
	{
		//IODIR1 |= macht(nummer);
		IOSET1 = macht(nummer);
	}
}

// ZET EEN BEPAALDE OUTPUT PIN UIT
void clrPin(int groep, int nummer)
{
	if(groep == 0)
	{
		//IODIR0 |= macht(nummer);
		IOCLR0 = macht(nummer);
	}

	else if(groep == 1)
	{
		//IODIR1 |= macht(nummer);
		IOCLR1 = macht(nummer);
	}
}

/**********************************************************
                       MAIN
**********************************************************/

int	main (void)
{
	
	int i,j,k;

	    T0TCR = 0x02;                           //reset counter
	    T0IR = 0xff;
	    T0MCR = 0x0003;                         //interrupt and reset on MR0
	    T0MR0 = 0x03938700;                     //compare-hit count
	    VICVectCntl0 = 0x00000024;              //use it for Timer 0 Interrupt:
	    VICVectAddr0 = (unsigned)IRQ_Routine;   //set interrupt vector in 0
	    VICIntEnable = 0x00000010;              //enable TIMER0 interrupt
	    T0TCR = 0x01;                           //enable Timer0
	    enableIRQ();

	   while(1)
           {
	        for(k=0; k<3; k++)
		{
			for(i=0; i<50000; i++)
				setPin(0,11);
			for(j=0; j<50000; j++)
				clrPin(0,11);
		}

		for(k=0; k<3; k++)
		{
			for(i=0; i<100000; i++)
				setPin(0,11);
			for(j=0; j<100000; j++)
				clrPin(0,11);
		}

		for(k=0; k<3; k++)
		{
                        
			for(i=0; i<50000; i++)
                                setPin(0,11);
                        
			for(j=0; j<50000; j++)
                                clrPin(0,11);
		}

                
		for(k=0; k<500000; k++)
                    clrPin(0,11);
	    }

}

/**********************************************************
                      INITIALIZE
**********************************************************/

void Initialize(void)
{
	// Setting Multiplier and Divider values
  	PLL0CFG=0x24;
  	feed();

	// Enabling the PLL */
	PLL0CON=0x01;
	feed();

	// Wait for the PLL to lock to set frequency
	while(!(PLL0STAT & PLOCK)) ;

	// Connect the PLL as the clock source
	PLL0CON=0x3;
	feed();

	// Enabling MAM and setting number of clocks used for Flash memory fetch (4 cclks in this case)
	MAMCR=0x02;
	MAMTIM=0x04;

	// Setting peripheral Clock (pclk) to System Clock (cclk)
	VPBDIV=0x01;
}

void feed(void)
{
  PLL0FEED=0xAA;
  PLL0FEED=0x55;
}

/*  Stubs for various interrupts (may be replaced later)  */
/*  ----------------------------------------------------  */

void IRQ_Routine (void)
{
    int i;
    //IOSET0 = 0x30600000;        //4 LEDs blink
    setPin(1,20);
    for(i=0;i<10000;i++);
    clrPin(1,20);
    T0IR = 0x01;                //clear interrupt
    VICVectAddr = 0;            //end of interrupt - dummy write
}

void FIQ_Routine (void)  {
     int i;
     while (1) ;
}


void SWI_Routine (void)  {
      int i;
      while (1) ;
}


void UNDEF_Routine (void) {
      int i;
      while (1) ;
}

](http://forum.sparkfun.com/viewtopic.php?t=13716)

I have been debugging this script all day now and I have found out some things.

The project board still goes into an eternal loop after a few interrupts, but this is being caused by the interrupt flag not always being cleared!

I watched this particular flag (the first bit of T0IR) in the register as it was being set (interrupt happens) and being cleared at the end of the interrupt IRQ. The thing is: after a few iterations there is an occasion where the flag does NOT get cleared! How is this possible? I am using the exact same code to clear the interrupts as is prescribed in the manual but still there are occasions where this flag does not switch off, causing the system to go into the eternal loop …

T0IR = 0x00000001; // this is the code to clear the particular flag but it does not always work correctly as seen in my debugger!

Anybody that can shed some light on this please?

Thanks!

Try the CrossWorks CTL, it makes interrupt handling very easy.

Thank you for the reply, but is there really no way to get the code working as is? I am using example code from a book on ARM7 programming and verified it by seeing it used in other scripts on the web. Using the Task Library seems complicated for the very simple thing I am trying to get going here … actually I would really like to understand why the flag won’t switch as it should …

Unless CTL really is that much easier to implement than it looks after a first glance at the manual :wink:

Here is the Timer0 initialization code for an application of mine:

 // initialise TIMER0
  T0TCR = 0; /* Reset timer 0 */
  T0PR = 0; /* Set the timer 0 prescale counter */
  T0MR0 = pclk/50 - 1; /* Set time 0 match register to generate an interrupt every 20 ms */
  T0MCR = 3; /* Generate interrupt and reset counter on match */
  T0TCR = 1; /* Start timer 0 */

  // setup CTL stuff for Timer 0
  ctl_set_isr(4, 0, CTL_ISR_TRIGGER_FIXED, timer0ISR, 0);
  ctl_unmask_isr(4);

  x = ctl_get_ticks_per_second();

So basically that’s all it takes to set up interrupts using CTL?

The problem is: my issue has everything to do with the fact that I can’t consistently get the interrupt flag cleared so there is always a time the flag doesn’t get changed and the system hangs … Does your interrupt handler look very different from mine?

Here is my ISR (it does a lot more than the usual ISR and I’ve deleted all that stuff):

static void timer0ISR(void)
{
  char temp[10];
  char s[44];
  u_long crc;
  unsigned int ptr;
  unsigned int C, A, B, E, F;
  unsigned int i;
  static unsigned int n;
  int R;
    

  ticks++;        // increment general delay ticks
  Timer0Count++;  // increment 20 ms ticks
  IO0PIN ^= ACTIVITY_LED; // toggle activity LED 
  C_total = A_total = B_total = E_total = F_total = 0;
  if (!(IO0PIN & PB)) // check if Panic button has been pressed
  {  
    #ifndef NODEBUG
    debug_printf("Panic button pressed!!!\n");
    #endif
    cancel(); // cancel function resets processor using watchdog
  }

  // lots of stuff deleted


  // feed watchdog
  WDFEED = 0xAA;
  WDFEED = 0x55;

  T0IR = 0xFF;  // Clear the timer 0 interrupt
}

Basically you are using a different framework, the CTL, to get interrupts arranged but at the end of the handler you still have to state that the interrupt flag must be cleared, which is the case in your code.

The thing is: this is what’s currently not working with my code. No matter if I switch to CTL to handle the interrupts or not: I will still have to be able to clear the interrupt flag which is not happening consistently right now! I find this very confusing: I literally copied and pasted your code but still it’s not consistently changing the flag, it does so most of the time but in a few instances the flag remains high causing the eternal loop …

I’m starting to think that this has to do with something else, maybe I got a configuration wrong or it has to do with the compiler? Very frustrating!

Try the LPC2000 Yahoo group files, and post the problem there. You are more likely to find someone who can help there.

Interestingly, I created a new project with just the Timer0 interrupt stuff in it and the interrupt isn’t being called (running under the simulator). I’ve probably missed something.

Thanks for the help!

I will ask at the forum you suggested, anyone else that reads this and can help out is greatly appreciated!

I just tried my little program on the actual hardware instead of the simulator and it worked OK. Here is the code:

#include <targets/LPC2148.h>
#include <ctl_api.h>
#include <targets/liblpc2000.h>

// Function prototypes

void Initialise(void);

// globals

unsigned int Timer0Count;


//---------------------- Timer 0 ISR every 20 ms -----------------//

static void timer0ISR(void)
{
  Timer0Count++;  // increment 20 ms ticks
 
  T0IR = 0xFF;  // Clear the timer 0 interrupt
}

int main(void)
{
   Initialise(); // initialisation stuff

   while(1)
    ;
}

//-------------------- initialisation stuff --------------------// 

void Initialise(void)
{
  volatile unsigned int x;

  // initialise PLL

  PLL0CFG=0x24;      // Cclk = 60Mhz
  PLL0CON=0x01;
  PLL0FEED=0xAA;
  PLL0FEED=0x55;
  while(!(PLL0STAT & 0x0400))
	;
  PLL0CON=0x3;
  PLL0FEED=0xAA;
  PLL0FEED=0x55;

  // initialise MAM and VPB

  MAMTIM=0x3;       // 3 cycles to read from FLASH
  MAMCR=0x2;        // MAM functions fully enabled
  APBDIV=0x02;      // Pclk = 30MHz

  // initialise pclk (30 MHz)
  unsigned long pclk = liblpc2000_get_pclk(liblpc2000_get_cclk(OSCILLATOR_CLOCK_FREQUENCY));
 
  // initialise TIMER0
  T0TCR = 0;              // Reset timer 0
  T0PR = 0;               // Set the timer 0 prescale counter
  T0MR0 = pclk/50 - 1;    // Set time 0 match register to generate an interrupt every 20 ms
  T0MCR = 3;              // Generate interrupt and reset counter on match
  T0TCR = 1;              // Start timer 0

  // setup CTL stuff for Timer 0
  ctl_set_isr(4, 0, CTL_ISR_TRIGGER_FIXED, timer0ISR, 0);
  ctl_unmask_isr(4);

   // enable global interrupts
  ctl_global_interrupts_enable();

}

Not sure if that is the case, but you could try setting VICIntSelect to explicitly set it to run in IRQ mode as opposed to FIQ mode.

I got everything running and have a much better understanding of interrupts in the ARM architecture :wink:

Thanks everyone!

Timebutt:
I got everything running and have a much better understanding of interrupts in the ARM architecture :wink:

Thanks everyone!

Timebutt, mind sharing what did you do to fix this problem? Might be helpful if it pops out in the future…