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.

TMS320F28027: PLL limp mode when running from flash

Part Number: TMS320F28027
Other Parts Discussed in Thread: C2000WARE

Hi,

I am in the process of configuring our code to run from flash. When the code enters the initialization routine for the PLL, it stops and it appears that the PLL is running in limp mode. Before, our code was being executed from RAM and no problems appeared. The specific code looks like this: 

void InitPll()
{
    //
    // 1. Make sure the PLL is not running in limp mode
    //
    if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)
    {
        EALLOW;
        //
        // OSCCLKSRC1 failure detected. PLL running in limp mode.
        // Re-enable missing clock logic.
        //
        SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1;
        EDIS;

        //
        // Replace this line with a call to an appropriate
        // SystemShutdown(); function.
        //

        asm("        ESTOP0");     // Uncomment for debugging purposes
    }

Next, I tried the C2000Ware example "flash_f2802x". Running this example does not show the above behaviour. I noticed that different values for the waitstates were used, so I adjusted the waitstates in our own code and the above problem dissapears. However, I do not understand why. Below are the specific values used:

The old values for the waitstates, where it appears that the PLL is in limp mode:

// Set the Paged Waitstate for the Flash
//
FlashRegs.FBANKWAIT.bit.PAGEWAIT = 0;

//
// Set the Random Waitstate for the Flash
//
FlashRegs.FBANKWAIT.bit.RANDWAIT = 1;

//
// Set the Waitstate for the OTP
//
FlashRegs.FOTPWAIT.bit.OTPWAIT = 1;

The new values for the waitstates, which runs fine:

// Set the Paged Waitstate for the Flash
//
FlashRegs.FBANKWAIT.bit.PAGEWAIT = 2;

//
// Set the Random Waitstate for the Flash
//
FlashRegs.FBANKWAIT.bit.RANDWAIT = 2;

//
// Set the Waitstate for the OTP
//
FlashRegs.FOTPWAIT.bit.OTPWAIT = 3;
 

For the "old values", I used table 5-24 of the datasheet (SPRS523N) which specifies the minimum required wait states. The code of setting the wait states is executed before initializing the PLL. As I understand from the technical reference manual (SPRUI09), after a reset  SYSCLKOUT equals 2.5 MHz or 400ns which resulted in the above "old values".

Does anyone have an idea why the PLL would go in limp mode?



Kind regards,
Steven.

  • Steven,

    I agree that the Flash WS shouldn't cause a Missing Clock event on their own.  Certainly if the device were running at its full 60MHz and the flash were accessed with these old settings you'd be more likely to get a illegal instruction(we could mis-decode an instruction as well). 

    While it is correct that coming out of reset the device is at 2.5MHz; I think by the time you exit the BROM we have executed the DeviceCal() function, which will get the internal oscillators to their DS spec of 10MHz.  Still, your old WS settings should still be good up till 20MHz.

    From your description, though, the missing clock event took place before the InitPLL function was even called and before the PLL was set to multiply the internal clock.

    Is it possible that in your code there was a change in the clock source off the internal 0-pin oscillator?  I think the problem with detecting this, is that on a missing clock the device will switch itself back to the internal oscillator as a safety net.

    Can you look to see where the InitFlash() function is called in your project, relative to the InitSysCtrl() funciton as well as the InitPLL() function?

    We could also see if its the main array WS or the OTP WS that is causing this; you can modify them independently and see if the issue goes away with one or the other.  The calibration function is in OTP, if this is not executing properly it will mis-calibrate the oscillator and the frequency will not be expected.

    Will look for you reply.

    Best,

    Matthew

  • Hi Matthew,

    With regards to the clock source, I am using internal oscillator 1. The order of functions called was first InitFlash(), next InitOsc1Sel() and lastly InitPLL(). All of these functions reside in InitSysCtrl().

    I now changed the order to first InitOsc1Sel(), next InitPLL() a lastly InitFlash(). The idea was to configure the flash after the PLL because I had the impression that although the code enters the section of the PLL being in limp mode, that this was not actually the case. When I simply restarted the code from Code Composer Studio, the limp mode section was not entered again. Also when the code entered the limp mode section, it checks that 

    SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0
    but when I watched 
    SysCtrlRegs.PLLSTS.bit.MCLKSTS
    in CSS, it showed being 0. Not sure if this is normal. 

    With the new order, so configuring flash after the PLL, the code runs fine and the limp mode section is not entered anymore. With the previous order, I indeed checked changing only the paged WS for the flash. This resulted in entering the limp mode. However, I did not checked changing only the WS for the OTP. 

     

    Kind regards,

    Steven.

  • Steven,

    Matthew is currently out of the office until July 8th.

    Are you configuring the PLL to generate a SYSCLK greater than 25MHz? If so, the original sequence of events would have executed all of the initialization sequence out of flash using the 25MHz wait-state settings. When the PLL was configured for >25MHz operation, the wait-states would no longer have been valid and the CPU would most likely have fetched corrupted instructions from flash. The corrupted instructions may have misconfigured the system into a missing clock condition.

    If the above is true, your original sequence should work as long as you increase the wait-states for >25MHz operation prior to configuring the PLL.

    -Tommy

  • Hi Tommy,

    I am configuring SYSCLK to be 10MHz. This is done inside the InitPll() function after checking if the PLL is running in limp mode. (As you can see from my first post, checking for limp mode is the first thing that is done in this function.)

    If I understand correctly, after a reset SYSCLK equals 2.5MHz. So if the code enters InitPLL() after a reset, the wait-states for 25MHz operation should be fine right? Please correct me if I am wrong here. 


    Kind regards,

    Steven.

  • I am configuring SYSCLK to be 10MHz. This is done inside the InitPll() function after checking if the PLL is running in limp mode.

    Ok, the speed was not obvious to me from skimming the prior posts.

    If I understand correctly, after a reset SYSCLK equals 2.5MHz.

    Yes, the hardware cold-reset default is to divide the internal oscillator frequency /4 for a TYP of 2.5MHz. However, the Boot ROM will execute immediately after reset, so your application will start from a /1 frequency (TYP of 10MHz).

    From the TRM:

    -Tommy

  • Hi Tommy,

    Thank you for linking this extra information. I now understand what your collegue Matthew meant exactly. 

    However, I don't think that this explains the above behaviour. In any case, configuring flash after the PLL instead of before resolved my issue. 


    Kind regards,

    Steven.

  • Steven,

    I would agree that we are still missing the root cause of the failure. Let us know if you wish to investigate further.

    -Tommy