Estoy confundido con respecto al cambio del árbol de reloj de un STM32F103 Cortex M3 en el tiempo de ejecución y espero que alguien pueda ayudarme con eso.
Estoy usando una placa de desarrollo que tiene un HSE de 8Mhz a bordo. Según la configuración predeterminada del archivo STM SPL stm32f10x_system.c, se selecciona PLL (derivado de HSE) como la fuente SYSCLK en el arranque.
Me gustaría usar PLL como fuente (derivado de HSI). Por lo que he entendido, los pasos principales son
- Habilitar HSI. Espera a que esté listo
- Establezca HSI como fuente SYSCLK. Establecer HCLK, PCLK1 & PCLK2 en consecuencia
- Deshabilitar PLL. Cambie su fuente a HSI y establezca el multiplicador
- Habilitar PLL. Espera a que esté listo el PLL
- Establece PLL como fuente SYSCLK. establecer HCLK, PCLK1 & PCLK2 en consecuencia
Según lo anterior, escribí mi rutina llamada cuando se inicia main ()
//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);
Esto funciona bien. Luego me di cuenta de que tendría que cambiar la latencia de FLASH y también mi reloj
Así que hice esto
//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);
Esto también funciona. Así que mis preguntas son
- ¿Es opcional el ajuste de la latencia del flash? ya que en mi caso funcionó incluso sin él.
- ¿Cuándo llama exactamente a la función FLASH_SetLatency con el nuevo estado de espera? ¿Antes de configurar el nuevo reloj o justo después?