2016-04-14 9 views
1

Mein Projekt hat ein Problem festgestellt, bei dem die SysTick-Rate normalerweise, aber nicht immer zu schnell eingestellt ist. Ich habe den Code, der relevant ist, nicht geändert, und er scheint temperaturabhängig zu sein.STM32F0 System Clock PLL-Konfiguration und/oder Temperatur, die Fehler verursacht?

ich einen STM32F072B-DISCOVERY Board verwenden, mit VisualGDB auf Visual Studio Gemeinschaft 2015

Meiner Initialisierungscode enthält die folgende Funktion:

void Setup_Init_Clocks() 
{ 
    // Set up 48 MHz Core Clock using HSI (8Mhz) with PLL x 6 
    RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_6); 
    RCC_PLLCmd(ENABLE); 

    // Wait for PLLRDY after enabling PLL. 
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET) 
    { } 

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // Select the PLL as clock source. 
    SystemCoreClockUpdate(); 
} 

Die Noten für RCC_SYSCLKConfig() Zustand „Wenn eine Taktquelle Noch nicht bereit ist ausgewählt, der Schalter wird ausgelöst, wenn die Taktquelle bereit ist. " Das Überprüfen des PLLRDY-RCC-Flags sollte diesen Zustand identifizieren, so dass der Taktwechsel sofort erfolgt, so dass der Takt sofort gesetzt wird.

SystemCoreClockUpdate() von den Standard-STM32-Bibliotheken ist (in der Datei system_stm32f0xx.c) und neu berechnet Werte, die später verwendet werden SysTick setzen:

void SystemCoreClockUpdate (void) 
{ 
    uint32_t tmp = 0, pllmull = 0, pllsource = 0, prediv1factor = 0; 

    /* Get SYSCLK source -------------------------------------------------------*/ 
    tmp = RCC->CFGR & RCC_CFGR_SWS; 

    switch (tmp) 
    { 
    case 0x00: /* HSI used as system clock */ 
     SystemCoreClock = HSI_VALUE; 
     break; 
    case 0x04: /* HSE used as system clock */ 
     SystemCoreClock = HSE_VALUE; 
     break; 
    case 0x08: /* PLL used as system clock */ 
     /* Get PLL clock source and multiplication factor ----------------------*/ 
     pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; 
     pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; 
     pllmull = (pllmull >> 18) + 2; 

     if (pllsource == 0x00) 
     { 
     /* HSI oscillator clock divided by 2 selected as PLL clock entry */ 
     SystemCoreClock = (HSI_VALUE >> 1) * pllmull; 
     } 
     else 
     { 
     prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1; 
     /* HSE oscillator clock selected as PREDIV1 clock entry */ 
     SystemCoreClock = (HSE_VALUE/prediv1factor) * pllmull; 
     }  
     break; 
    default: /* HSI used as system clock */ 
     SystemCoreClock = HSI_VALUE; 
     break; 
    } 
    /* Compute HCLK clock frequency ----------------*/ 
    /* Get HCLK prescaler */ 
    tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; 
    /* HCLK clock frequency */ 
    SystemCoreClock >>= tmp; 
} 

Im Debugger kann ich sehen, wo dies fehlschlägt: tmp = RCC->CFGR & RCC_CFGR_SWS;, wodurch der falsche Fall ausgewählt wird.

Das sieht relativ einfach in den Disassembler:

237: tmp = RCC->CFGR & RCC_CFGR_SWS; 
0x08003262 2A 4B    ldr r3, [pc, #168] ; (0x800330c SystemCoreClockUpdate+192>) 
0x08003264 5B 68    ldr r3, [r3, #4] 
0x08003266 0C 22    movs r2, #12 
0x08003268 13 40    ands r3, r2 
0x0800326a FB 60    str r3, [r7, #12] 

Die RCC CFGR Register einen Wert von 0x0010800a hat. Die RCC_CFGR_SWS Maske ist 0x0000000c. Das Ergebnis dieser sollte sein tmp 0x08 zugewiesen, die PLL Fall der Auswahl, mit SystemCoreClock bis 48000000.

1) gesetzt wird, wenn I einen Haltepunkt an oder vor dieser Anweisung gesetzt, und Schritt durch sie richtig funktioniert, mit tmp zugewiesen 0x08, und die Uhren sind richtig eingestellt.

2) Wenn ich unmittelbar danach den Haltepunkt auf die switch-Anweisung setze, schlägt das normalerweise fehl *. tmp wird 0x0010800a zugewiesen, als ob die Anweisung ands r3, r2 übersprungen würde! Dies führt dazu, dass der Fall default ausgeführt wird und SystemCoreClock auf 8000000 gesetzt ist, obwohl der Chip mit 48 MHz läuft. mit dem schnellen SysTick als Ergebnis.

3) wenn ich den RCC_SYSCLKConfig() Anruf auf Kommentar, die Start-up-HSI Uhr verlassen ausgewählt, tmp zugeordnet 0x00 und alles funktioniert wie erwartet, mit dem Chip auf 8 MHz läuft, nicht die 48MHz, die ich will.

4) Wenn ich es unplugged für ein paar Minuten verlassen, wird es auf dem ersten Power-Up-OK arbeiten, aber an warmen Resets (einschließlich Debugging) fehlschlagen, oder wenn unplugged für

kurze Zeiträume (~ 15 Sekunden)

5) Ich vermutete, dass die PLL-Initialisierung von der Temperatur beeinflusst wird. Ich arbeite seit über einem Monat nicht mehr am Projekt und mein Arbeitsplatz ist jetzt saisonal wärmer. Ich kühlte den Chip etwas ab, indem ich eine kleine Tasse Leitungswasser auf den Chip legte. Dies war insofern erfolgreich, als das Programm jedes Mal korrekt lief! Nach dem Entfernen der Tasse und dem Erwärmen des Chips mit meinem Finger ist es erneut fehlgeschlagen.

Kann eine solche Änderung der System Clock-Konfiguration die Integrität der Berechnung beeinflussen? Gibt es etwas anderes, was ich tun sollte, um sicherzustellen, dass die Uhr richtig eingerichtet ist?

+0

Schauen Sie wie harsware ploblem. Wenn dieser Initialisierungscode - Sie können versuchen, Power-On-Reset (POR) zu konfigurieren, und einige Pause (durch einfache Schleife) etwa 1s oder weniger vor jedem Arbeitscode starten - das ist sicher, dass HSI stabilisiert ist. – imbearr

+2

haben Sie den Blitz verlangsamt, bevor Sie angefangen haben. Ja, ich verstehe, dass Sie erst nachher auf der schnelleren Uhr sind, aber vielleicht schaltet sie vor dem Multiplizieren auf eine externe Uhr um. Das Übertakten des Blitzes würde zu merkwürdigem Verhalten führen, obwohl einzelnes Treten immer noch etwas Merkwürdiges ergeben könnte/sollte. –

+0

@dwelch Danke - ich wusste nicht, dass dies notwendig war, da ich den FLASH-Teil des Referenzhandbuchs nicht im Detail gelesen habe, und es wird nicht im Uhrteil erwähnt, dass ich finden kann. Beim STM32F072 muss die Latenz für 24 MHz ≤ SYSCLK ≤ 48 MHz auf 1 gesetzt werden. Hinzufügen von "FLASH_SetLatency (FLASH_Latency_1);" vor dem Einstellen der Uhr löst das Problem. Fügen Sie das als Antwort hinzu, und ich werde es akzeptieren. – mbmcavoy

Antwort

1

Haben Sie den Blitz vor dem Start verlangsamt? Ja, ich verstehe, dass Sie erst nachher auf der schnelleren Uhr sind, aber vielleicht schaltet sie vor dem Multiplizieren auf eine externe Uhr um. das Übertakten des Blitzes würde zu merkwürdigem Verhalten führen, obwohl das einzelne Treten immer noch etwas Seltsames hervorbringen könnte