Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 14 of 14

Thread: Can't use LPTMR0 on teensy 3.0.

  1. #1
    Junior Member
    Join Date
    Dec 2012
    Posts
    8

    Can't use LPTMR0 on teensy 3.0.

    Hello.

    I want to use LPTMR0 timer in my project, but when I try to read any LPTMR0 register board hangs.

    for example I loaded simple blink sketch and inserted there something like

    x = LPTMR0_CNR; at the end of the main loop.

    Sketch is compiling and uploading as usual, but after restart board blinks one time and stops blinking.

    Is it possible to use this timer, or may be another way for me? I need simple free running 16bit counter with prescaler, no interrupts needed.

    I'm using Arduino 1.0.5 and teeensyduino 1.17

  2. #2
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    Isn't LPTMR0_CNR concerned with power conservation/wakeup and interrupts? Unreladed to timers?


    could you use
    Code:
    short x;
    x = (short)millis();
    //or 
    x = (short)micros();
    to get 16 bits?
    Last edited by stevech; 01-18-2014 at 09:38 PM.

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,576
    Quote Originally Posted by ancc View Post
    I want to use LPTMR0 timer in my project, but when I try to read any LPTMR0 register board hangs.
    You need to enable it before accessing any of its registers.

    Try adding this:

    Code:
    SIM_SCGC5 |= SIM_SCGC5_LPTIMER;

  4. #4
    Junior Member
    Join Date
    Dec 2012
    Posts
    8
    Quote Originally Posted by stevech View Post
    Isn't LPTMR0_CNR concerned with power conservation/wakeup and interrupts? Unreladed to timers?


    could you use
    Code:
    short x;
    x = (short)millis();
    //or 
    x = (short)micros();
    to get 16 bits?
    I'm now trying to adapt one library from AVR to teensy3. When I failed when LPTMR I begin to rewright this library to work with micros() but It was a bad idea.

  5. #5
    Junior Member
    Join Date
    Dec 2012
    Posts
    8
    Quote Originally Posted by PaulStoffregen View Post
    You need to enable it before accessing any of its registers.

    Try adding this:

    Code:
    SIM_SCGC5 |= SIM_SCGC5_LPTIMER;
    Thanks! I'll try.

  6. #6
    Junior Member
    Join Date
    Dec 2012
    Posts
    8
    Now the board is working. But when reading LPTMR0_CNR register I got "0" every time. Other registers of LPTMR0 is reading correctly.

    Here is my config of this timer. I need to set prescaler to 8, no interrupts

    LPTMR0_PSR = 0x10;
    LPTMR0_CSR = 0x05;

    What I'm doing wrong?

  7. #7
    Try this, although trying to read LPTMR0_CNR will likely still read 0, it will trigger the interrupt at the period you specify in compare_value.

    Code:
    int compare_value;
    
    void setup(){
      
      compare_value = 500;
      
      pinMode(5, OUTPUT);
      INIT_LPTMR_INT();
    
    }
    
    void loop(){
      asm("WFI");
    }
    
    void lptmr_isr(){
      digitalWriteFast(5, !digitalRead(5));
      LPTMR0_CSR|=LPTMR_CSR_TCF_MASK;  //Clear LPT Compare flag
    }
    
    void INIT_LPTMR_INT(){
      
    
      /* Enable LPT Module */
      SIM_SCGC5 |= SIM_SCGC5_LPTIMER;
    
      /* Reset LPTMR registers */
      lptmr_clear_registers();
    
      /* Configure LPT */
      LPTMR0_CMR=LPTMR_CMR_COMPARE(compare_value);  //Set compare value
      LPTMR0_PSR=LPTMR_PSR_PCS(0x1)|LPTMR_PSR_PBYP_MASK;  //Use LPO clock and bypass prescale
      LPTMR0_CSR=LPTMR_CSR_TIE_MASK;  //Enable LPT interrupt
    
      /* Enable LPT Interrupt in NVIC */
      NVIC_ENABLE_IRQ(IRQ_LPTMR); 
    
      LPTMR0_CSR|=LPTMR_CSR_TEN_MASK; 
    }

  8. #8
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,576
    I ran into this problem today.

    Turns out there's an undocumented synchronism mechanism. You write zero (or probably any value) to LPTMR0_CNR to cause it to acquire a new reading from the actual counter (which runs asynchronously from the main CPU & peripheral bus).

    The datasheet talks about reading LPTMR0_CNR multiple times and checking for 2 in a row that match. That probably applies to some older version. The one in Teensy 3.1 definitely has the write-to-sync mechanism, despite Freescale's documentation.

  9. #9
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,198
    FYI
    The other anomaly I have observed is that it is not possible to clear the interrupt TCF flag without disabling the LPTMR0. The reference manual suggests you can clear that flag by just writing a 1 to it. Didn't work for me. In Paul's entropy library ISR, he uses two steps to clear the interrupt
    Code:
    void lptmr_isr(void)
    {
      LPTMR0_CSR = 0b10000100;
      LPTMR0_CSR = 0b01000101;
      isr_hardware_neutral(SYST_CVR);
    }
    Last edited by manitou; 04-20-2016 at 01:07 AM.

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,576
    Yup, several of Freescale's reference manuals have wrong documentation on the LPTMR sync mechanism.

  11. #11

    LPTMR0 on Teensy-LC

    Does LPTMR not work with the PLL clock (48MHz, Teensy-LC)? I have this code:

    Code:
    volatile uint32_t countdown;
    
    void
    delay_ms( uint32_t ms )
    {
        SIM_SCGC5 |= SIM_SCGC5_LPTMR(1);
        
        LPTMR0_CSR = 0;						// Reset / disable LPTMR0
    
        NVIC_EnableIRQ( LPTMR0_IRQn );
        
        LPTMR0_CNR = 0;						// Clear counter (not possible?)
        LPTMR0_CMR = 48000;                 // Clock is 48MHz, so compare @ 48000 == 1mS
        LPTMR0_PSR = (LPTMR_PSR_PBYP(1) |   // Bypass prescaler, clock 0 selected
                      LPTMR_PSR_PCS(0));	// Select clock 0
        LPTMR0_CSR = (LPTMR_CSR_TCF_MASK |
                      LPTMR_CSR_TIE(1) |
                      LPTMR_CSR_TPS(0b00) |
                      LPTMR_CSR_TPP(0) |
                      LPTMR_CSR_TFC(0) |
                      LPTMR_CSR_TMS(0) |
                      LPTMR_CSR_TEN(1));
    
        
        for (countdown = ms; countdown; ) ;
    
        NVIC_DisableIRQ( LPTMR0_IRQn );
        LPTMR0_CSR = 0;
    }
    
    void __attribute__(( interrupt ))
    lptmr_isr( void )
    {
        GPIOC->PTOR = (1 << 5);
        if (countdown) {
            --countdown;
        } else {
            LPTMR0_CSR = 0;
        }
    }
    But PC5 (LED) never wiggles...

  12. #12
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,198
    post #9 above would suggest it takes two steps to clear the interrupt, and those steps should be done unconditionally (outside the if/else) in your isr. i don't have an LC handy to test your sketch ...

  13. #13
    I just put in a poor-man's breakpoint ("while (1) GPIOC->PTOR = (1 << 5);") in the ISR, and it never gets there. There's not even one interrupt happening.

  14. #14
    ...and there it is: you have to turn on MCGIRCLK...MCG_C1 |= MCG_C1_IRCLKEN(1).

    Incidentally, it looks like you can clear the LPTMR F flag by writing 1 to it, as the documentation states. At least on the chip on my Teensy-LC.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •