blob: ed4208285dceb1bf085ba72275b5ac60c23907dc (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
#include "rcc.h"
#include "flash.h"
#include "../syscfg/syscfg.h"
void rcc_init() {
// Initialize flash.
flash_init();
#if defined(STM32F1) || defined(STM32F3)
// Enable (assumed 8MHz!) HSE
RCC->CR |= 0x10000;
while(!(RCC->CR & 0x20000));
// Configure and enable PLL from HSE.
auto pll_mul = 9;
RCC->CFGR = ((pll_mul-2)<<18) | (0x2 << 15);
RCC->CR |= 0x1000000;
while(!(RCC->CR & 0x2000000));
// Switch to PLL.
RCC->CFGR |= 0x2;
while(!(RCC->CFGR & 0x8));
// Set APB1 prescaler to /2.
RCC->CFGR |= 0x400;
// Set ADCCLK prescaler to /6. => 12MHz is ~sufficient
#if defined(STM32F1)
RCC->CFGR |= 0x8000;
#else
RCC->CFGR2 = (0b10011 << 9) | (0b10011 << 4);
#endif
#elif defined(STM32F4)
// Enable HSE.
RCC->CR |= 0x10000;
while(!(RCC->CR & 0x20000));
// Configure and enable PLL.
RCC->PLLCFGR = 0x20400000 | (7 << 24) | (2 * 168 << 6) | 8;
RCC->CR |= 0x1000000;
while(!(RCC->CR & 0x2000000));
// Switch to PLL.
RCC->CFGR |= 0x2;
while(!(RCC->CFGR & 0x8));
// Set APB1 prescaler to /4.
RCC->CFGR |= 5 << 10;
// Set APB2 prescaler to /2.
RCC->CFGR |= 4 << 13;
#elif defined(STM32F0)
// Enable HSI48.
RCC->CR2 |= 1 << 16; // HSI48ON
while(!(RCC->CR2 & (1 << 17))); // HSI48RDY
// Switch to HSI48.
RCC->CFGR |= 3 << 0; // SW = HSI48
while((RCC->CFGR & (3 << 2)) != (3 << 2)); // SWS = HSI48
#elif defined(STM32L0)
// Enable HSI16.
RCC->CR |= 1 << 0; // HSI16ON
while(!(RCC->CR & (1 << 2))); // HSI16RDYF
// Configure PLL.
RCC->CFGR |= (1 << 22) | (1 << 18) | (0 << 16); // PLLDIV = /2, PLLMUL = 4x, PLLSRC = HSI16
// Enable PLL.
RCC->CR |= 1 << 24; // PLLON
while(!(RCC->CR & (1 << 25))); // PLLRDY
// Switch to PLL.
RCC->CFGR |= 3 << 0; // SW = PLL
while((RCC->CFGR & (3 << 2)) != (3 << 2)); // SWS = PLL
// Enable VREFINT for HSI48.
RCC->enable(RCC->SYSCFG);
SYSCFG.CFGR3 |= (1 << 13) | (1 << 0); // ENREF_HSI48, EN_VREFINT
while(!(SYSCFG.CFGR3 & (1 << 26))); // REF_HSI48_RDYF
// Enable HSI48.
RCC->CRRCR |= 1 << 0; // HSI48ON
while(!(RCC->CRRCR & (1 << 1))); // HSI48RDY
// Select HSI48 for USB.
RCC->CCIPR |= 1 << 26;
#elif defined(STM32WB)
// Enable HSE.
RCC->CR |= (1<<16);
while(!(RCC->CR & (1<<17)));
// Configure and enable PLL.
// R=2, Q = 2, P = 2, M = 2, N = 8, src=HSE
const auto m = 2;
const auto n = 8;
const auto p = 2;
const auto q = 2;
const auto r = 2;
RCC->PLLCFGR = ((r-1)<<29) | (1<<28) | ((q-1)<<25) | ((p-1)<<17) | (n<<8) | ((m-1)<<4) | (3<<0);
RCC->CR |= (1<<24);
while(!(RCC->CR & (1<<25)));
// 64MHz/2 to keep CPU2 in bounds
RCC->EXTCFGR |= (0b1000 << 4);
// Switch to PLL.
RCC->CFGR |= 0x3;
while((RCC->CFGR & (3 << 2)) != (3 << 2)); // SWS = PLL
#endif
}
#if defined(STM32F4) || defined(STM32F7)
void rcc_init(uint32_t osc_mhz, uint32_t sysclk_mhz) {
// Initialize flash.
flash_init();
uint32_t pll_mhz = sysclk_mhz > 192 / 2 ? sysclk_mhz * 2 : sysclk_mhz * 4;
uint32_t pllp = sysclk_mhz > 192 / 2 ? 0 : 1;
// Enable HSE.
RCC->CR |= 0x10000;
while(!(RCC->CR & 0x20000));
// Configure and enable PLL.
RCC->PLLCFGR = 0x20400000 | ((pll_mhz / 48) << 24) | (pllp << 16) | (pll_mhz << 6) | osc_mhz;
RCC->CR |= 0x1000000;
while(!(RCC->CR & 0x2000000));
// Switch to PLL.
RCC->CFGR |= 0x2;
while(!(RCC->CFGR & 0x8));
if(sysclk_mhz > 84) {
// Set APB1 prescaler to /4.
RCC->CFGR |= 5 << 10; // PPRE1
// Set APB2 prescaler to /2.
RCC->CFGR |= 4 << 13; // PPRE2
} else {
// Set APB1 prescaler to /2.
RCC->CFGR |= 4 << 10; // PPRE1
// Set APB2 prescaler to /1.
RCC->CFGR |= 0 << 13; // PPRE2
}
}
#endif
|