1
\$\begingroup\$

I am having b it of confusion regarding changing the clock tree of an STM32F103 Cortex M3 at runtime and I am hoping someone can help me with it.

I am using a development board which has a 8Mhz HSE on board. As per the defaylt configuration of STM SPL stm32f10x_system.c file, PLL (derived from HSE) is selected as the SYSCLK source on boot.

I would like to use PLL as the source (derived from HSI). From what I have understood, the main steps are

  1. Enable HSI. Wait for it to be ready
  2. Set HSI as SYSCLK source. Set HCLK, PCLK1 & PCLK2 accordingly
  3. Disable PLL. Change it's source to HSI and set multiplier
  4. Enable PLL. Wait for PLL to be ready
  5. Set PLL as SYSCLK source. set HCLK, PCLK1 & PCLK2 accordingly

As per above I wrote my routine called when main() starts

//TURN ON HSI AND SET IT AS SYSCLK SRC
RCC_HSICmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET){};

//SET HSI AS SYSCLK SRC. CONFIGURE HCLK, PCLK1 & PCLK2
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);

//DISABLE PLL
RCC_PLLCmd(DISABLE);

//CHANGE PLL SRC AND MULTIPLIER
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16);

//ENABLE PLL
//WAIT FOR IT TO BE READY
//SET SYSCLK SRC AS PLLCLK
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){};
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

//SET HCLK = SYSCLK = 64MHZ
RCC_HCLKConfig(RCC_SYSCLK_Div1);

//SET PCLK2 = HCLK = 64MHZ
RCC_PCLK2Config(RCC_HCLK_Div1);

//SET PCLK1 = HCLK/2 = 32MHZ
RCC_PCLK1Config(RCC_HCLK_Div2);

This works just fine. Then I realized that I would need to change the FLASH latency as well as per my clock

So I did this

//SETUP THE SYSTEM CLOCK AS BELOW
//CLOCK SRC = 8MHZ HSI + PLL
//SYSCLK = 64MHZ
//HCLK = SYSCLK = 64MHZ
//PCLK2 = HCLK = 64MHZ
//PCLK1 = HCLK = 32MHZ

//TURN ON HSI AND SET IT AS SYSCLK SRC
RCC_HSICmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET){};

//SET HSI AS SYSCLK SRC. CONFIGURE HCLK, PCLK1 & PCLK2
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);

//SET THE FLASH LATENCY AS PER OUR CLOCK
//FASTER THE CLOCK, MORE LATENCY THE FLASH NEEDS
//000 Zero wait state, if 0  MHz < SYSCLK <= 24 MHz
//001 One wait state, if  24 MHz < SYSCLK <= 48 MHz
//010 Two wait states, if 48 MHz < SYSCLK <= 72 MHz */
FLASH_SetLatency(FLASH_Latency_0);

//DISABLE PLL
RCC_PLLCmd(DISABLE);

//CHANGE PLL SRC AND MULTIPLIER
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16);

//ENABLE PLL
//WAIT FOR IT TO BE READY
//SET SYSCLK SRC AS PLLCLK
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){};
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

FLASH_SetLatency(FLASH_Latency_2);

//SET HCLK = SYSCLK = 64MHZ
RCC_HCLKConfig(RCC_SYSCLK_Div1);

//SET PCLK2 = HCLK = 64MHZ
RCC_PCLK2Config(RCC_HCLK_Div1);

//SET PCLK1 = HCLK/2 = 32MHZ
RCC_PCLK1Config(RCC_HCLK_Div2);

This also works. So my questions are

  1. Is setting flash latency optional? since in my case it worked even without it.
  2. When exactly do you call the FLASH_SetLatency function with the new wait state? Before setting the new clock or right after?
\$\endgroup\$
5
\$\begingroup\$

Is setting flash latency optional? since in my case it worked even without it.

No. If you do not set the flash latency correctly, your program may sometimes read incorrect data from flash memory.

When exactly do you call the FLASH_SetLatency function with the new wait state? Before setting the new clock or right after?

Before increasing the system clock frequency, or after decreasing it.

Having the latency too high for the system clock is mostly harmless -- it will slow the system down slightly, but that's it -- but having the latency set too low may cause malfunctions.

\$\endgroup\$
  • \$\begingroup\$ Thanks. Makes more sense. Understood the having latency too high is mostly harmless.. bit. Can you explain more on Before increasing the system clock frequency, or after decreasing it.. part? \$\endgroup\$ – Ankit Mar 23 '17 at 6:15
  • 1
    \$\begingroup\$ Consider: You could be changing the clock speed up or down. If the clock speed's going up, the flash latency needs to be increased before the clock speed goes up. If the clock speed is going down, you can't decrease the latency until the clock speed has already slowed down. \$\endgroup\$ – duskwuff Mar 23 '17 at 6:38
  • 1
    \$\begingroup\$ Could Flash Latency setting be the problem in this question too? \$\endgroup\$ – Bence Kaulics Mar 23 '17 at 7:57
1
\$\begingroup\$

You should also add this line: SystemCoreClock = 64000000;

  • SystemCoreClock variable: Contains the core clock (HCLK), it can be used by the user application to setup the SysTick timer or configure other parameters.

Or even better, instead of:

SystemCoreClock = 64000000;

call:

SystemCoreClockUpdate();

and it will calculate the SystemCoreClock variable.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.