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.

TMS320F28035: About switching to an alternative clock.

Part Number: TMS320F28035
Other Parts Discussed in Thread: C2000WARE

Hello.
Please tell me about switching to an alternative clock when MISS_CLOCK is detected.
PLL_Initial(6,2) generates a 60MHz system clock using 20M_XTAL.
For a switching test, run the code below and the process will proceed to nmi_isr().
NmiIntruptRegs.NMIFLGFRC.bit.CLOCKFAIL = 1;

We understand that it is necessary to reconfigure the PLL in order to switch to internal OSC1 within this function.
Is this understanding correct?
I am thinking of generating a 60MHz system clock using internal OSC1 using PLL_Initial(12, 2).
However, when this function is executed, the CPU will stop.
Conversely, if this function is not executed, the CPU will continue to operate.
Is the XTAL->OSC1 switching successful without resetting the PLL?

Best regard.



Best regard!

__interrupt void nmi_isr(void)
{
    PLL_Initial(12, 2);     // CLK=10M*12/2=60M  XTAL->OSC1

    EALLOW;
    NmiIntruptRegs.NMIFLGCLR.bit.CLOCKFAIL = 1;
    NmiIntruptRegs.NMIFLGCLR.bit.NMIINT = 1;
    EDIS;
}

void 
PLL_Initial(Uint16 val, Uint16 divsel)
{
   volatile Uint16 iVol;

   //
   // 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
    }

    //
    // DIVSEL MUST be 0 before PLLCR can be changed from
    // 0x0000. It is set to 0 by an external reset XRSn
    // This puts us in 1/4
    //
    if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0)
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;
        EDIS;
    }

    //
    // Change the PLLCR
    //
    if (SysCtrlRegs.PLLCR.bit.DIV != val)
    {
        EALLOW;
        
        //
        // Before setting PLLCR turn off missing clock detect logic
        //
        SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
        SysCtrlRegs.PLLCR.bit.DIV = val;
        EDIS;

        //
        // Optional: Wait for PLL to lock.
        //
        // During this time the CPU will switch to OSCCLK/2 until
        // the PLL is stable.  Once the PLL is stable the CPU will
        // switch to the new PLL value.
        //
        // This time-to-lock is monitored by a PLL lock counter.
        //
        // Code is not required to sit and wait for the PLL to lock.
        // However, if the code does anything that is timing critical,
        // and requires the correct clock be locked, then it is best to
        // wait until this switching has completed.
        //
        
        //
        // Wait for the PLL lock bit to be set.
        //

        //
        // The watchdog should be disabled before this loop, or fed within
        // the loop via ServiceDog().
        //

        //
        // Uncomment to disable the watchdog
        //
        DisableDog();

        while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
        {
            //
            // Uncomment to service the watchdog
            //
            // ServiceDog();
        }

        EALLOW;
        SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;
        EDIS;
    }

    //
    // If switching to 1/2
    //
    if((divsel == 1)||(divsel == 2))
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel;
        EDIS;
    }

    //
    // If switching to 1/1
    // * First go to 1/2 and let the power settle
    //   The time required will depend on the system, this is only an example
    // * Then switch to 1/1
    //
    if(divsel == 3)
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;
        DELAY_US(50L);
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;
        EDIS;
    }
}

  • Your test condition is similar to case D shown in page 74  of www.ti.com/lit/SPRUI10: "PLLCR is zeroed. The user must reconfigure PLLCR"

  • Thank you for your reply.
    That's right. It imitates caseD.
    So why does the CPU stop working when resetting is done using the PLL_Initial(12, 2) function within a non-maskable interrupt?
    Please let me know the possible causes.
    I have attached the XTAL initialization function.
    INTOSC1 continues to oscillate.

    void XTAL_Sel (void)  {
         EALLOW;
         SysCtrlRegs.CLKCTL.bit.XTALOSCOFF = 0;     // Turn on XTALOSC
         DELAY_US(1000L);                           // 1mS delay to ensure crystal
                                                    // oscillator is up and running.
                                                    // Adjust as needed.
         SysCtrlRegs.CLKCTL.bit.XCLKINOFF = 1;      // Turn off XCLKIN
         SysCtrlRegs.CLKCTL.bit.OSCCLKSRC2SEL = 0;  // Switch to external clock
         SysCtrlRegs.CLKCTL.bit.OSCCLKSRCSEL = 1;   // Switch from INTOSC1 to INTOSC2/ext clk
         SysCtrlRegs.CLKCTL.bit.WDCLKSRCSEL = 0;    // Clock Watchdog off of INTOSC1
         SysCtrlRegs.CLKCTL.bit.INTOSC2OFF = 1;     // Turn off INTOSC2
         SysCtrlRegs.CLKCTL.bit.INTOSC1OFF = 0;    // Leave INTOSC1 on
         EDIS;
    }

  • Can you please clarify what you mean my "CPU stop working"? CPU has to be doing something. Meaning, it has to be executing some code. It cannot simply "stop". The only time CPU actually stops (i.e. not do anything) is in one of the 3 low-power modes (IDLE, STANDBY or HALT)

  • That's exactly what you said. No code is written to transition to LPM_MODE.
    When I checked the details, it was only that SCI communication was not possible.
    I am generating a 2ms task with CPUTIMER0, but it has changed to a 1ms cycle.
    NG occurs when executing PLL_Initial(12, 2) within a non-maskable interrupt.
    Do not reset. Or PLL_Initial(6, 2) is OK.
    From the above, it seems that it has not switched to INTOSC1.
    I understand that INTOSC1 switches automatically when CLOCKFAIL is detected.
    Do I need to make any settings in advance?

  • I understand that INTOSC1 switches automatically when CLOCKFAIL is detected

    Correct.

    It appears that the CPU does not actually "stop" but the behavior of your code is changing. I suggest you use the functions in DSP2803x_SysCtrl.c "as is" (see C:\ti\c2000\C2000Ware_5_01_00_00\device_support\f2803x\common\source directory). These are tested functions and should work without any modifications.

  • Thank you. Please tell me a little more.
    In the InitPll function of the DSP2803x_SysCtrl.c file,
    while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
    {
    //
    // Uncomment to service the watchdog
    //
    // ServiceDog();
    }
    Is it okay to leave ServiceDog(); commented out?
    Is internal WD enabled/disabled unrelated to CLK switching?
    Is it okay to delete IntOsc1Sel() in InitSysCtrl(void) and write XtalOscSel() as I understand?
    Best regards!

  • Is it okay to leave ServiceDog(); commented out?

    If the WD counter overflows, it will reset the device.

    Is internal WD enabled/disabled unrelated to CLK switching?

    Yes.

    Is it okay to delete IntOsc1Sel() in InitSysCtrl(void) and write XtalOscSel() as I understand?

    Yes. As mentioned before, you should have no issues if you use the functions "as is" from C2000ware.