STM32F103 ARM – Ändern der Uhr zur Laufzeit – FLASH-Latenz

Ich bin verwirrt, wenn es darum geht, den Taktbaum eines STM32F103 Cortex M3 zur Laufzeit zu ändern, und ich hoffe, dass mir jemand dabei helfen kann.

Ich verwende ein Entwicklungsboard, das ein 8-MHz-HSE an Bord hat. Gemäß der Standardkonfiguration der STM-SPL-Datei stm32f10x_system.c wird PLL (abgeleitet von HSE) beim Booten als SYSCLK-Quelle ausgewählt.

Ich möchte PLL als Quelle verwenden (abgeleitet von HSI). Nach dem, was ich verstanden habe, sind die wichtigsten Schritte

  1. Aktivieren Sie HSI. Warten Sie, bis es fertig ist
  2. Stellen Sie HSI als SYSCLK-Quelle ein. Stellen Sie HCLK, PCLK1 & PCLK2 entsprechend ein
  3. PLL deaktivieren. Ändern Sie die Quelle auf HSI und stellen Sie den Multiplikator ein
  4. PLL aktivieren. Warten Sie, bis PLL bereit ist
  5. Stellen Sie PLL als SYSCLK-Quelle ein. stellen Sie HCLK, PCLK1 & PCLK2 entsprechend ein

Wie oben beschrieben habe ich meine Routine geschrieben, die aufgerufen wird, wenn main() startet

//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);

Das funktioniert gut. Dann wurde mir klar, dass ich die FLASH-Latenz sowie meine Uhr ändern müsste

Also habe ich das gemacht

//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);

Das funktioniert auch. Also meine Fragen sind

  1. Ist die Einstellung der Flash-Latenz optional? da es bei mir auch ohne funktioniert hat.
  2. Wann genau rufen Sie die Funktion FLASH_SetLatency mit dem neuen Wartezustand auf? Vor dem Einstellen der neuen Uhr oder gleich danach?

Antworten (2)

Ist die Einstellung der Flash-Latenz optional? da es bei mir auch ohne funktioniert hat.

Nein. Wenn Sie die Flash-Latenzzeit nicht korrekt einstellen, liest Ihr Programm möglicherweise manchmal falsche Daten aus dem Flash-Speicher.

Wann genau rufen Sie die Funktion FLASH_SetLatency mit dem neuen Wartezustand auf? Vor dem Einstellen der neuen Uhr oder gleich danach?

Vor dem Erhöhen der Systemtaktfrequenz oder nach dem Verringern.

Eine zu hohe Latenz für den Systemtakt ist meistens harmlos – es wird das System etwas verlangsamen, aber das war’s – aber eine zu niedrige Latenz kann zu Fehlfunktionen führen.

Danke. Macht mehr Sinn. Bisschen verstanden having latency too high is mostly harmless... Kannst du mehr zum Before increasing the system clock frequency, or after decreasing it..Teil erklären?
Bedenken Sie: Sie könnten die Taktrate nach oben oder unten ändern. Wenn die Taktrate steigt, muss die Flash-Latenz erhöht werden, bevor die Taktrate steigt. Wenn die Taktrate sinkt, können Sie die Latenz nicht verringern, bis sich die Taktrate bereits verlangsamt hat.
Könnte die Flash-Latenzeinstellung auch in dieser Frage das Problem sein ?

Sie sollten auch diese Zeile hinzufügen: SystemCoreClock = 64000000;

  • SystemCoreClock-Variable: Enthält die Kernuhr (HCLK). Sie kann von der Benutzeranwendung verwendet werden, um den SysTick-Timer einzurichten oder andere Parameter zu konfigurieren.

Oder noch besser statt:

SystemCoreClock = 64000000;

Forderung:

SystemCoreClockUpdate();

und es berechnet die SystemCoreClock-Variable.