 |
SparkFun Electronics MicroController Ideas and Support
|
| View previous topic :: View next topic |
| Author |
Message |
futz
Joined: 06 May 2008 Posts: 71 Location: Vancouver, B.C. Canada
|
Posted: Fri Jan 16, 2009 12:52 am Post subject: Can't get LPC2148 timer match interrupts to work (SOLVED) |
|
|
I'm an ARM newb. One at a time I'm going through the peripherals on my LPC-P2148 to learn how ARMs do it (played with HC11/12s, AVRs, MSP430s, lots of PICs before).
I wrote this little test program and can't get the interrupt to fire. I've been over it and over it. Looks right to me (not that that means anything ).
I'm using Eclipse/yagarto.
Can anyone spot what I'm doing wrong here?
| Code: | #include "LPC214x.h"
#define PLOCK 0x400
void init(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)
{
IODIR0 = 0x30600000;
IOCLR0 = 0x30600000; //LEDs off
init();
T0MR0 = 0x00001388; //compare-hit count
T0MCR = 0x0003; //interrupt and reset on MR0
T0TCR = 0x01; //enable Timer0
VICVectCntl0 = 0x00000030; //use it for Timer 0 Interrupt:
VICVectAddr0 = (unsigned)IRQ_Routine; //set interrupt vector in 0
VICIntEnable = 0x00000010; //enable TIMER0 interrupt
while(1);
}
void init(void)
{
PLLCFG=0x24; //set multiplier/divider values
PLLFEED=0xaa;
PLLFEED=0x55;
PLLCON=0x01; //enable PLL
PLLFEED=0xaa;
PLLFEED=0x55;
while(!(PLLSTAT & PLOCK)); //wait for the PLL to lock to set frequency
PLLCON=0x3; //connect the PLL as the clock source
PLLFEED=0xaa;
PLLFEED=0x55;
MAMCR=0x02; //enable MAM
MAMTIM=0x04; //set number of clocks for flash memory fetch
VPBDIV=0x01; //set peripheral clock(pclk) to system clock(cclk)
}
void IRQ_Routine(void)
{
IOPIN0 ^= 0x30600000; //toggle 4 LEDs
T0IR = 0x01; //clear interrupt
VICVectAddr0 = 0x00000000; //end of interrupt - dummy write
}
void FIQ_Routine(void){
while (1) ;
}
void SWI_Routine(void){
while (1) ;
}
void UNDEF_Routine(void) {
while (1) ;
}
|
_________________ =======================
Futz's Microcontrollers & Robotics
=======================
Last edited by futz on Mon Jan 19, 2009 4:10 pm; edited 1 time in total |
|
| Back to top |
|
 |
gdisirio
Joined: 22 Sep 2007 Posts: 154 Location: Salerno, Italy
|
Posted: Fri Jan 16, 2009 6:05 am Post subject: |
|
|
I think you should enable the TIM0 clock in PCONP. _________________ ChibiOS/RT project page, the RTOS supports ARM7, Cortex-M3, AVR ATmega, MSP430, Coldfire, H8S, x86. |
|
| Back to top |
|
 |
futz
Joined: 06 May 2008 Posts: 71 Location: Vancouver, B.C. Canada
|
Posted: Fri Jan 16, 2009 5:01 pm Post subject: |
|
|
| gdisirio wrote: | | I think you should enable the TIM0 clock in PCONP. |
Unfortunately that's not it. That's already enabled by default after reset. Of course I put a line in the program to enable it again , just in case, but no change. _________________ =======================
Futz's Microcontrollers & Robotics
======================= |
|
| Back to top |
|
 |
gdisirio
Joined: 22 Sep 2007 Posts: 154 Location: Salerno, Italy
|
|
| Back to top |
|
 |
manton
Joined: 07 Mar 2008 Posts: 52 Location: Edmonton, AB, Canada
|
Posted: Sat Jan 17, 2009 2:18 pm Post subject: |
|
|
You likely need to enable interrupts using the global interrupt flags in the CPSR register. I'm not sure if Yagarto does this for you in the startup code.
You need some routines like these:
| Quote: |
/* Enable and disable functions "ripped" from a sample by R O Software.
* Copyright 2004, R O SoftWare
* No guarantees, warrantees, or promises, implied or otherwise.
* May be used for hobby or commercial purposes provided copyright
* notice remains intact. */
#include "VIClowlevel.h"
#define IRQ_MASK 0x00000080
static inline unsigned asm_get_cpsr(void)
{
unsigned long retval;
asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ );
return retval;
}
static inline void asm_set_cpsr(unsigned val)
{
asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) );
}
unsigned enableIRQ(void)
{
unsigned _cpsr;
_cpsr = asm_get_cpsr();
asm_set_cpsr(_cpsr & ~IRQ_MASK);
return _cpsr;
}
unsigned disableIRQ(void)
{
unsigned _cpsr;
_cpsr = asm_get_cpsr();
asm_set_cpsr(_cpsr | IRQ_MASK);
return _cpsr;
}
unsigned restoreIRQ(unsigned oldCPSR)
{
unsigned _cpsr;
_cpsr = asm_get_cpsr();
asm_set_cpsr((_cpsr & ~IRQ_MASK) | (oldCPSR & IRQ_MASK));
return _cpsr;
}
/* end of R O code */
|
Mike |
|
| Back to top |
|
 |
futz
Joined: 06 May 2008 Posts: 71 Location: Vancouver, B.C. Canada
|
Posted: Sat Jan 17, 2009 3:44 pm Post subject: |
|
|
| manton wrote: | | You likely need to enable interrupts using the global interrupt flags in the CPSR register. I'm not sure if Yagarto does this for you in the startup code. |
I think that stuff is done in the crt.s startup code. I pasted the one I'm using at bottom of this post.
I've tried a lot of stuff in my program. In the debugger I can see that the timer is working and the timer interrupt flag gets set properly on a match. But no interrupt occurs! Something is awry.
My current test program:
| Code: | #include "LPC214x.h"
#define PLOCK 0x400
void init(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 = 0x30600000;
IOCLR0 = 0x30600000; //LEDs off
init();
T0TCR = 0x02; //reset counter
T0IR = 0xff;
T0MCR = 0x0003; //interrupt and reset on MR0
T0MR0 = 0x0000ffff; //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
while(1){
i=0;
for(i=0;i<1000;i++);
i=1;
}
}
void IRQ_Routine(void)
{
int i;
IOSET0 = 0x30600000; //4 LEDs blink
for(i=0;i<0x0000ffff;i++);
IOCLR0 = 0x30600000;
T0IR = 0x01; //clear interrupt
VICVectAddr0 = 0; //end of interrupt - dummy write
}
void init(void)
{
PLLCFG=0x24; //set multiplier/divider values
PLLFEED=0xaa;
PLLFEED=0x55;
PLLCON=0x01; //enable PLL
PLLFEED=0xaa;
PLLFEED=0x55;
while(!(PLLSTAT & PLOCK)); //wait for the PLL to lock to set frequency
PLLCON=0x3; //connect the PLL as the clock source
PLLFEED=0xaa;
PLLFEED=0x55;
MAMCR=0x02; //enable MAM
MAMTIM=0x04; //set number of clocks for flash memory fetch
VPBDIV=0x01; //set peripheral clock(pclk) to system clock(cclk)
}
void FIQ_Routine(void){
while (1) ;
}
void SWI_Routine(void){
while (1) ;
}
void UNDEF_Routine(void) {
while (1) ;
}
|
My current crt.s:
| Code: | /* ***************************************************************************************************************
crt.s STARTUP ASSEMBLY CODE
-----------------------
Module includes the interrupt vectors and start-up 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, 0X00000004 /* stack for "IRQ" normal interrupts is 4 bytes */
.set SVC_STACK_SIZE, 0x00000004 /* stack for "SVC" supervisor mode is 4 bytes */
#.set _MEMMAP, 0xE01FC040
/* 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,#-0xFF0] /* 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:
/* 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|I_BIT|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
|
_________________ =======================
Futz's Microcontrollers & Robotics
======================= |
|
| Back to top |
|
 |
manton
Joined: 07 Mar 2008 Posts: 52 Location: Edmonton, AB, Canada
|
Posted: Sat Jan 17, 2009 4:27 pm Post subject: |
|
|
Your startup code sets up stacks like it should, but it leaves all interrupts disabled (this is what the comments indicate, and my limited understanding of ARM assembler would agree that the comments are correct). So you will need to enable interrupts in your code.
It would be quite normal for the startup code to leave interrupts disabled, as there is a bunch of initialization that needs to be done before they can be enabled.
Mike |
|
| Back to top |
|
 |
futz
Joined: 06 May 2008 Posts: 71 Location: Vancouver, B.C. Canada
|
Posted: Sat Jan 17, 2009 4:36 pm Post subject: |
|
|
| manton wrote: | Your startup code sets up stacks like it should, but it leaves all interrupts disabled (this is what the comments indicate, and my limited understanding of ARM assembler would agree that the comments are correct). So you will need to enable interrupts in your code.
It would be quite normal for the startup code to leave interrupts disabled, as there is a bunch of initialization that needs to be done before they can be enabled. |
Really!?!? That's crazy! What the hell good is it with no interrupts?
So where do I go to find out how to enable them? What's involved? You say "a bunch of initialization". I kind of thought I'd already done that... _________________ =======================
Futz's Microcontrollers & Robotics
======================= |
|
| Back to top |
|
 |
manton
Joined: 07 Mar 2008 Posts: 52 Location: Edmonton, AB, Canada
|
Posted: Sat Jan 17, 2009 4:53 pm Post subject: |
|
|
You have done the initialization in main(), which the startup code does not handle, which is why interrupts are not normally enabled in the startup code. It is the requirement of main() to enable interrupts after the system configuration has been completed.
If you look at the code I posted earlier, you will find routines in it for enabling and disabling interrupts. After you have configured the VIC and set up your timer, call the enableIRQ() function.
Mike
[/quote] |
|
| Back to top |
|
 |
futz
Joined: 06 May 2008 Posts: 71 Location: Vancouver, B.C. Canada
|
Posted: Sat Jan 17, 2009 5:11 pm Post subject: |
|
|
| manton wrote: | You have done the initialization in main(), which the startup code does not handle, which is why interrupts are not normally enabled in the startup code. It is the requirement of main() to enable interrupts after the system configuration has been completed.
If you look at the code I posted earlier, you will find routines in it for enabling and disabling interrupts. After you have configured the VIC and set up your timer, call the enableIRQ() function.
Mike |
Thanks Mike. I probably won't get around to digging into it till Sunday or Monday. I'll probably have some more dumb questions then.  _________________ =======================
Futz's Microcontrollers & Robotics
======================= |
|
| Back to top |
|
 |
futz
Joined: 06 May 2008 Posts: 71 Location: Vancouver, B.C. Canada
|
Posted: Mon Jan 19, 2009 2:43 pm Post subject: |
|
|
After a couple hours of confusion and fumbling with it on Monday, I got it working. The confusion was good though. I learned some things I might not have learned had it just worked right away.
Yee Haw!! I have interrupts! Now I can get this thing doing something.
Thanks again Mike.  _________________ =======================
Futz's Microcontrollers & Robotics
======================= |
|
| Back to top |
|
 |
MattyZee
Joined: 30 Dec 2008 Posts: 10
|
Posted: Tue Jan 20, 2009 3:27 am Post subject: code? |
|
|
Hey futz. glad to hear you got it going. any chance of uploading your code how it is now so i can see what you did to fix it?
I've just got my dev board and succesfully made my first LED blinky code. Now i want to play with interrupts and would be heaps helpful i could go over you code.
Thanks!  |
|
| Back to top |
|
 |
futz
Joined: 06 May 2008 Posts: 71 Location: Vancouver, B.C. Canada
|
Posted: Tue Jan 20, 2009 9:09 am Post subject: Re: code? |
|
|
| MattyZee wrote: | Hey futz. glad to hear you got it going. any chance of uploading your code how it is now so i can see what you did to fix it?
I've just got my dev board and succesfully made my first LED blinky code. Now i want to play with interrupts and would be heaps helpful i could go over your code. |
If I find time tonight I'll post a few new pages on my site. I wrote some ultra-simple demo code for PWM and A/D last night too. And I have some simple RTC code I wrote last week that needs to be posted. Next up is RTC w/interrupts so it's more useful. _________________ =======================
Futz's Microcontrollers & Robotics
======================= |
|
| Back to top |
|
 |
futz
Joined: 06 May 2008 Posts: 71 Location: Vancouver, B.C. Canada
|
Posted: Wed Jan 21, 2009 9:52 am Post subject: Re: code? |
|
|
| MattyZee wrote: | | Any chance of uploading your code how it is now so i can see what you did to fix it? |
It has been posted to my site. Hit the LPC-P2148 link on the home page. Lots of little newb programs for the 2148 as I get each part figured out and working. If you're looking for advanced topics, this isn't the site for you.  _________________ =======================
Futz's Microcontrollers & Robotics
======================= |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|