Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

LPC2378-STK interrupt problem in Eclipse

Status
Not open for further replies.

basterzysko

New Member
Hello,

I am newbie in programming ARM7. I have a Olimex LPC2378-STK board and I would like to test IRQ interrupt from Timer1, but it doesn't working.
Timer1 and blink led working without interrupt.

I put the whole code on **broken link removed**.

I have cleared I_BIT in CPSR, in crt.s I have Code:
ldr PC, [PC,#-0x120]

(LPC23xx why it's -0x120 not -0xFF0) and I have set VIC Registers.

I think that enableIRQ() and VIClowlevel.h and .c in my code can be deleted because I have set IRQ bit 0 in crt.s

My software:
openocd v1.0 svn: 1135
new yagarto & toolchain from yagarto.de
gcc: 4.3.2
eclipse: 3.4.1

Maybe anybody has any simple working code with interrupts on this board for Eclipse?

Could anybody look at my code? Plz help and sorry for my English.

Marcin
 
have you ever worked with interrupts before? you do not test them, they call you, you have to tell the compiler that it is an interrupt handler. you need to enable them in the VIC and in the timer and the service routine needs to clear them in the VIC and the timer so the next one can come in.

Dan
 
Last edited:
Maybe anybody has any simple working code with interrupts on this board for Eclipse?
Have a look at **broken link removed** and **broken link removed** on my site. They're for LPC2148, but the code is very similar. Same family.

Could anybody look at my code? Plz help and sorry for my English.
I'll try to have a look after work today.
 
have you ever worked with interrupts before? you do not test them, they call you, you have to tell the compiler that it is an interrupt handler. you need to enable them in the VIC and in the timer and the service routine needs to clear them in the VIC and the timer so the next one can come in.

Dan

I got it everything...

Ok, it will be long post.

First, I don't use function from VIClowlevel.c, because I don't set I_BIT in crt.s and my CPSR in debug is OK, I_BIT is 0 so interrupts are enabled.

This is my crt.s:

Code:
/* Stack Sizes */
.set  UND_STACK_SIZE, 0x00000004		/* stack for "undefined instruction" interrupts is 4 bytes  */
.set  ABT_STACK_SIZE, 0x00000004		/* stack for "abort" interrupts is 4 bytes                  */
.set  FIQ_STACK_SIZE, 0x00000004		/* stack for "FIQ" interrupts  is 4 bytes         			*/
.set  IRQ_STACK_SIZE, 0X00000080		/* stack for "IRQ" normal interrupts is 4 bytes    			*/
.set  SVC_STACK_SIZE, 0x00000004		/* stack for "SVC" supervisor mode is 4 bytes  				*/



/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */
.set  MODE_USR, 0x10            		/* Normal User Mode 										*/
.set  MODE_FIQ, 0x11            		/* FIQ Processing Fast Interrupts Mode 						*/
.set  MODE_IRQ, 0x12            		/* IRQ Processing Standard Interrupts Mode 					*/
.set  MODE_SVC, 0x13            		/* Supervisor Processing Software Interrupts Mode 			*/
.set  MODE_ABT, 0x17            		/* Abort Processing memory Faults Mode 						*/
.set  MODE_UND, 0x1B            		/* Undefined Processing Undefined Instructions Mode 		*/
.set  MODE_SYS, 0x1F            		/* System Running Priviledged Operating System Tasks  Mode	*/

.set  I_BIT, 0x80               		/* when I bit is set, IRQ is disabled (program status registers) */
.set  F_BIT, 0x40               		/* when F bit is set, FIQ is disabled (program status registers) */


.text
.arm

.global	Reset_Handler
.global _startup
.func   _startup

_startup:

# Exception Vectors

_vectors:       ldr     PC, Reset_Addr
                ldr     PC, Undef_Addr
                ldr     PC, SWI_Addr
                ldr     PC, PAbt_Addr
                ldr     PC, DAbt_Addr
                nop							/* Reserved Vector (holds Philips ISP checksum) */
                ldr     PC, [PC,#-0x120]	/* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin  */
                ldr     PC, FIQ_Addr

Reset_Addr:     .word   Reset_Handler		/* defined in this module below  */
Undef_Addr:     .word   UNDEF_Routine		/* defined in main.c  */
SWI_Addr:       .word   SWI_Routine			/* defined in main.c  */
PAbt_Addr:      .word   UNDEF_Routine		/* defined in main.c  */
DAbt_Addr:      .word   UNDEF_Routine		/* defined in main.c  */
IRQ_Addr:       .word   IRQ_Routine			/* defined in main.c  */
FIQ_Addr:       .word   FIQ_Routine			/* defined in main.c  */
                .word   0					/* rounds the vectors and ISR addresses to 64 bytes total  */

# Reset Handler

Reset_Handler:

				.extern TargetResetInit
                 ldr     SP, =_stack_end    @ temporary stack at Stack_Top
                 LDR R0, =TargetResetInit
                 MOV LR, PC
                 BX R0

				/* Setup a stack for each mode - note that this only sets up a usable stack
				for User mode.   Also each mode is setup with interrupts initially disabled. */

    			ldr   r0, =_stack_end
    			msr   CPSR_c, #MODE_UND|I_BIT|F_BIT 	/* Undefined Instruction Mode  */
    			mov   sp, r0
    			sub   r0, r0, #UND_STACK_SIZE
    			msr   CPSR_c, #MODE_ABT|I_BIT|F_BIT		/* Abort Mode */
    			mov   sp, r0
    			sub   r0, r0, #ABT_STACK_SIZE
    			msr   CPSR_c, #MODE_FIQ|I_BIT|F_BIT 	/* FIQ Mode */
    			mov   sp, r0
   				sub   r0, r0, #FIQ_STACK_SIZE
    			msr   CPSR_c, #MODE_IRQ|I_BIT|F_BIT 	/* IRQ Mode */
    			mov   sp, r0
    			sub   r0, r0, #IRQ_STACK_SIZE
    			msr   CPSR_c, #MODE_SVC|I_BIT|F_BIT		/* Supervisor Mode */
    			mov   sp, r0
    			sub   r0, r0, #SVC_STACK_SIZE
    			msr   CPSR_c, #MODE_SYS|F_BIT				/* User Mode */
    			mov   sp, r0

				/* copy .data section (Copy from ROM to RAM) */
                ldr     R1, =_etext
                ldr     R2, =_data
                ldr     R3, =_edata
1:        		cmp     R2, R3
                ldrlo   R0, [R1], #4
                strlo   R0, [R2], #4
                blo     1b

				/* Clear .bss section (Zero init)  */
                mov     R0, #0
                ldr     R1, =_bss_start
                ldr     R2, =_bss_end
2:				cmp     R1, R2
                strlo   R0, [R1], #4
                blo     2b

				/* Enter the C code  */
                b       main

.endfunc
.end

As you can see I_BIT is disabled in USER MODE and I have a line
Code:
ldr     PC, [PC,#-0x120]
. It is -0x120 for LPC23xx, not -0xFF0.

TargetResetInit called in crt.s is function in main.c and it sets PLL and MAM. I put the whole main.c for You:

Code:
#include "LPC23xx.h"

#define PLOCK 0x4000000
void TargetResetInit(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")));

int	main (void) {

	int i;

	IODIR0 = 0x00200000;	// pin P0.21 (LED) is an output, everything else is input after reset
	IOCLR0 = 0x00200000;
	T0TCR = 0x02;									/* Reset timer */
	T0IR = 0xff;									/* Reset all interrupts	*/
	T0MCR = 0x03;									/* Reset TC on match */
	T0MR0 = 1000*12500-1;							/* Set match register (1mSec = 15.000-1 counts) */
	VICVectPriority0 = 0x0000000004;				/* Use it for Timer 0 Interrupt */
	VICVectAddr0 = (unsigned)IRQ_Routine;			/* Set interrupt vector in 0 */
	VICIntEnable = 0x00000010;						/* Enable Timer0 interrupt */
	T0TCR = 0x01;									/* Start timer */

	while(1) {										/* Loop forever */
			i=0;
			i=1;
	}
}

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

void IRQ_Routine (void) {
	IOPIN0 |= 0x00200000;
	T0IR = 0x00000001;						/* Reset interrupt */
	VICAddress = 0x00000000;
}

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

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


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

void TargetResetInit(void)
{
	if ( PLLSTAT & (1 << 25) )
    {
		PLLCON = 1;			/* Enable PLL, disconnected */
		PLLFEED = 0xaa;
		PLLFEED = 0x55;
    }
	PLLCON = 0;				/* Disable PLL */
    PLLFEED = 0xaa;
    PLLFEED = 0x55;
    SCS |= 0x20;			/* Enable main OSC */
    while( !(SCS & 0x40) );	/* Wait until main OSC is usable */
    CLKSRCSEL = 0x1;		/* select main OSC, 12MHz, as the PLL clock source */
    PLLCFG = 0x00010018;
    PLLFEED = 0xaa;
    PLLFEED = 0x55;
    PLLCON = 1;				/* Enable PLL, disconnected */
    PLLFEED = 0xaa;
    PLLFEED = 0x55;
    CCLKCFG = 0x05;			/* Fcco = 300M, Fcclk = 300/(5+1) = 50M */
    while ( !(PLLSTAT & PLOCK));	/* Check lock bit status */
    PLLCON = 0x03;			/* enable and connect */
    PLLFEED = 0xaa;
    PLLFEED = 0x55;
    while ( ((PLLSTAT & (1 << 25)) == 0) );	/* Check connect bit status */
    MAMCR = 0;
    MAMTIM = 3;
    MAMCR = 2;				/* Enable MAM */
}

I set everything using LPC23xx User Manual and Futz file (a bit modified to LPC23xx).

VICVectPriority0 set priority and it is instead of VICVectCntl0

From LPC23xx user manual:
VICVectPriority0-31
These registers select a priority level for the 32 vectored IRQs. There are 16 priority levels, corresponding to the values 0 through 15 decimal, of which 15 is the lowest priority.


And only bits 3:0 we can set, bits 31:4 are reserved.

VICAddress is the same like VICVectAddr in LPC21xx.

When program is running in loop while(1) in main my CPSR = 0x6000005F so 5F = 0101 1111, so it is USER MODE and I_BIT = 0, ant T_BIT = 0, so it's everything OK why I don't need function enableIRQ etc.

If You know why my code doesn't working, plz help me.

Marcin
 
one thing I do not see is where you are branching to the interrupt routine by loading the program counter from VICAddress : 0xFFFF FF00.

The way the interrupt system works is by making the active interupt service routine's address available at this address. at the end of the service routine both the VIC and the interrupting hardware (the timer in this case) need to be told that the interrupt has been serviced.

Dan
 
one thing I do not see is where you are branching to the interrupt routine by loading the program counter from VICAddress : 0xFFFF FF00.

The way the interrupt system works is by making the active interupt service routine's address available at this address. at the end of the service routine both the VIC and the interrupting hardware (the timer in this case) need to be told that the interrupt has been serviced.

Dan

hm... in crt.s in line
Code:
ldr     PC, [PC,#-0x120]

From Hitex ARM7 Insider's Guide LPC2300:
'While IRQ is happening in the VIC unit, the ARM7 CPU is going trough its normal entry into the IRQ Mode and will jump to 0x00000018, the IRQ interrupt vector. In order to enter the appropriate ISR, the address in the VIC Vector Address Register must be loaded into the PC. The assembly instruction shown below does this in a single cycle.
LDR PC, [PC, #-0x0120]
As we are on the IRQ we know the address is 0x00000018 + 8(for the pipeline). If we deduct 0x0120 from this, it wraps the address round the top of the 32-bit address space and loads the contents of address 0xFFFFFF00 (the Vector Address Register).'

Marcin
 
hm... in crt.s in line
Code:
ldr     PC, [PC,#-0x120]

From Hitex ARM7 Insider's Guide LPC2300:
'While IRQ is happening in the VIC unit, the ARM7 CPU is going trough its normal entry into the IRQ Mode and will jump to 0x00000018, the IRQ interrupt vector. In order to enter the appropriate ISR, the address in the VIC Vector Address Register must be loaded into the PC. The assembly instruction shown below does this in a single cycle.
LDR PC, [PC, #-0x0120]
As we are on the IRQ we know the address is 0x00000018 + 8(for the pipeline). If we deduct 0x0120 from this, it wraps the address round the top of the 32-bit address space and loads the contents of address 0xFFFFFF00 (the Vector Address Register).'

Marcin
ok I see it now.... are you sure that file's object code is being loaded into address 0x0? And I see your irq routine named as such but I do not see the compiler being told it is one in the

"void IRQ_Routine (void) {" line.

It should say something like: void irq IRQ_Routine (void) { . it needs to be explicitly declared as an interrupt service routine the way you would declare a static or int.

Dan
 
Last edited:
ok I see it now.... are you sure that file's object code is being loaded into address 0x0? And I see your irq routine named as such but I do not see the compiler being told it is one in the

"void IRQ_Routine (void) {" line.

It should say something like: void irq IRQ_Routine (void) { . it needs to be explicitly declared as an interrupt service routine the way you would declare a static or int.

Dan

in the main.c in prototype of function IRQ_Routine it is
Code:
void IRQ_Routine (void)   __attribute__ ((interrupt("IRQ")));

Maybe anybody has a code with working interrupt for Eclipse on this board?

Marcin
 
in the main.c in prototype of function IRQ_Routine it is
Code:
void IRQ_Routine (void)   __attribute__ ((interrupt("IRQ")));

Maybe anybody has a code with working interrupt for Eclipse on this board?

Marcin

well it looks like it is declared...it is hard to tell since every compiler handles it differently. I know what the hardware wants and can find out how Keil and ARM do it since we use those two compilers here, but that is as much as I can help.
 
OK! I got it worked!

My fault... In LPC23xx every peripheral has related VICVectAddr... and Timer0 is on VICVectAddr4 so it was
Code:
VICVectPriority0 = 0x0000000004;
	VICVectAddr0 = (unsigned)IRQ_Routine;
	VICIntEnable = 0x00000010;

and should be

Code:
	VICVectAddr4 = (unsigned)IRQ_Routine;
	VICVectPriority4 = 0x0000000004;
	VICIntEnable = 0x00000010;

Now everything is working! Thanks for Your help.

Marcin
 
Hi Friends,

Am stuck up in a problem.I am not able to get any characters on the
terminal for the UART project under Eclipse platform(LPC2378).I have
attached the file, I am able to generate the hex file without any errors
but finally no character are echoed on the terminal.The WinRar file is in embdev.net where it can be downloaded under UART + Eclipse topic.
Thank You.

UART + Eclipse - EmbDev.net
 
Hi,

I'm new to LPC23xx programming.

I'm using keil uVision4 for simulation of the peripherals and learning.

I tried the interrupt programming explained above but could not generate interrupt and the ISR routine is not hit at the break point set.

Has anybody simulated the timer0/1/2 interrupt using keil and help me out.

Regards,
Javeed
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top