Tengo un poco de confusión con respecto a cambiar el árbol del reloj de un STM32F103 Cortex M3 en 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, PLL (derivado de HSE) se selecciona 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
Como se indicó anteriormente, 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 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. Entonces mis preguntas son
¿La configuración de la latencia del flash es opcional? ya que en mi caso funciono aun sin el.
No. Si no configura correctamente la latencia flash, 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 del reloj del sistema o después de disminuirla.
Tener una latencia demasiado alta para el reloj del sistema es casi inofensivo: ralentizará un poco el sistema, pero eso es todo, pero tener una latencia demasiado baja puede causar fallas de funcionamiento.
También debe agregar esta línea: SystemCoreClock = 64000000;
O incluso mejor, en lugar de:
SystemCoreClock = 64000000;
llamar:
SystemCoreClockUpdate();
y calculará la variable SystemCoreClock.
Ankit
having latency too high is mostly harmless..
bit. ¿ Puedes explicar más enBefore increasing the system clock frequency, or after decreasing it..
parte?usuario39382
Bence Kaulics