aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/hal/ports/STM32/STM32L4xx/hal_lld.c
diff options
context:
space:
mode:
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.c392
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 */
39uint32_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 */
54static 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 */
113void 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 */
164void 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/** @} */