Halbe SYSCLK Geschwindigkeit beim STM32F205 PLL

OP #4533604
Lesenswert?

Moin zusammen, lange hier nichts mehr gepostet. Und jetzt wo ich dran 
brin... kommt erstmal ne Frage.

Ich habe ein selbstentwickeltes STM32F205 Board, der Hardwaremäßig 
funktioniert. Flashen, programmieren, LEDs blinken, alles toll.

I möchte jetzt die Frequenz des SYSCLK auf ~98 MHz erhöhen (12.288 MHz 
Kristall x 8), leider bekomme ich beim Ausgang des PLLs nur die Hälfte? 
Um das zu testen, habe ich ein SysTick timer konfiguriert, der jede 1000 
Ticks ein Interrupt auslöst. Da wird kurz mal ein LED hoch und runter 
geschaltet.

Gemessen am Oszi funktioniert der SysTick ganz gut bei HSI oder HSE (je 
16 oder 12.288 KHz Signal), aber wie gesagt, beim PLL, zeigt es dann nur 
49 KHz statt erwarteten 98 KHz.

Weiter runter habe ich das Code mit Kommentare. Und Entschuldigung wenn 
mein Deutsch etwas komisch klingt, wohne seit ein paar Jahren nicht mehr 
in DE!

Albert
1
#include "typedef.h"
2

3
#include "stm32f2xx.h"
4
#include "stm32f2xx_it.h"
5

6
#include "digIo.h"
7

8
void initFlash(void);
9
void initClocks(void);
10

11
char ledsOn = 0x1;
12

13
int main(void){
14

15
    initFlash();
16
    initClocks();
17

18
    /** Set timer to 98 KHz **/
19
  if (SysTick_Config(1000))
20
  {
21
    /* Capture error */
22
    while (1);
23
  }
24

25
    initLEDS();
26

27
    setLED_Off(0);
28
    setLED_Off(1);
29
    setLED_Off(2);
30
    setLED_Off(3);
31

32
    setLED_On(0);
33
    setLED_On(1);
34
    setLED_On(2);
35
    setLED_On(3);
36

37
    while(1){
38

39
        if(timerExpired == 1){
40
            timerExpired = 0;
41

42
            setLED_On(3);
43
            setLED_Off(3);
44
        }
45
    }
46

47
}
48

49
void initFlash(void){
50

51
  /** Set three wait states **/
52
  FLASH->ACR |= FLASH_ACR_LATENCY_3WS ;
53
}
54

55
void initClocks(void){
56

57
  /** Initialize clock to external clock (12.288 MHz) **/
58
  RCC->CR |= RCC_CR_HSEON;
59
  while(!(RCC->CR & RCC_CR_HSERDY)){
60
    ;
61
  }
62

63
  /** Set PLL source to HSE **/
64
  RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;
65

66
  /** Set M divider to 0x8 (/8) **/
67
  RCC->PLLCFGR |= (RCC_PLLCFGR_PLLM_3);
68

69
  /** Set N multiplier to 0x80 (x128) **/
70
  RCC->PLLCFGR |= (RCC_PLLCFGR_PLLN_7);
71

72
  /** Set P divider to 0x0 (/2) **/
73
  RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLP);
74

75
  /** Enable PLL **/
76
  RCC->CR |= RCC_CR_PLLON;
77
  while(!(RCC->CR & RCC_CR_PLLRDY)){
78
    ;
79
  }
80

81
  /** Set SW to PLL **/
82
  RCC->CFGR |= RCC_CFGR_SW_PLL;
83
  while(!(RCC->CFGR & RCC_CFGR_SWS_PLL)){
84
    ;
85
  }
86
}
OP #4534708
Lesenswert?

Ich meine in dem Fall ist der SystemCoreClock nur der Wert des 
erwarteten PLL Ausgangs.

Bei SysTick_Config(1000) heisst es (so wie ich das verstehe), nach 1000 
ticks (clocks), löse Interrupt aus.

Man kann auch SysTick_Config(SystemCoreClock/1000) konfigurieren, dann 
kommt der Interrupt eben alle 1 ms. Deswegen wird der Wert 
SystemCoreClock neu geschrieben.

Ich werde nochmal weiterschauen, mir ist aufgefallen ich habe was an 
Flash wait states und prefetch vergessen.
OP #4534725
Lesenswert?

Lösung gefunden.

Es scheint als ob man das RCC->PLLCFGR register in einem Schritt 
beschreiben muss. So sieht es jetzt aus
1
void initClocks(void){
2

3
  /** Initialize clock to external clock (12.288 MHz) **/
4
  RCC->CR |= RCC_CR_HSEON;
5
  while(!(RCC->CR & RCC_CR_HSERDY)){
6
    ;
7
  }
8

9
  /** Flash configuration **/
10
    /** Flash prefetch and cache ON, Flash 3 wait state **/
11
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;
12

13
  /** Set M divider to 0x8 (/8) **/
14
  /** Set N multiplier to 0x80 (x128) **/
15
  /** Set P divider to 0x0 (/2) **/
16
  /** Set PLL source to HSE **/
17
    RCC->PLLCFGR = (0x8 | ((uint32_t)0x80 << 6) | (((0x2 >> 1) -1) << 16)) | (RCC_PLLCFGR_PLLSRC_HSE);
18

19
  /** Enable PLL **/
20
  RCC->CR |= RCC_CR_PLLON;
21
  while(!(RCC->CR & RCC_CR_PLLRDY)){
22
    ;
23
  }
24

25
  /** Set SW to PLL **/
26
  RCC->CFGR |= RCC_CFGR_SW_PLL;
27
  while(!(RCC->CFGR & RCC_CFGR_SWS_PLL)){
28
    ;
29
  }
30
}

Un es läuft wie erwartet, schön 98 Khz Interrupts ausgelöst.

Albert.
Gast #4535259
Lesenswert?

Albert F. schrieb:
> Ich meine in dem Fall ist der SystemCoreClock nur der Wert des
> erwarteten PLL Ausgangs.
>
> Bei SysTick_Config(1000) heisst es (so wie ich das verstehe), nach 1000
> ticks (clocks), löse Interrupt aus.

Ah, richtig. Das habe ich elegant überlesen.

Danke noch für den Hinweis. Bei mir ist aktuell der PLLCFGR zwar in 
einem durch, aber man weiß ja nie, was man daran mal ändern will.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren