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.

CCS/MSP432P401R: RTC runs fast

Part Number: MSP432P401R
Other Parts Discussed in Thread: CC1310

Tool/software: Code Composer Studio

Hi all,

CCS Version: 7.2.0.00013

I initialize the RTC from my laptop via usb-to-uart then read the time back.


The time starts in sync but the RTC time gains about 1 second every 10 seconds.


Any ideas how to diagnose this?

  • Hi Robert,
    could you check a time gain after 100 or 1000 seconds?
  • How are you setting up your clocks?
  • Time drift appears to have reduced over time.
    Now the 432 gains approximately 3 to 4 seconds per minute.
    120 sec: 8 seconds gain
    240 sec: 15 seconds gain
    480 sec: 30
    960 sec: 58
  • RTC_C is clocked by 32.768 kHz.
    On most LPs TI gives 20 ppm crystals.
    As I remember, a calibration can be done in rance of +/- 200-300 ppm.
    Do you have a scope to check a frequency?
  • It might not be connected to the Xtal. RTC_C is clocked from BClock and that can come from LFXTCLK (the xtal) or REF0CLK.
  • This is copy-and-paste from my setRTC() call:

    MAP_RTC_C_holdClock();

    MAP_RTC_C_initCalendar(&ti_calendar, RTC_C_FORMAT_BINARY); /* init, was RTC_C_FORMAT_BCD */

    MAP_RTC_C_clearInterruptFlag(RTC_C_CLOCK_READ_READY_INTERRUPT | RTC_C_CLOCK_ALARM_INTERRUPT);

    MAP_RTC_C_enableInterrupt(RTC_C_CLOCK_READ_READY_INTERRUPT | RTC_C_CLOCK_ALARM_INTERRUPT);

    MAP_RTC_C_startClock(); /* start clock */
    MAP_Interrupt_enableInterrupt(INT_RTC_C); /* enable main RTC interrupt */
  • The frequency is measured on scope as 32.768 kHz
  • Checking this now...
  • Robert,
    looks to me that you use other clock than crystal.
    Yoy would need to check how to setup BCLK.
  • I added this to the card initialization:

    CS_initClockSignal ( CS_BCLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1 )

    and reran the time test for 240 seconds:

    240 sec: 14 sec gain (was 15 sec on last run, but timer start and stop is done by human hands)
  • Did you check for an oscillator fault?
  • Investigating now...
  • I found a description in the 2015 432 user's guide that makes the oscillator faut feature seem complicated to set up and use.
    It appears to generate an NMI interrupt when a fault count is exceeded. Is this correct?

    Is there an example project for this anywhere for me to copy and try?
  • The prescale dividers, RT0PS and RT1PS, are automatically configured to provide a 1-second clock interval for the RTC.
    An automatically configured is a bit misleading. Figure 20-1. RTC_C Block Diagram shows that dividers are hardwired to RTCSEC.

    Any write to any counting register takes effect immediately. However, the clock is stopped during the write. In addition, RT0PS and RT1PS registers are reset. This could result in losing up to 1 second during a write.
    So, any write delays RTC_C.

    The maximum frequency error that can be corrected to account for both offset error and temperature variation is ±240ppm. This means the sign addition of offset error value and temperature compensation value should not exceed maximum of ±240ppm otherwise the excess value above ±240ppm is ignored by hardware. Reading from RTCTCMP register at any time returns the cumulative value which is the signed addition of RTCOCALx and RTCTCMPx values. (Writing RTCOCAL reset the temperature compensation value to zero.) For example, when RTCOCAL value is +150ppm and the value written into RTCTCMP is +200ppm the effective value taken in for next calibration cycle is +240ppm. Software is expected to do temperature measurement at certain regularity, calculate the frequency error and write into RTCTCMP register to not to exceed the max limit of ±240ppm.

    Right now, I have no idea.
  • Could you check REF0CLK frequency?
    It can have 32.768 kHz +10-30%.
  • Robert,

    <<< I found a description in the 2015 432 user's guide that makes the oscillator faut feature seem complicated to set up and use.
    <<< It appears to generate an NMI interrupt when a fault count is exceeded. Is this correct?

    2015 432 users's guide? Do you have red, black? Which chip revision? We should base on an a TRM (tech. ref. man.) version valid for your chip.
    According to the latest TRM, oscillator fault does not seem complicated.

    TRM:

    LFXT_OscFault:
    This signal is set after the LFXT oscillator has stopped operation and is cleared after operation resumes. The fault condition causes LFXTIFG to be set and remain set. If the user clears LFXTIFG and the fault condition still exists, LFXTIFG is set again.

    NOTE: Fault logic As long as a fault condition still exists, the individual fault flags remains set. The clock logic switches back to the original user settings before the fault condition when the fault condition is resolved and the corresponding fault flag is cleared.

    6.2.11 Start-up Counters The LFXT includes a counter that makes sure that a programmable number of clock cycles have passed before the LFXT_OscFault signal is cleared. The counter can be programmed from 4096 to 32768 counts using the FCNTLF bits. The default is the maximum count. Any crystal fault restarts the counter. It is also possible to restart the counter directly through software by setting the RCNTLF bit.

    No doubts you know how to deal with it.
    Please give us a feedback about your findings.

    Many thanks for an opportunity to learn how to deal with the clock faults!

  • The chip is Rev D, and the board is bespoke. My hardware guy is searching for the corresponding TRM.

    The frequency is accurate to what the scope indicates. The oscillator is a standard part, not likely to be at fault.

    Will be adding the fault counter code today and posting more info when I have it.
  • Are you checking the value of CS_startLFXT()
  • I wish the documentation was more explicit with examples...
    From all the replies (thank you very much) it appears that I am using the RTC without making the library calls needed to calibrate it.
    I'm not saying this is the answer, only that this appears to be the answer.
    Next reply from me will have more info (after I've added the calls. I've been stuck in meetings all this morning).
  • The call to CS_startLFXT() does not return, when I suspend the program in the debugger, the code is in the "waiting for frequency stabilization loop"

    So that is that. Thank you for all your help to isolate the problem.

    However, knowing what the problem is has not resolved the underlying issue of what caused the problem:

    What prevents frequency stabilization?
  • Calibration cannot exceed of ±240ppm.
    In your issue like about -90,000 is needed.

  • <<< The call to CS_startLFXT() does not return, when I suspend the program in the debugger, the code is in the "waiting for frequency stabilization loop"
    Somehow it should be timed out.

    <<< What prevents frequency stabilization?
    Cold solder?
    Crystal device broken?
    Capacitors around crystal?
    I am not h/w guy.

    Each crystal has its power envelop.
    In case of CC1310LP, LFXT starts with maximum power allowed or provided by CC1310.
    Later LFXT power can be decreased.
    Probably something similar is implemented on msp432.

    You may try to deal with a crystal power, however, according to my intuition, more power, more stable oscillations.
  • THere is also a timeout API.  

    CS_startLFXTWithTimeout(uint32_t xtDrive, uint32_t timeout)

    Also, confirming Tmoasz comment, in this API the maximum drive strength is applied and then once the crystal has started the drive strength is changed to the parameter passed in the API.

    I have found this to be a good reference for the LFXT, 

    Regards,

    Chris

  • I used the below program on my MSP432P401R redboard. Note that until I put the timeout, CS_startLFXT() did not return.

    I ran it for 565 seconds according to the stopwatch in my watch and the elapsed time according to the program was 564 seconds - within my margin of error.

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    /*******************************************************************************
     * MSP432 SysTick - Blink LED Program
     *
     * Description: This program will use the SysTick module to blink an LED with
     * a one second period. Once setup, the application will go into LPM3
     * mode and only wake up to toggle the GPIO pin.
     *
     * This program runs infinitely until manually halted by the user.
     *
     *                MSP432P401
     *             ------------------
     *         /|\|                  |
     *          | |                  |
     *          --|RST         P1.0  |---> P1.0 LED
     *            |                  |
     *            |                  |
     *            |                  |
     *            |                  |
     *            |                  |
     *
     *******************************************************************************/
    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Standard Includes */
    #include <stdlib.h>
    #include <stdio.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <stdbool.h>
    
     static volatile RTC_C_Calendar newTime;
    
    // Time is Saturday, November 12th 1955 10:03:00 PM */
     const RTC_C_Calendar currentTime =
     {
             0x00,
             0x03,
             0x22,
             0x06,
             0x12,
             0x11,
             0x1955
     };
    
    volatile unsigned int Tick;
    volatile int i;
    
    //![Simple SysTick Example]
    int main(void)
    {
        volatile unsigned int stash;
        uint_fast8_t rtcs;
        uint_fast8_t rtcm;
        int sec, mins;
    
        /* Halting the Watchdog */
        MAP_WDT_A_holdTimer();
    
        /* Configuring GPIO as an output */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    
        // Configure the clock
        /* Just in case the user wants to use the getACLK, getMCLK, etc. functions,
         * let's set the clock frequency in the code.
         */
        CS_setExternalClockSourceFrequency(32000,48000000);
    
        /* Starting HFXT in non-bypass mode without a timeout. Before we start
         * we have to change VCORE to 1 to support the 48MHz frequency */
    
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_FlashCtl_setWaitState(FLASH_BANK0, 1);
        MAP_FlashCtl_setWaitState(FLASH_BANK1, 1);
        CS_startHFXT(false);
        CS_startLFXTWithTimeout(CS_LFXT_DRIVE3, 256);
    
        /* Initializing MCLK to HFXT (effectively 48MHz) */
        MAP_CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
        MAP_CS_initClockSignal(CS_BCLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
        //![Simple CS Config]
    
        MAP_RTC_C_initCalendar(&currentTime, RTC_C_FORMAT_BCD);
    
    
        MAP_SysTick_enableModule();
        MAP_SysTick_setPeriod(48000); // every 1 ms?
        MAP_SysTick_enableInterrupt();
    
        /* Enabling MASTER interrupts */
        MAP_Interrupt_enableMaster();
    
        printf("Hello, World!\n");
        fflush(stdout);
    
        MAP_RTC_C_startClock();
    
        while (1)
        {
            for (i=0; i<3000000; i++) /* delay */;
    
            MAP_SysTick_disableInterrupt();
            stash = Tick;
            MAP_SysTick_enableInterrupt();
    
    
                newTime = RTC_C_getCalendarTime();
                rtcs = newTime.seconds;
                rtcm = newTime.minutes;
                sec = RTC_C_convertBCDToBinary(rtcs);
                mins = RTC_C_convertBCDToBinary(rtcm);
                printf("RTC_min = %d, RTC secs = %d\n",mins, sec);
                fflush(stdout);
        }
    }
    
    void SysTick_Handler(void)
    {
        Tick++;
    }
    //![Simple SysTick Example]
    
    

  • Keith,

    <<< Note that until I put the timeout, CS_startLFXT() did not return.
    I need to elaborate that.
    Worth to reproduce!

    As I remember, I have 2 reds and 2 blacks.
    I will focus on reds. Regarding blacks, if needed, based on reds results, it would take some time for a proper setup.

    Weekend is coming, time for sailing and based on a weather conditions I might not respond till Mon.

  • OK, I found my mistake as to why startLFXT() did not return

    I needed a
    MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ,
    GPIO_PIN0 | GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);

    To turn the GPIO's into crystal inputs.

    So I was probably using the internal REF0.

    I re-ran things with the XTAL and got essentially the same results.
    I did compare the "SysTick" to the RTC, and found that the stdio interrupt for printf() shut the systick interrupt off for a loooong time, so the numbers were not comparable at all. I would need to repeat things with the back channel UART.
  • "Note that until I put the timeout, CS_startLFXT() did not return."

    If you used the timeout, how did you know the call completed successfully?

    IDid you check the status of the return value?

  • I don't want to check the resolved box until I hear from the other people on this forum who are checking out the problem.
    There could be a combination of hardware and also software problems, i.e. Barkley's response above, also detecting lockup on a launchpad.
  • I will try this...
  • I will try:
    MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ,
    GPIO_PIN0 | GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);
  • I added the GPIO statement and the code still hangs testing the CS_IFG_LXTIFG_OFS bit in the start command.
  • I am assuming this is a bespoke hardware problem and clicking the resolved box (even though the problem isn't resolved but there's likely no more you can help with on this)

**Attention** This is a public forum