1. 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.
    Dismiss Notice

Can't get LPC2148 timer match interrupts to work

Discussion in 'Microcontrollers' started by futz, Jan 17, 2009.

  1. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    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.
     
  2. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    i cant wait to order this board from sparkfun. I have some weeks to wait still. :( but when i get it, i hope i get lost in it lol
     
  3. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Ya, "lost in it". That's exactly how it is. They aren't as simple as PICs. Basic bit twiddling stuff is similar, but some things are pretty tough to figure out.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.

    You're ok to write zeros to reserved bits. Just not ones.
     
  6. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    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.
     
  7. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    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 (text):

    #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) ;
    }

     
     
  8. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    I've been on a thread over at Sparkfun and I think I have the problem almost sorted. Near the bottom Manton comes along and clears up a few things (or maybe opens a whole new can of worms ;) ).
     
  9. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    If you want you can try this lol i know i change too much...
    Code (text):

    #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:
    http://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: Jan 17, 2009
  10. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    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
     
  11. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Hell no! Are you kidding? ;) Ya, sure. :p

    Does your computer have a parallel port? None of my newer boxes does. Definitely not my programming/mcu box. Has to be USB.
     
  12. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    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: Jan 17, 2009
  13. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    ONLINE
    Has anyone tried this board from Futurelec?

    Mike.
     
  14. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Hey, that's nice, and decent price! If I didn't already have a 2148 board I'd grab one.

    Think I'll dig around in their site and see what else they have... for an upgrade! Ya, that's it! I need an upgrade! :p Stupid gear lust. Must... Not... Spend... Learn what you already have.
     
  15. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    Last edited: Jan 18, 2009
  16. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    Futz i have a feeling that your issue is Compiler specific. I was reading some info on the RealView MDK :

    from: RealView® Compilation Tools
     
  17. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    try this as your startup code:
    Code (text):

    /* ***************************************************************************************************************
       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
     
     
  18. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    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"

    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 (text):
    /* 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: Jan 18, 2009
  19. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    look at this startup script (from RealView(MDK)). I added the txt extension so i can upload it.
     

    Attached Files:

    Last edited: Jan 18, 2009
  20. Ubergeek63

    Ubergeek63 Well-Known Member

    Joined:
    Apr 16, 2008
    Messages:
    1,886
    Likes:
    37
    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
     
  21. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    I have no idea what you're talking about. :D


    Yes I did.
    Code (text):
    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
    }
     

    The processor is running fine. It just sits in my endless while(1) loop forever, waiting for that interrupt to fire.

    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 (text):
    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 (text):
    .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: Jan 21, 2009

Share This Page