Electronic – STM32F103 ARM – Modifying Clock At Runtime – FLASH Latency

armcortex-m3stm32stm32f10x

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?

Best Answer

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.