STM32F103 ARM - Modificación del reloj en tiempo de ejecución - Latencia de FLASH

1

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

  1. Habilitar HSI. Espera a que esté listo
  2. Establezca HSI como fuente SYSCLK. Establecer HCLK, PCLK1 & PCLK2 en consecuencia
  3. Deshabilitar PLL. Cambie su fuente a HSI y establezca el multiplicador
  4. Habilitar PLL. Espera a que esté listo el PLL
  5. 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

  1. ¿Es opcional el ajuste de la latencia del flash? ya que en mi caso funcionó incluso sin él.
  2. ¿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?
pregunta Ankit

2 respuestas

4
  

¿Es opcional el ajuste de la latencia del flash? ya que en mi caso funcionó incluso sin él.

No. Si no configura la latencia del flash correctamente, su programa a veces puede leer datos incorrectos de la memoria flash.

  

¿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?

Antes de aumentar la frecuencia de reloj del sistema o después de disminuirla.

Tener la latencia demasiado alta para el reloj del sistema es casi inofensivo, ralentizará ligeramente el sistema, pero eso es todo, pero tener la latencia demasiado baja puede causar un mal funcionamiento.

    
respondido por el duskwuff
0

También debe agregar esta línea: SystemCoreClock = 64000000;

  • Variable SystemCoreClock: contiene el reloj central (HCLK), se puede usar por la aplicación de usuario para configurar el SysTick temporizador o configurar otros parámetros.

O incluso mejor, en lugar de:

SystemCoreClock = 64000000;

llamada:

SystemCoreClockUpdate();

y calculará la variable SystemCoreClock.

    
respondido por el can

Lea otras preguntas en las etiquetas