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.

F28M36P63C2: Calling function SysCtlClockConfigSet() twice in the row causes system to enter endless loop

Part Number: F28M36P63C2

In F28M36 Support Library V210 if calling function SysCtlClockConfigSet() twice in the row causes system to enter endless loop. Seems problem is related to the WATCHDOG1 configuration in SysCtlClockPllConfig(...) . How this problem could be resolved?

  • Hello,

    Apologies, I am out of the office until Thursday (3/2). Please expect a reply then. 

    Best,
    Matt

  • Hello,

    The double-lock is required as part of a single PLL initialization sequence, but calling SysCtlClockConfigSet() a second time after the system is already configured will cause a system reset or hang.

    The datasheet explicitly states that the PLL should be locked twice in a row, and the SysCtlClockPllConfig() function implements this double-lock sequence. However, calling SysCtlClockConfigSet() multiple times in your application --especially after a bootloader has already configured the PLL--can cause system resets and instability, so you should only configure the PLL once during initialization.

    What is the status of the SYSPLLSTS[SYSPLLLOCKS] register? You also check the MRESC register to confirm the reset cause.

    Best,
    Matt

  • What is the status of the SYSPLLSTS[SYSPLLLOCKS] register? You also check the MRESC register to confirm the reset cause

    I'll check it

  • Please let me know what you find. Is there any reason why you are calling SysCtlClockPllConfig() twice? Calling it twice seems to be a known issue, as documented by the linked thread above.

    Best,
    Matt

  • RESC = 0x0000000 (apparently RESET not occurred)

    SYSPLLSTS = 0x00000001

    Running code extracted from SysCtlClockPllConfig() function twice in the row:

       //1st run

       SysCtlPeripheralEnable(SYSCTL_PERIPH_WDOG1);
        // Setup the watchdog before switching to the PLL
       WatchdogUnlock(WATCHDOG1_BASE);         // Unlock writes to watchdog configuration

       while(!WatchdogWriteReady());
       WatchdogIntClear(WATCHDOG1_BASE);       // Clear interrupt status

       while(!WatchdogWriteReady());
       WatchdogResetEnable(WATCHDOG1_BASE);    // Enable reset generation from the watchdog timer.

       while(!WatchdogWriteReady());
       WatchdogReloadSet(WATCHDOG1_BASE, 0xFFFFFFFF);  // Set the period of the watchdog timer.

       while(!WatchdogWriteReady());
       WatchdogEnable(WATCHDOG1_BASE);         // Enable the watchdog timer.

       while(!WatchdogWriteReady());
       WatchdogLock(WATCHDOG1_BASE);           // Lock the watchdog

       //2nd run

       WatchdogUnlock(WATCHDOG1_BASE);         // Unlock writes to watchdog configuration.

       while(!WatchdogWriteReady());
       WatchdogIntClear(WATCHDOG1_BASE);       // Clear interrupt status

       while(!WatchdogWriteReady());
       WatchdogResetEnable(WATCHDOG1_BASE);    // Enable reset generation from the watchdog timer.

       while(!WatchdogWriteReady());
       WatchdogReloadSet(WATCHDOG1_BASE, 0xFFFFFFFF);  // Set the period of the watchdog timer.

       while(!WatchdogWriteReady());    <-----------------------------------------------------------------------------STUCK HERE!!!!
       WatchdogEnable(WATCHDOG1_BASE);         // Enable the watchdog timer.

       while(!WatchdogWriteReady());
       WatchdogLock(WATCHDOG1_BASE);           // Lock the watchdog

  • Hello,

    SYSPLLSTS = 0x1 indicates that the PLL is locked. 

    Thank you for narrowing the issue down. The issue seems to be that once watchdog interrupts are enabled, all writes are ignored (see WDTCTL.INTEN bit):

    To ask again:

    Is there any reason why you are calling SysCtlClockPllConfig() twice? Calling it twice seems to be a known issue, as documented by the linked thread above.

    Best,
    Matt

  • Hi Matt! Thank you so much! Now when we clearly understand reason for such behavior, I'll check if it is mandatory to call SysCtlClockPllConfig() twice in our design.

    But now another problem came up in the same function implementation:

    Original if-condition declares:

    // If any PLL Settings changed, reconfigure PLL
    if ((CurPllSrc != (ClkSrcReq >> SYSCTL_USE_PLL_SHIFT)) || (CurPllIMult != (PllMult & SYSCTL_SPLLIMULT_M)) || (CurPllFMult != (PllMult & SYSCTL_SPLLFMULT_M)))

    {....}

    Should it be like this (without odd bit shift for ClkSrcReq)?

    // If any PLL Settings changed, reconfigure PLL
    if ((CurPllSrc != ClkSrcReq) || (CurPllIMult != (PllMult & SYSCTL_SPLLIMULT_M)) || (CurPllFMult != (PllMult & SYSCTL_SPLLFMULT_M)))

    {....}

    Also original if-condition doesn't take into account is PLL enabled and locked (register SYSPLLSTS). How can we fix it?

  • Hello,

    Should it be like this (without odd bit shift for ClkSrcReq)?

    // If any PLL Settings changed, reconfigure PLL
    if ((CurPllSrc != ClkSrcReq) || (CurPllIMult != (PllMult & SYSCTL_SPLLIMULT_M)) || (CurPllFMult != (PllMult & SYSCTL_SPLLFMULT_M)))

    {....}

    That is correct. This looks like a mistake in SysCtlClockConfigSet() that was never caught. 

    Bit 31 of ClkSrcReq and CurPllSrc both represent bit 0 of SYSPLLCTL register, SYSPLLEN. The right-shift to ClkSrcReq will cause the PLL to be unintentionally re-locked when ClkSrcReq[31]  = '1' and CurPllSrc[31] = '1' (even if IMULT/FMULT are the same).
     
    Also original if-condition doesn't take into account is PLL enabled and locked (register SYSPLLSTS). How can we fix it?

    Are you intending for clock configuration to be skipped if it's already locked? 

    Best,
    Matt

  • Hello, Matt!

    As I can see with attached debugger - PLL is got configured somehow even before initialization by SysCtlClockPllConfig().

    I guess it happens under original _c_int00 function (in accordance with CFG-file settings) before main().

    Now let's imagine PLL was not locked in the proper way before call to the SysCtlClockPllConfig (for example, errata was not considered there) but

    multipliers are defined the same - condition above won't catch this case. That's what I am thinking about...

  • One more question, please! Does it  mean I can't reconfigure Watchdog1 after calling the SysCtlClockPllConfig()?

  • Hello,

    As I can see with attached debugger - PLL is got configured somehow even before initialization by SysCtlClockPllConfig().

    I believe if you flash the device via JTAG, the PLL will be configured by the flash plugin in CCS.

    Now let's imagine PLL was not locked in the proper way before call to the SysCtlClockPllConfig (for example, errata was not considered there) but

    multipliers are defined the same - condition above won't catch this case. That's what I am thinking about...

    This shouldn't generally occur. If the PLL doesn't successfully lock the watchdog will reset the device.

    You could add to the if-condition as follows (pseudo-code), but not entirely necessarily:

    if ((!SYSPLLSTS[SYSPLLLOCKS] && SYSPLLCTL[SPLLEN]) || CurPllSrc != ClkSrcReq) || ...) {}

    Does it  mean I can't reconfigure Watchdog1 after calling the SysCtlClockPllConfig()?

    When the watchdog interrupt has been enabled, all subsequent writes to the WDTCTL control register are ignored. The only mechanism that can re-enable writes is a hardware reset. I believe you can still reconfigure the other WDT1 registers (reload values, etc.)

    Best,

    Matt

  • Now when we see issue with watchdog re-configuration can we state that it is prohibited to run WATCHDOG1 before SysCtlClockPllConfig(...) was called?

    Our goals - to configure PLL once after start but use Watchdog1 then for our own purposes.

  • Hello,

    Yes, I would advise against running Watchdog1 before calling SysCtlClockPllConfig() on F28M36x devices. Best practice recommends configuring the PLL first, then initializing the Watchdog. Most TI reference code calls SysCtlClockPllConfig() before any peripheral driver (including the watchdogs) is opened.

    Best,

    Matt

  • Hello, Matt

    Following this approach, we have to configure PLL once after power-up and then configure WDT1 without subsequent writings to its CTL register.

    I would like to consider another solution as well - just remove WDT1 from PLL configuration. Please, advise.

    Since WDT1 is launched only after PLL already successfully locked (after while loop inside 5 attempts) is it reasonable to run WDT1 on this step? 

  • Hello,

    WDT1 is configured at that time to provide a reset mechanism in the case that the PLL lock fails, before it can be used as the system clock source. 

    As per the errata: "The Watchdog timer is used to detect if the condition has occurred because it is not clocked by the PLL output. The watchdog should be enabled before selecting the PLL as the clock source and configured to reset the device. If the PLL is not producing a clock, the Watchdog will reset the device and the user initialization software will therefore repeat the PLL initialization."

    Best,
    Matt

  • I cannot see WDT1 intentionally configured and running before PLL locking attempts (F28M36 Support Library V210).

    Should it be running before this while-loop starts to prevent endless loop if PLL failed to lock?

  • Hello,

    That is true, there seems to be potential for livelock if the lock fails. You can add in a software timeout (with a counter) or do the WDT1 configurations beforehand with a suitable timeout value. Many TI support library examples assume nominal hardware conditions and don't include timeout protection on PLL lock loops.

    Best,
    Matt

  • Thank you, Matt! I'd like to schedule a brief meeting with the team members next week and

    if we don't have any more questions, we can mark topic as "resolved" and wrap up.

  • Hi,

    Sounds good! I'll be here to assist if anything else needs to be clarified.

    Best,

    Matt

  • Hi Matt!  After briefing with our team I would like to offer another solution - 

    Call two functions below after PLL was successfully locked and enabled:

    SysCtlPeripheralDisable(SYSCTL_PERIPH_WDOG1); //this function already exists
    SysCtlPeripheralReset(SYSCTL_PERIPH_WDOG1); //reset only WDT1 registers

    Seems it solves all possible problems and we can clearly see that we can reconfigure PLL twice etc.

    All WDT1 registers are also reconfigurable after it's local peripheral reset.

    Do we have any possible issues with this solution?

  • Hello,

    Yes, that would be an effective workaround to the WDTCTL register lock issue. I'm glad to hear things are working now!

    Best,

    Matt