AnsweredAssumed Answered

ADSP-21479 PLL issue

Question asked by marc_s1 on Feb 27, 2017
Latest reply on Mar 29, 2017 by Jithul_Janardhanan

Hello all,

 

I am using the ADSP-21479 and encounter the phenomenon that my firmware does NOT ALWAYS boot. I think that setting up the PLL is the problem, since with default PLL settings my firmware boots OK (CLK_CFG1:0 = 00). This is also a confirmation that reading the firmware from EEPROM functions correctly.

 

The code I use for PLL setup is according to ADSP-21477_21478_21479_anomaly_RevH 15000020 (see code below, where f_target = 266.0 MHz and f_xtal = 24.0 MHz):

 

#pragma optimize_off

/*************************** FUNCTION ************************************/
bool init_pll(float f_target, float f_xtal)
/*************************** INFO ****************************************
**
** DESCRIPTION : initialises the pll.
**
**               initialisation steps according ADSP-2147x anomaly list:
**               15000020 - PLL Programming may not take effect under
**               specific conditions (CASE 1)
**
** INPUT       : f_target: target cclk frequency (in MHz).
**               f_xtal:   target xtal frequency (in Mhz).
**
** OUTPUT      : none
**
** RETURN      : TRUE, initialised successfully.
**************************************************************************/
{
  bool   init_ok = FALSE;
  bool   freq_ok = FALSE;
  uint32 div_table[4] = {2, 4, 8, 16}; 
  uint32 cnt;
  uint32 pmctlsetting; 
  uint32 pll_m, pll_m_current;
  uint32 pll_d;
  float  f_vco, f_vco_current;
 
  pmctlsetting  = *pPMCTL;
 
  pll_m_current = pmctlsetting & 0x0000003F;
  f_vco_current = 2 * pll_m_current * f_xtal;

  if(f_target >  FCORE_MIN &&
     f_target <= FCORE_MAX &&
     f_xtal   >  FXTAL_MIN   )
  {
    pll_d = sizeof(div_table);
   
    while(!freq_ok && pll_d > 0)
    {   
      pll_d--;       
     
      f_vco = f_target * div_table[pll_d];
     
      if((f_vco <= FVCO_MAX) &&
         (f_vco >= FVCO_MIN)   )
      {
        pll_m = (uint32)(f_vco / f_xtal + 0.5);
       
        if(pll_m > 0 && pll_m < 64)
        {
          adsp.cclk_freq = (2 * pll_m * (f_xtal / 2)) / div_table[pll_d];
          adsp.cclk_freq = adsp.cclk_freq * 1000000.0;
          adsp.pclk_freq = adsp.cclk_freq / 2.0;

          freq_ok = TRUE;              
          init_ok = TRUE;
        }
      }
    } 
   
    if(freq_ok)
    {
      /* step 1 */
      pmctlsetting  = *pPMCTL;
      pmctlsetting &= ~PLLD16;
      pmctlsetting |= (PLLD4 | DIVEN);
      *pPMCTL       = pmctlsetting;
   
      /*step 2 */
      for(cnt = 0; cnt < 16; cnt++)
        NOP;
     
      /* step 3 - 6 are not needed when current f_vco < FVCO_MAX / 2 */
           
      if(f_vco_current >= FVCO_MAX / 2)
      {
        /* step 3 */
        pmctlsetting &= ~DIVEN;
        pmctlsetting |= (INDIV | PLLBP);
        *pPMCTL       = pmctlsetting;
     
        /* step 4 */
        for(cnt = 0; cnt < 4096; cnt++)
          NOP;
     
        /* step 5 */
        pmctlsetting  = *pPMCTL;
        pmctlsetting &= ~PLLBP;
        *pPMCTL       = pmctlsetting;
     
        /* step 6 */
        for(cnt = 0; cnt < 16; cnt++)
          NOP;
      }
     
      /* step 7 */
      pmctlsetting  = *pPMCTL;
      pmctlsetting &= ~(PLLM63 | DIVEN);
      pmctlsetting |= ((pll_m << 0) | INDIV | PLLBP);
      *pPMCTL       = pmctlsetting;
   
      /* step 8 */
      for(cnt = 0; cnt < 4096; cnt++)
        NOP;
     
      /* step 9 */
      pmctlsetting  = *pPMCTL;
      pmctlsetting &= ~PLLBP;
      *pPMCTL       = pmctlsetting;
   
      /* step 10 */
      for(cnt = 0; cnt < 16; cnt++)
        NOP;
   
      /* step 11 */
      pmctlsetting  = *pPMCTL;
      pmctlsetting &= ~(PLLD16 | 0x1C0000);
      pmctlsetting |= (SDCKR2 | (pll_d << 6) | DIVEN);
      *pPMCTL       = pmctlsetting;
        
      /* step 12 */
      for(cnt = 0; cnt < 16; cnt++)
        NOP; 
    }
  }
 
  return(init_ok);
}

#pragma optimize_as_cmd_line

 

Any help to get this working would be greatly appreciated!

Outcomes