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.

Can't get LPC2148 timer match interrupts to work

Status
Not open for further replies.
yeah better safe then sorry :D ... also look at the "T0TCR |= 0x01;" i used |= to set it since it has reserved bits which are used internally i suppose . Using the OR will set only the bits you want and leave the rest unchanged.
 
i just reread it futz and ur correct 1's are the evil for reserved :D

im tired lol Ill try to read up on it some more. Good luck while i read the sheet.
 
I have to step out but modded the code as you know i cant test it so ...
I was reading from the VIC start in the datasheet and this is how i would do it.
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();
    T0MCR = 0x0003;                         //interrupt and reset on MR0
    T0MR0 = 0x00ffffff;                     //compare-hit count
    T0TCR |= 0x01;                           //enable Timer0
    T0TCR |= 0x02;                           //reset counter

    VICSoftInt = 0x00000010;
    VICSoftIntClear = 0x00000010;
    VICIntEnable = 0x00000010;
    VICIntEnClear = 0x00000010;
    VICIntSelect = 0xFFFFFFEF;
    VICVectCntl0 = 0x00000024;
    VICVectAddr0 = (unsigned long)&IRQ_Routine;

    while(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) ;
}
 
If you want you can try this lol i know i change too much...
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();
    T0MCR = 0x0003;                         //interrupt and reset on MR0
    T0MR0 = 0x00ffffff;                     //compare-hit count
    T0TCR |= 0x01;                           //enable Timer0
    T0TCR |= 0x02;                           //reset counter

    VICSoftInt = 0x00000010;
    VICIntEnable = 0x00000010;
    VICIntSelect = 0x00000010;
    VICVectCntl0 = 0x00000024;
    VICVectAddr0 = (unsigned long)&IRQ_Routine;
    VICDefVectAddr = (unsigned long)&IRQ_Routine;
    while(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) ;
}


CHECK this out:
ARM Information Center

in PDF its:
https://www.electro-tech-online.com/custompdfs/2009/01/DDI0181.pdf

Ive seen your post on sparkfun also lol when i was searching google :D to find some info.

I cant wait to get me one of these it looks like lots of things you can set and do . I love the interrupts. Its awesome.... even if we cant get them to work yet ! lol.

Ill see if i order one tomorrow... if i order one will you help me setup? I might make:
VS Electronics and Embedded Development JTAG Wiggler Clone

or should i buy the USB Tiny?
 
Last edited:
If you want you can try this lol i know i change too much...
Won't work. Not gonna try it. You need to jump thru some stupid code hoops to enable interrupts. No amount of messing with my original code will change that. I have the additional code needed already, but haven't got it working yet. I quit for the night anyway. :p
 
I have parallel! Yay

ima try to get the money i need tomorrow. Where should i buy it from? Sparkfun is out of stock on USB TINY thing on the parallel and if im buying parallel i might as well make it lol and buy it also :D

If i buy parallel and board then its about $98 + $7 shipping/handling so that $105 ... I have $90 on me now. I need $15 tomorrow. That shouldnt be a issue at all! Yeah!
 
Last edited:
Last edited:
Futz i have a feeling that your issue is Compiler specific. I was reading some info on the RealView MDK :

The RealView C compiler provides function attributes that give you access to ARM hardware features. For example:

* __irq allows you to create interrupt service routines in C.
* __swi(id) allows you to invoke a software interrupt handler
from: RealView® Compilation Tools
 
try this as your startup code:
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
                LDR     PC, IRQ_Addr           ; [b]I added this[/b]
                LDR     PC, [PC, #-0x0FF0]     ; Vector from VicVectAddr
                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 i have a feeling that your issue is Compiler specific. I was reading some info on the RealView MDK :
Nope. It's all caused by the crt.s startup code, which disables interrupts by default. (How stupid is that?) The guy who was helping me seemed to think it was perfectly normal to have startup code that disables interrupts. :eek: And I say, "Huh? Why? That seems crazy! Ok, whatever... Lets get em enabled then"

try this as your startup code:
I won't even try it because it won't work. That one does the same thing.

To enable interrupts you add a piece of code like this (tho this one might not be for 2148).
Code:
/* 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 */
and call enableIRQ() after init in main().
 
Last edited:
look at this startup script (from RealView(MDK)). I added the txt extension so i can upload it.
 

Attachments

  • Startup.s.txt
    14.5 KB · Views: 182
Last edited:
well I don't know where it went, but the one thing that jumped out at me was that once it is an interrupt function the compiler should take interrupt controller if it has the support built in for the hardware so you should check the generated code for releasing the interrupt twice.

If not it is better to put it in a function call to handle the end of interrupt functionality so you only have to do it once.

I also do not remember now if you cleared the interrupt in the timer, this also needs to be done for it to trigger again.

If the processor itself has stopped running you need to check and see if it is in one of the error interrupt endless loops. While the standard compiler code defaults to this it would be a good idea to through out some indication that it has landed there if you are not going to handle them so you know it is time to reboot, or to let you know why it did if you have the watchdog running.

Dan
 
well I don't know where it went, but the one thing that jumped out at me was that once it is an interrupt function the compiler should take interrupt controller if it has the support built in for the hardware so you should check the generated code for releasing the interrupt twice.

If not it is better to put it in a function call to handle the end of interrupt functionality so you only have to do it once.
I have no idea what you're talking about. :D


I also do not remember now if you cleared the interrupt in the timer, this also needs to be done for it to trigger again.
Yes I did.
Code:
void IRQ_Routine(void)
{
    int i;
    IOSET0 = 0x30600000;        //4 LEDs blink
    for(i=0;i<0x0000ffff;i++);
    IOCLR0 = 0x30600000;
    T0IR = 0x01;                //clear interrupt
    VICVectAddr = 0;            //end of interrupt - dummy write
}


If the processor itself has stopped running you need to check and see if it is in one of the error interrupt endless loops.
The processor is running fine. It just sits in my endless while(1) loop forever, waiting for that interrupt to fire.

While the standard compiler code defaults to this it would be a good idea to through out some indication that it has landed there if you are not going to handle them so you know it is time to reboot, or to let you know why it did if you have the watchdog running.
Once again I have no idea what you mean by that. Do you mean that these stubs (I didn't write them - I think Jim Lynch did)
Code:
void FIQ_Routine(void){
    while (1) ; 
}
void SWI_Routine(void){
    while (1) ; 
}
void UNDEF_Routine(void) {
	while (1) ;	
}
should have something other than while(1) in them. I agree, but they're not getting hit. I've run the thing in the debugger enough to know for sure. Watchdog is not running.

manton (Mike) over at the SparkFun forum thread about this says the whole thing is because crt.s disables interrupts (for some whacked out reason that I can't comprehend). Here's the lines that do it (as far as I can see):
Code:
.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) */

...

	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
He suggests adding that piece of code a few posts back to enable interrupts. I haven't got that to work yet, but haven't spent much time at it yet either.

The thing I don't get is why they think it's normal to have interrupts disabled in the startup code. That seems completely nutz to me. What good is an MCU with the interrupts disabled? It's crippled, IMHO. But whatever, if I can use that other piece of code to enable them then fine.
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top