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.

PLL is not unlocking

I am working on a custom boot loader.  I have a function being executed from boot.asm called loader_main().  The first line of this function is InitSysCtrl();().  When I run this as an actual app (loader_main is changed to main()) in RAM the application runs as expected.  However, when executing from FLASH the PLL does not unlock and gets stuck.  Is this a problem from executing from FLASH?  I am using the 28335 control card.

  • Christopher,

    There is no expected problem with the PLL. I suspect it is a generic issue with changing the application code from RAM based to Flash based.

    Section 4.7 of the following FAQ might help: http://processors.wiki.ti.com/index.php/C2000_Flash_Common_Issues/FAQs .

    There is also the following app note on running code from internal flash: http://focus.ti.com/mcu/docs/litabsmultiplefilelist.tsp?sectionId=96&tabId=1502&literatureNumber=spra958i&docCategoryId=1&familyId=1414 .

    Regards,
    Dave Foley

     

  • I looked through the documents and have not found anything.  There must be something different in the initialization of the hardware between a RAM build and a FLASH build.  However, none of my code is different.  The values I feed into the PLL init are the same, 10 and 2.  Again I ask the question, why does a RAM build allow the PLL to initialize and FLASH build not when they are running the same initialization code.  The code is running and I can debug.  The first line of my app is InitSysCtrl();. 

    void InitSysCtrl(void)
    {

       // Disable the watchdog
       DisableDog();

       // Initialize the PLL control: PLLCR and DIVSEL
       // DSP28_PLLCR and DSP28_DIVSEL are defined in DSP2833x_Examples.h
       InitPll(DSP28_PLLCR,DSP28_DIVSEL);

       // Initialize the peripheral clocks
       InitPeripheralClocks();
    }

    void InitPll(Uint16 val, Uint16 divsel)
    {

       // Make sure the PLL is not running in limp mode
       if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)
       {
          // Missing external clock has been detected
          // Replace this line with a call to an appropriate
          // SystemShutdown(); function.
          asm("        ESTOP0");
       }

       // 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) // this is where it remains forever
          {
              // 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;
        }


        // NOTE: ONLY USE THIS SETTING IF PLL IS BYPASSED (I.E. PLLCR = 0) OR OFF
        // 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;
        }
    }

  • Christopher,

    The PLLCR does not know whether the code is run from RAM or Flash, so it should not care. One thing to note though is that the PLLCR register is not reset by a CCS CPU Reset. It is only reset when the external pin XRSN is pulled low. Therefore, if you have a gel file that is loading the PLLCR when you connect CCS or pull a CPU reset in CCS, or if you have previously set the PLLCR to your desired value in CCS, it could look like everything is running properly when using the emulator, but when you go to stand alone mode and pull an external reset to start the flash it has to actually change the PLL. Still not clear why this would be a problem, but it is a difference between emulating and stand alone as pertains to the PLLCR register. Just a thought - don't know if it will help your debug.

    Regards,
    Dave Foley

     

  • There was a problem with my cmd file.  I was putting .obj files into a section of FLASH and missed adding the (.text) to the end.  Couldn't access registers from FLASH.

  • Excellent. Glad to hear you cleared up the issue.

    Regards,
    Dave Foley