diff options
Diffstat (limited to 'lib/chibios/os/hal/ports/STM32/STM32L4xx/hal_lld.c')
-rw-r--r-- | lib/chibios/os/hal/ports/STM32/STM32L4xx/hal_lld.c | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/lib/chibios/os/hal/ports/STM32/STM32L4xx/hal_lld.c b/lib/chibios/os/hal/ports/STM32/STM32L4xx/hal_lld.c new file mode 100644 index 000000000..ed587bbd5 --- /dev/null +++ b/lib/chibios/os/hal/ports/STM32/STM32L4xx/hal_lld.c | |||
@@ -0,0 +1,392 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file STM32L4xx/hal_lld.c | ||
19 | * @brief STM32L4xx HAL subsystem low level driver source. | ||
20 | * | ||
21 | * @addtogroup HAL | ||
22 | * @{ | ||
23 | */ | ||
24 | |||
25 | #include "hal.h" | ||
26 | |||
27 | /*===========================================================================*/ | ||
28 | /* Driver local definitions. */ | ||
29 | /*===========================================================================*/ | ||
30 | |||
31 | /*===========================================================================*/ | ||
32 | /* Driver exported variables. */ | ||
33 | /*===========================================================================*/ | ||
34 | |||
35 | /** | ||
36 | * @brief CMSIS system core clock variable. | ||
37 | * @note It is declared in system_stm32f7xx.h. | ||
38 | */ | ||
39 | uint32_t SystemCoreClock = STM32_HCLK; | ||
40 | |||
41 | /*===========================================================================*/ | ||
42 | /* Driver local variables and types. */ | ||
43 | /*===========================================================================*/ | ||
44 | |||
45 | /*===========================================================================*/ | ||
46 | /* Driver local functions. */ | ||
47 | /*===========================================================================*/ | ||
48 | |||
49 | /** | ||
50 | * @brief Initializes the backup domain. | ||
51 | * @note WARNING! Changing RTC clock source impossible without resetting | ||
52 | * of the whole BKP domain. | ||
53 | */ | ||
54 | static void hal_lld_backup_domain_init(void) { | ||
55 | |||
56 | /* Reset BKP domain if different clock source selected.*/ | ||
57 | if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { | ||
58 | /* Backup domain reset.*/ | ||
59 | RCC->BDCR = RCC_BDCR_BDRST; | ||
60 | RCC->BDCR = 0; | ||
61 | } | ||
62 | |||
63 | #if STM32_LSE_ENABLED | ||
64 | /* LSE activation.*/ | ||
65 | #if defined(STM32_LSE_BYPASS) | ||
66 | /* LSE Bypass.*/ | ||
67 | RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; | ||
68 | #else | ||
69 | /* No LSE Bypass.*/ | ||
70 | RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; | ||
71 | #endif | ||
72 | while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) | ||
73 | ; /* Wait until LSE is stable. */ | ||
74 | #endif | ||
75 | |||
76 | #if STM32_MSIPLL_ENABLED | ||
77 | /* MSI PLL activation depends on LSE. Reactivating and checking for | ||
78 | MSI stability.*/ | ||
79 | RCC->CR |= RCC_CR_MSIPLLEN; | ||
80 | while ((RCC->CR & RCC_CR_MSIRDY) == 0) | ||
81 | ; /* Wait until MSI is stable. */ | ||
82 | #endif | ||
83 | |||
84 | #if HAL_USE_RTC | ||
85 | /* If the backup domain hasn't been initialized yet then proceed with | ||
86 | initialization.*/ | ||
87 | if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { | ||
88 | /* Selects clock source.*/ | ||
89 | RCC->BDCR |= STM32_RTCSEL; | ||
90 | |||
91 | /* RTC clock enabled.*/ | ||
92 | RCC->BDCR |= RCC_BDCR_RTCEN; | ||
93 | } | ||
94 | #endif /* HAL_USE_RTC */ | ||
95 | |||
96 | /* Low speed output mode.*/ | ||
97 | RCC->BDCR |= STM32_LSCOSEL; | ||
98 | } | ||
99 | |||
100 | /*===========================================================================*/ | ||
101 | /* Driver interrupt handlers. */ | ||
102 | /*===========================================================================*/ | ||
103 | |||
104 | /*===========================================================================*/ | ||
105 | /* Driver exported functions. */ | ||
106 | /*===========================================================================*/ | ||
107 | |||
108 | /** | ||
109 | * @brief Low level HAL driver initialization. | ||
110 | * | ||
111 | * @notapi | ||
112 | */ | ||
113 | void hal_lld_init(void) { | ||
114 | |||
115 | /* Reset of all peripherals. | ||
116 | Note, GPIOs are not reset because initialized before this point in | ||
117 | board files.*/ | ||
118 | rccResetAHB1(~0); | ||
119 | rccResetAHB2(~STM32_GPIO_EN_MASK); | ||
120 | rccResetAHB3(~0); | ||
121 | rccResetAPB1R1(~RCC_APB1RSTR1_PWRRST); | ||
122 | rccResetAPB1R2(~0); | ||
123 | rccResetAPB2(~0); | ||
124 | |||
125 | /* PWR clock enabled.*/ | ||
126 | rccEnablePWRInterface(true); | ||
127 | |||
128 | /* Initializes the backup domain.*/ | ||
129 | hal_lld_backup_domain_init(); | ||
130 | |||
131 | /* DMA subsystems initialization.*/ | ||
132 | #if defined(STM32_DMA_REQUIRED) | ||
133 | dmaInit(); | ||
134 | #endif | ||
135 | |||
136 | /* IRQ subsystem initialization.*/ | ||
137 | irqInit(); | ||
138 | |||
139 | /* Programmable voltage detector enable.*/ | ||
140 | #if STM32_PVD_ENABLE | ||
141 | PWR->CR2 = PWR_CR2_PVDE | (STM32_PLS & STM32_PLS_MASK); | ||
142 | #else | ||
143 | PWR->CR2 = 0; | ||
144 | #endif /* STM32_PVD_ENABLE */ | ||
145 | |||
146 | /* Enabling independent VDDUSB.*/ | ||
147 | #if HAL_USE_USB | ||
148 | PWR->CR2 |= PWR_CR2_USV; | ||
149 | #endif /* HAL_USE_USB */ | ||
150 | |||
151 | /* Enabling independent VDDIO2 required by GPIOG.*/ | ||
152 | #if STM32_HAS_GPIOG | ||
153 | PWR->CR2 |= PWR_CR2_IOSV; | ||
154 | #endif /* STM32_HAS_GPIOG */ | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * @brief STM32L4xx clocks and PLL initialization. | ||
159 | * @note All the involved constants come from the file @p board.h. | ||
160 | * @note This function should be invoked just after the system reset. | ||
161 | * | ||
162 | * @special | ||
163 | */ | ||
164 | void stm32_clock_init(void) { | ||
165 | |||
166 | #if !STM32_NO_INIT | ||
167 | /* PWR clock enable.*/ | ||
168 | #if defined(HAL_USE_RTC) && defined(RCC_APB1ENR1_RTCAPBEN) | ||
169 | RCC->APB1ENR1 = RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN; | ||
170 | #else | ||
171 | RCC->APB1ENR1 = RCC_APB1ENR1_PWREN; | ||
172 | #endif | ||
173 | |||
174 | /* Initial clocks setup and wait for MSI stabilization, the MSI clock is | ||
175 | always enabled because it is the fall back clock when PLL the fails. | ||
176 | Trim fields are not altered from reset values.*/ | ||
177 | |||
178 | /* MSIRANGE can be set only when MSI is OFF or READY.*/ | ||
179 | RCC->CR = RCC_CR_MSION; | ||
180 | while ((RCC->CR & RCC_CR_MSIRDY) == 0) | ||
181 | ; /* Wait until MSI is stable. */ | ||
182 | |||
183 | /* Clocking from MSI, in case MSI was not the default source.*/ | ||
184 | RCC->CFGR = 0; | ||
185 | while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) | ||
186 | ; /* Wait until MSI is selected. */ | ||
187 | |||
188 | /* Core voltage setup.*/ | ||
189 | PWR->CR1 = STM32_VOS; | ||
190 | while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ | ||
191 | ; /* stable. */ | ||
192 | |||
193 | #if STM32_HSI16_ENABLED | ||
194 | /* HSI activation.*/ | ||
195 | RCC->CR |= RCC_CR_HSION; | ||
196 | while ((RCC->CR & RCC_CR_HSIRDY) == 0) | ||
197 | ; /* Wait until HSI16 is stable. */ | ||
198 | #endif | ||
199 | |||
200 | #if STM32_CLOCK_HAS_HSI48 | ||
201 | #if STM32_HSI48_ENABLED | ||
202 | /* HSI activation.*/ | ||
203 | RCC->CRRCR |= RCC_CRRCR_HSI48ON; | ||
204 | while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0) | ||
205 | ; /* Wait until HSI48 is stable. */ | ||
206 | #endif | ||
207 | #endif | ||
208 | |||
209 | #if STM32_HSE_ENABLED | ||
210 | #if defined(STM32_HSE_BYPASS) | ||
211 | /* HSE Bypass.*/ | ||
212 | RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; | ||
213 | #endif | ||
214 | /* HSE activation.*/ | ||
215 | RCC->CR |= RCC_CR_HSEON; | ||
216 | while ((RCC->CR & RCC_CR_HSERDY) == 0) | ||
217 | ; /* Wait until HSE is stable. */ | ||
218 | #endif | ||
219 | |||
220 | #if STM32_LSI_ENABLED | ||
221 | /* LSI activation.*/ | ||
222 | RCC->CSR |= RCC_CSR_LSION; | ||
223 | while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) | ||
224 | ; /* Wait until LSI is stable. */ | ||
225 | #endif | ||
226 | |||
227 | /* Backup domain access enabled and left open.*/ | ||
228 | PWR->CR1 |= PWR_CR1_DBP; | ||
229 | |||
230 | #if STM32_LSE_ENABLED | ||
231 | /* LSE activation.*/ | ||
232 | #if defined(STM32_LSE_BYPASS) | ||
233 | /* LSE Bypass.*/ | ||
234 | RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; | ||
235 | #else | ||
236 | /* No LSE Bypass.*/ | ||
237 | RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; | ||
238 | #endif | ||
239 | while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) | ||
240 | ; /* Wait until LSE is stable. */ | ||
241 | #endif | ||
242 | |||
243 | /* Flash setup for selected MSI speed setting.*/ | ||
244 | FLASH->ACR = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | | ||
245 | STM32_MSI_FLASHBITS; | ||
246 | |||
247 | /* Changing MSIRANGE to configured value.*/ | ||
248 | RCC->CR |= STM32_MSIRANGE; | ||
249 | |||
250 | /* Switching from MSISRANGE to MSIRANGE.*/ | ||
251 | RCC->CR |= RCC_CR_MSIRGSEL; | ||
252 | while ((RCC->CR & RCC_CR_MSIRDY) == 0) | ||
253 | ; | ||
254 | |||
255 | /* MSI is configured SYSCLK source so wait for it to be stable as well.*/ | ||
256 | while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) | ||
257 | ; | ||
258 | |||
259 | #if STM32_MSIPLL_ENABLED | ||
260 | /* MSI PLL (to LSE) activation */ | ||
261 | RCC->CR |= RCC_CR_MSIPLLEN; | ||
262 | #endif | ||
263 | |||
264 | /* Updating MSISRANGE value. MSISRANGE can be set only when MSIRGSEL is high. | ||
265 | This range is used exiting the Standby mode until MSIRGSEL is set.*/ | ||
266 | RCC->CSR |= STM32_MSISRANGE; | ||
267 | |||
268 | #if STM32_ACTIVATE_PLL || STM32_ACTIVATE_PLLSAI1 || STM32_ACTIVATE_PLLSAI2 | ||
269 | /* PLLM and PLLSRC are common to all PLLs.*/ | ||
270 | #if defined(STM32L496xx) || defined(STM32L4A6xx) | ||
271 | RCC->PLLCFGR = STM32_PLLPDIV | STM32_PLLR | | ||
272 | STM32_PLLREN | STM32_PLLQ | | ||
273 | STM32_PLLQEN | STM32_PLLP | | ||
274 | STM32_PLLPEN | STM32_PLLN | | ||
275 | STM32_PLLM | STM32_PLLSRC; | ||
276 | #else | ||
277 | RCC->PLLCFGR = STM32_PLLR | STM32_PLLREN | | ||
278 | STM32_PLLQ | STM32_PLLQEN | | ||
279 | STM32_PLLP | STM32_PLLPEN | | ||
280 | STM32_PLLN | STM32_PLLM | | ||
281 | STM32_PLLSRC; | ||
282 | #endif | ||
283 | #endif | ||
284 | |||
285 | #if STM32_ACTIVATE_PLL | ||
286 | /* PLL activation.*/ | ||
287 | RCC->CR |= RCC_CR_PLLON; | ||
288 | |||
289 | /* Waiting for PLL lock.*/ | ||
290 | while ((RCC->CR & RCC_CR_PLLRDY) == 0) | ||
291 | ; | ||
292 | #endif | ||
293 | |||
294 | #if STM32_ACTIVATE_PLLSAI1 | ||
295 | /* PLLSAI1 activation.*/ | ||
296 | #if defined(STM32L496xx) || defined(STM32L4A6xx) | ||
297 | RCC->PLLSAI1CFGR = STM32_PLLSAI1PDIV | STM32_PLLSAI1R | | ||
298 | STM32_PLLSAI1REN | STM32_PLLSAI1Q | | ||
299 | STM32_PLLSAI1QEN | STM32_PLLSAI1P | | ||
300 | STM32_PLLSAI1PEN | STM32_PLLSAI1N; | ||
301 | #else | ||
302 | RCC->PLLSAI1CFGR = STM32_PLLSAI1R | STM32_PLLSAI1REN | | ||
303 | STM32_PLLSAI1Q | STM32_PLLSAI1QEN | | ||
304 | STM32_PLLSAI1P | STM32_PLLSAI1PEN | | ||
305 | STM32_PLLSAI1N; | ||
306 | #endif | ||
307 | RCC->CR |= RCC_CR_PLLSAI1ON; | ||
308 | |||
309 | /* Waiting for PLL lock.*/ | ||
310 | while ((RCC->CR & RCC_CR_PLLSAI1RDY) == 0) | ||
311 | ; | ||
312 | #endif | ||
313 | |||
314 | #if STM32_ACTIVATE_PLLSAI2 | ||
315 | /* PLLSAI2 activation.*/ | ||
316 | #if defined(STM32L496xx) || defined(STM32L4A6xx) | ||
317 | RCC->PLLSAI2CFGR = STM32_PLLSAI2PDIV | STM32_PLLSAI2R | | ||
318 | STM32_PLLSAI2REN | STM32_PLLSAI2P | | ||
319 | STM32_PLLSAI2PEN | STM32_PLLSAI2N; | ||
320 | #else | ||
321 | RCC->PLLSAI2CFGR = STM32_PLLSAI2R | STM32_PLLSAI2REN | | ||
322 | STM32_PLLSAI2P | STM32_PLLSAI2PEN | | ||
323 | STM32_PLLSAI2N; | ||
324 | #endif | ||
325 | RCC->CR |= RCC_CR_PLLSAI2ON; | ||
326 | |||
327 | /* Waiting for PLL lock.*/ | ||
328 | while ((RCC->CR & RCC_CR_PLLSAI2RDY) == 0) | ||
329 | ; | ||
330 | #endif | ||
331 | |||
332 | /* Other clock-related settings (dividers, MCO etc).*/ | ||
333 | RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_STOPWUCK | | ||
334 | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; | ||
335 | |||
336 | /* CCIPR register initialization, note, must take care of the _OFF | ||
337 | pseudo settings.*/ | ||
338 | { | ||
339 | uint32_t ccipr = STM32_DFSDMSEL | STM32_SWPMI1SEL | STM32_ADCSEL | | ||
340 | STM32_CLK48SEL | STM32_LPTIM2SEL | STM32_LPTIM1SEL | | ||
341 | STM32_I2C3SEL | STM32_I2C2SEL | STM32_I2C1SEL | | ||
342 | STM32_UART5SEL | STM32_UART4SEL | STM32_USART3SEL | | ||
343 | STM32_USART2SEL | STM32_USART1SEL | STM32_LPUART1SEL; | ||
344 | #if STM32_SAI2SEL != STM32_SAI2SEL_OFF | ||
345 | ccipr |= STM32_SAI2SEL; | ||
346 | #endif | ||
347 | #if STM32_SAI1SEL != STM32_SAI1SEL_OFF | ||
348 | ccipr |= STM32_SAI1SEL; | ||
349 | #endif | ||
350 | RCC->CCIPR = ccipr; | ||
351 | } | ||
352 | |||
353 | #if STM32_HAS_I2C4 | ||
354 | /* CCIPR2 register initialization.*/ | ||
355 | { | ||
356 | uint32_t ccipr2 = STM32_I2C4SEL; | ||
357 | RCC->CCIPR2 = ccipr2; | ||
358 | } | ||
359 | #endif | ||
360 | |||
361 | /* Set flash WS's for SYSCLK source */ | ||
362 | if (STM32_FLASHBITS > STM32_MSI_FLASHBITS) { | ||
363 | FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; | ||
364 | while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != | ||
365 | (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /* Switching to the configured SYSCLK source if it is different from MSI.*/ | ||
370 | #if (STM32_SW != STM32_SW_MSI) | ||
371 | RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ | ||
372 | /* Wait until SYSCLK is stable.*/ | ||
373 | while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) | ||
374 | ; | ||
375 | #endif | ||
376 | |||
377 | /* Reduce the flash WS's for SYSCLK source if they are less than MSI WSs */ | ||
378 | if (STM32_FLASHBITS < STM32_MSI_FLASHBITS) { | ||
379 | FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; | ||
380 | while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != | ||
381 | (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { | ||
382 | } | ||
383 | } | ||
384 | |||
385 | #endif /* STM32_NO_INIT */ | ||
386 | |||
387 | /* SYSCFG clock enabled here because it is a multi-functional unit shared | ||
388 | among multiple drivers.*/ | ||
389 | rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); | ||
390 | } | ||
391 | |||
392 | /** @} */ | ||