This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTC counting too fast on lm4f120xl launchpad

hi,

i want to use the hibernation modul for a realtime clock and date with my launchpad for an data logger

evereything ist working fine, but the rtc counts approximately 1% too fast.

Did i forget something, to activate the external 32khz chrystal?

here are my settings for the hibernationmodul:

 

/* Realtime Clock and hibernate*/
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
ROM_HibernateEnableExpClk(SysCtlClockGet());
HibernateClockConfig(HIBERNATE_OSC_DISABLE | HIBERNATE_OSC_HIGHDRIVE);
HibernateClockSelect(HIBERNATE_CLOCK_SEL_RAW);
HibernateGPIORetentionEnable();
ROM_HibernateWakeSet(HIBERNATE_WAKE_PIN);
ROM_SysCtlDelay(6400);
ROM_HibernateRTCEnable();
/* End Realtime Clock */

  • Hard to imagine that a 1% error results from "failure to activate/enable" your 32KHz xtal.  What is the xtal's spec and are its bypass C's proper?  Is your 1% error "protest" realistic - what is your accuracy target?

    I'm little experienced w/RTC module and your particular LX4F MCU.  However - there are clever means to output a true, divided down replica, of the MCU System Clock when employing the main oscillator.  If you can adapt this method to your 32KHz clock - that would appear to offer some useful data.  (usually - attaching even expensive scope probe to an MCU's xtal input has great likelihood of "pulling" the frequency - thus contaminating the measurement.  (Perhaps @ such low frequency that effect is less - but the  method I'll suggest completely eliminates this error source) 

    To output a "divided down" replica of System Clock employ the MCU Timer in PWM mode.  Setting the PWM Clock to 1/1000 of System Clock (and 50% duty) results in an easily measured frequency output @ 1/1000th of Sys Clk - and with no "loading" upon the xtal or sensitive MCU inputs.  Again - I do not know if you can route your 32KHz RTC clock to the PWM Module - or if you must devise another means to indirectly output this 32KHz signal - again w/out causing frequency shift/degradation.  (perhaps interrupting upon this 32KHz clock would enable you to trigger a GPIO output - which then could be safely (freq. de-tune free) monitored.

    Update: thinking bit more - as this error is unipolar - and if it remains consistent - you should be able to "compensate out" that 1% via software.  This should be done with code executing as quickly as possible - and at a rate which does not in itself cause error - and with an RTC result that easily enables a 1% "adjustment"...

  • Uli,

    You can fine tune the RTC by using the Trim Registers, see the Stellaris peripheral Driver Library pdf page 180 (http://www.ti.com/lit/ug/spmu019o/spmu019o.pdf).

    Out of curiosity are you actually using the hibernate module to hibernate, or just for the RTC?

    -Austin

  • hi,

    i'm going to use the hibernation modul for hibernating and for the rtc.  i will have a look at the trim registers.

    thanks for reply.

  • make sure to read pg 463 carefully (RTC Trim section), it should allow you to compensate nicely. It is more or less what CB1 was talking about.

  • thanks @ all:

    i looked which value had my trim register: it was 0x00002040.  so the counter counts too fast every 64 second!!

    you have to set it to 0x7FFF like mentioned on page 462 (spsm294e.pdf).

    but in the workbook for the launchpad, they didn't set the trim register manually. so i didn't know that the lm4f120 has a trim register.

    following example works for me fine:

     

    //Realtime Clock and hibernate
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    ROM_HibernateEnableExpClk(SysCtlClockGet()); //must be called first have a look page at 458 (spms294e.pdf)
    HibernateClockConfig(HIBERNATE_OSC_DISABLE | HIBERNATE_OSC_HIGHDRIVE); //select the external crystal with 24pF filter capacitor (for launchpad lm4f120xl)
    HibernateClockSelect(HIBERNATE_CLOCK_SEL_RAW); //select the raw output of the 32khz crystal
    HibernateRTCTrimSet(0x7FFF); // must be called. if you don't set manually the trim register, the counter counts too fast or too slow have a look at page 462 (spsm294e.pdf)
    HibernateGPIORetentionEnable();
    ROM_HibernateWakeSet(HIBERNATE_WAKE_PIN);
    ROM_SysCtlDelay(6400); //necessary, without this rtc won't work. don't really know why
    ROM_HibernateRTCEnable();
    // End Realtime Clock

  • @Uli: Good for you - persistence & attention to detail again paid off.  Am concerned that your start & finish "adjustment settings" are so far apart - would not expect that for your report of 1% initial error.  (method of RTC measurement deserves some detail - imho {see below})

    @Austin: Past "hibernates" had less than stellar reputation - thus our group avoided.  Anytime a vendor adjustment is available - best to try it first - as stated - I provided a general solution (worked often for us past).

    What remains unstated - and should be of interest - is just how poster (really all users) should perform such RTC measurements - prior to and during the "calibration" process.  Many dedicated RTC chips have special "speed up" circuitry - which enables superior measurements in a shorter time-frame.  (I've not yet reviewed our LX4F manual - this chapter - but offer this as adjustment w/out proper technique is sub-optimal...)

  • Uli Brugger said:
    you have to set it to 0x7FFF like mentioned on page 462 (spsm294e.pdf).

    but in the workbook for the launchpad, they didn't set the trim register manually. so i didn't know that the lm4f120 has a trim register.

    According to the LM4F120H5QR datasheet the Hibernation RTC Trim (HIBRTCT) register is supposed to have a reset value of 0x7fff.
    Uli Brugger said:
    i looked which value had my trim register: it was 0x00002040.  
    Thefollowing code also reports a RTC time value of 0x2040 after a power-up or reset:

    Void initialiseRtc (Void)
    {
        char debug[9];

     MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_HIBERNATE);

     if(!MAP_HibernateIsActive ())
     {
      MAP_HibernateClockConfig (HIBERNATE_OSC_HIGHDRIVE);
            MAP_HibernateEnableExpClk (MAP_SysCtlClockGet());

            // Delay for the maximum crystal oscillator start-up time of 1500ms
            MAP_SysCtlDelay (1500 * (MAP_SysCtlClockGet() / 3 / 1000));

            MAP_HibernateRTCEnable ();
     }

     sprintf (debug, "%08X", MAP_HibernateRTCTrimGet ());
     setLEDModuleText (debug);
    }

    The following L4MF12-H5QR errata seems to explain why the RTC time register doesn't have the expected value at reset:

    3.1 Some Hibernation module registers may not have the correct value in two situations

    Description:
    Some Hibernation module registers may not have the correct value in two different situations:
    1. After enabling the hibernation 32-kHz oscillator by setting the CLK32EN bit in the Hibernation Control (HIBCTL) register.

    2. When the CLK32EN bit is set, both the RTCEN and PINWEN bits in the HIBCTL register are clear, and any kind of reset occurs.

    The following Hibernation module registers are affected:
    - HIBRTCLD
    - HIBRTCM0
    - HIBRTCSS
    - HIBRTCT
    - HIBIM

    Note that the register values may or may not be correct, but software cannot assume that these registers have any specific values following the occurrence of the situations described above.

    Workaround:
    Ensure that every bit in these registers is correctly initialized in application software following the occurrence of the situations described above.

    Silicon Revision Affected:
    A1, A3, B0, B1

    Fixed:
    Not yet fixed.

    However, the above code shouldn't leave CLK32EN bit set and RTCEN clear, so not sure if the errata doesn't fully explain all conditions which can cause the RTC trim not to be initialised with the default value.

  • Chester Gillon said:
    However, the above code shouldn't leave CLK32EN bit set and RTCEN clear, so not sure if the errata doesn't fully explain all conditions which can cause the RTC trim not to be initialised with the default value.

    Used the following to debug from a power-up on a EK-LM4F120XL:
      volatile int holdIt=1;

     MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_HIBERNATE);

     while (holdIt)
     {

     }

     if(!MAP_HibernateIsActive ())
     {
            MAP_HibernateEnableExpClk (MAP_SysCtlClockGet());

    The while (holdIt) loop means that after power-up the device halts in the loop. You can then attach the debugger, clear holdIt and then single step before there have been any writes to the hibernate module. The situation is:

    1) After power-up the hibernate register contain:

    HIB_CTL = 0x80002000

    HIB_RTCLD = 0x00000000

    HIB_RTCM0 = 0xFFFFFFFF

    HIB_RTCSS = 0x00000000

    HIB_RTCT = 0x00007FFF

    HIB_IM = 0x00000000

    These are the reset register values in the device datasheet.

    2) After the driverlib HibernateEnableExpClk function has set the CLK32EN bit in the HIBCTL register the register values are:

    HIB_CTL = 0x80002040

    HIB_RTCLD = 0x80000040

    HIB_RTCM0 = 0x80002040

    HIB_RTCSS = 0x00000000

    HIB_RTCT = 0x00002040

    HIB_IM = 0x00000000

    Therefore, it appears the act of setting the CLK32EN bit in the HIBCTL register corrupts the values in the HIB_RTCLD, HIB_RTCM0  and HIB_RTCT  registers.

  • Chester Gillon said:
    Therefore, it appears the act of setting the CLK32EN bit in the HIBCTL register corrupts the values in the HIB_RTCLD, HIB_RTCM0  and HIB_RTCT  registers

    This is the code I ended up with, documented to work-around the silicon errata:

    Void initialiseRtc (Void)
    {
     MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_HIBERNATE);

     if(!MAP_HibernateIsActive ())
     {
      // Need to set the OSCDRV bit to set high drive strength, as the EK-LM4F120XL has 24pF capacitors
      // on the XOSC crystal.
      //
      // The LM4F120H5QR datasheet states the oscillator stability is not guaranteed if
      // the user changes the OSCDRV value after the the oscillator is running.
      //
      // However, calling HibernateClockConfig (HIBERNATE_OSC_HIGHDRIVE) to attempt to set OSCDRV
      // before the oscillator has been started (i.e. when CLK32EN is still clear) doesn't set
      // the OSCDRV bit. Therefore, bypass the driverlib and set the OSCDRV and CLK32EN bits
      // directly in one write.
         HWREG(HIB_CTL) |= HIB_CTL_CLK32EN | HIB_CTL_OSCDRV;

            // Delay for the maximum crystal oscillator start-up time of 1500ms
            MAP_SysCtlDelay (1500 * (MAP_SysCtlClockGet() / 3 / 1000));

            // Restore the register default values which may be corrupted by Errata 3.1 when CLK23EN was set
            MAP_HibernateRTCSet (0);
            HibernateRTCMatchSet (0, 0xFFFFFFFF); // Not available in ROM
            HibernateRTCSSMatchSet (0, 0); // Not available in ROM
            MAP_HibernateRTCTrimSet (0x7FFF);
            MAP_HibernateIntDisable (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_LOW_BAT |
                               HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_WR_COMPLETE);

            // Enable the RTC to start counting from the default of zero, to provide a monotonic
            // clock of the time since power up.
            MAP_HibernateRTCEnable ();
     }
    }