cancel
Showing results for 
Search instead for 
Did you mean: 

PLLRDY Not Going Active For External Crystal

ryanrj
Associate
Posted on March 01, 2013 at 20:52

I have three prototypes assembled that use the STM32F407 processor. Two of the boards work fine but the third board is having a problem with the clock setup.

I am using an external 25MHz crystal and setting the main PLL to output 144MHz. As I said, two of the boards work fine. On the third board HSERDY goes true but after configuring the PLL and turning it on, the PLLRDY flag never goes true. It will go true if I use HSI instead of HSE.

I am using a lightly modified version of the ST Micro code from the demo board (with 144MHz instead of 168MHz though I tried changing that as well). Works with the two other boards so I don't think it is a code issue.

It is the exact same circuit design as the demo board. I tried replacing the crystal and its caps resistor.

Any suggestions?

#delay #keil-iar-pll-crystal
5 REPLIES 5
Posted on March 01, 2013 at 21:10

Check thoroughly supply pins, decoupling/bulk cap. Check capacitor and voltages present on VCAP pins. Check stability of HSE. Use a scope, check for noise.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ryanrj
Associate
Posted on March 04, 2013 at 20:04

Thanks for the reply. I rechecked all the connections and they looked fine. The crystal signals were very small though. Did some checking on the crystal itself and found out that instead of a crystal with a load capacitance of 20pF we ordered one with a CL of 8pF! I pulled off the load caps on the board and it works fine (with board and pin capacitance only). Not sure why HSE would be shown as running but not be able to get the PLL to work. Maybe is was a load issue. Anyway, I'll need to make sure we order the correct part for production.

huang_yn
Associate
Posted on April 07, 2014 at 06:06

I encountered the similar issue recently.

I used 25MHz crystal. The MCU was STM32F207VGT6. And I used STMicro standard library STM32F2xx_StdPeriph_Lib_V1.1.0. The system_stm32f2xx.c was generated by use of STM32F2xx_Clock_Configuration_V1.2.0.xls, with the following settings, system clock 120MHz, crystal 25MHz, PLL using HSE.

The problem appeared when I was trying to output a 24MHz clock from MCO2. When the board was running, I measured the MCO2, it was around 3.2MHz instead of 24MHz. It indicated the system clock is 16MHz, instead of 120MHz. Then in Keil uVision debug mode, I checked register RCC_CR. Its content was 0x00037F83. This register value showed PLLRDY = 0, PLL was unlocked. And HSERDY = 1, HSE oscillator was ready.

Further tested the code by putting while(1) endless loop in the following “else� branch. Found the program stopped there, this indicated HSE was not ready when the Timeout was reached. The program never entered another branch to set PLL.

static void SetSysClock(void)

{

/******************************************************************************/

/*            PLL (clocked by HSE) used as System clock source                */

/******************************************************************************/

  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

  /* HYN: MCO2 Setting, source Sysclk, division by 5*/

  RCC->CFGR &= ~(RCC_CFGR_MCO2);

  RCC->CFGR       |= RCC_CFGR_MCO2PRE;

 

  /* Enable HSE */

  RCC->CR |= ((uint32_t)RCC_CR_HSEON);

  /* Wait till HSE is ready and if Time out is reached exit */

  do

  {

    HSEStatus = RCC->CR & RCC_CR_HSERDY;

    StartUpCounter++;

  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)

  {

    HSEStatus = (uint32_t)0x01;

  }

  else

  {

    HSEStatus = (uint32_t)0x00;

  }

  if (HSEStatus == (uint32_t)0x01)

  {

    /* HCLK = SYSCLK / 1*/

    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

     

    /* PCLK2 = HCLK / 2*/

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

   

    /* PCLK1 = HCLK / 4*/

    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

    /* Configure the main PLL */

    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |

                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

    /* Enable the main PLL */

    RCC->CR |= RCC_CR_PLLON;

    /* Wait till the main PLL is ready */

    while((RCC->CR & RCC_CR_PLLRDY) == 0)

    {

    }

  

    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */

    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;

    /* Select the main PLL as system clock source */

    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));

    RCC->CFGR |= RCC_CFGR_SW_PLL;

    /* Wait till the main PLL is used as system clock source */

    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);

    {

    }

  }

  else

  { /* If HSE fails to start-up, the application will have wrong clock

         configuration. User can add here some code to deal with this error */

   while (1);

  }

}

As the HSE oscillator was not ready when the Timeout was reached, it will be useful if we increase the Timeout setting.

I increased HSE_STARTUP_TIMEOUT from 0x500 (default) to 0x1000. Re-built the program and run, I got the 24MHz clock from MCO2. The RCC_CR value became 0x03037F83, PLLRDY = 1 (PLL locked).

On the other hand, I kept HSE_STARTUP_TIMEOUT value to default, i.e. 0x500. I changed the crystal external load capacitors value from 27pF to 18pF. With this change, HSE can get ready before the Timeout is reached and PLL will be turned on and locked.

But there is a strange thing for this issue. All above I described, I was using Keil uVision V4.21.0.0. My colleagues use latest IAR EWARM, this issue does not appear. With HSE_STARTUP_TIMEOUT = 0x500, load capacitor value 27pF, HSE can get ready before the Timeout is reached.

So, I am wondering what can cause the different behavior between Keil MDK-ARM and IAR EWARM. With Keil compiler, the code reached the loop “do … while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT))� earlier than IAR compiled code?

In summary, the issue PLL is unlocked is because HSE oscillator is not ready when the Timout is reached. To solve this issue, either increasing the timeout limit HSE_STARTUP_TIMOUT or adjusting the load capacitors value.

os_kopernika
Associate II
Posted on April 07, 2014 at 11:16

StartUpCounter++;

Depending on the implementation this op-code and optimization it can be made faster or slower - the delay is not precise.

Posted on April 07, 2014 at 14:06

Software delay loops are notoriously non-portable.

The code here could be made significantly more robust, for example having a specific ''time'' related timeout, and fail-over code which for example might use the HSI+PLL when the HSE doesn't start, and provide some error/fault that can be passed to a user. Perhaps an LED, or Test Point GPIO.

The code is designed to be tailored to your specific board/project, and if used commercially should be analyzed more thoroughly, with consideration of manufacturing defects and production/final test.

Anywhere ST places ''while(1);'' is a candidate for the developer to add more appropriate code for their system.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..