aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/hal/ports/STM32/STM32L0xx/hal_lld.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/hal/ports/STM32/STM32L0xx/hal_lld.c')
-rw-r--r--lib/chibios/os/hal/ports/STM32/STM32L0xx/hal_lld.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/lib/chibios/os/hal/ports/STM32/STM32L0xx/hal_lld.c b/lib/chibios/os/hal/ports/STM32/STM32L0xx/hal_lld.c
new file mode 100644
index 000000000..a1b72ad6b
--- /dev/null
+++ b/lib/chibios/os/hal/ports/STM32/STM32L0xx/hal_lld.c
@@ -0,0 +1,261 @@
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 STM32L0xx/hal_lld.c
19 * @brief STM32L0xx 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_stm32l0xx.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 */
52static void hal_lld_backup_domain_init(void) {
53
54 /* Backup domain access enabled and left open.*/
55 PWR->CR |= PWR_CR_DBP;
56
57 /* Reset BKP domain if different clock source selected.*/
58 if ((RCC->CSR & STM32_RTCSEL_MASK) != STM32_RTCSEL) {
59 /* Backup domain reset.*/
60 RCC->CSR |= RCC_CSR_RTCRST;
61 RCC->CSR &= ~RCC_CSR_RTCRST;
62 }
63
64 /* If enabled then the LSE is started.*/
65#if STM32_LSE_ENABLED
66 RCC->CSR |= RCC_CSR_LSEON;
67 while ((RCC->CSR & RCC_CSR_LSERDY) == 0)
68 ; /* Waits until LSE is stable. */
69#endif
70
71#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK
72 /* If the backup domain hasn't been initialized yet then proceed with
73 initialization.*/
74 if ((RCC->CSR & RCC_CSR_RTCEN) == 0) {
75 /* Selects clock source.*/
76 RCC->CSR |= STM32_RTCSEL;
77
78 /* RTC clock enabled.*/
79 RCC->CSR |= RCC_CSR_RTCEN;
80 }
81#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */
82}
83
84/*===========================================================================*/
85/* Driver interrupt handlers. */
86/*===========================================================================*/
87
88/*===========================================================================*/
89/* Driver exported functions. */
90/*===========================================================================*/
91
92/**
93 * @brief Low level HAL driver initialization.
94 *
95 * @notapi
96 */
97void hal_lld_init(void) {
98
99 /* Reset of all peripherals except those on IOP.*/
100 rccResetAHB(~RCC_AHBRSTR_MIFRST);
101 rccResetAPB1(~RCC_APB1RSTR_PWRRST);
102 rccResetAPB2(~0);
103
104 /* PWR clock enabled.*/
105 rccEnablePWRInterface(true);
106
107 /* Initializes the backup domain.*/
108 hal_lld_backup_domain_init();
109
110 /* DMA subsystems initialization.*/
111#if defined(STM32_DMA_REQUIRED)
112 dmaInit();
113#endif
114
115 /* IRQ subsystem initialization.*/
116 irqInit();
117
118 /* Programmable voltage detector enable.*/
119#if STM32_PVD_ENABLE
120 PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK);
121#endif /* STM32_PVD_ENABLE */
122}
123
124/**
125 * @brief STM32L0xx voltage, clocks and PLL initialization.
126 * @note All the involved constants come from the file @p board.h.
127 * @note This function should be invoked just after the system reset.
128 *
129 * @special
130 */
131/**
132 * @brief Clocks and internal voltage initialization.
133 */
134void stm32_clock_init(void) {
135
136#if !STM32_NO_INIT
137 /* PWR clock enable.*/
138 RCC->APB1ENR = RCC_APB1ENR_PWREN;
139
140 /* Core voltage setup.*/
141 while ((PWR->CSR & PWR_CSR_VOSF) != 0)
142 ; /* Waits until regulator is stable. */
143 PWR->CR = STM32_VOS;
144 while ((PWR->CSR & PWR_CSR_VOSF) != 0)
145 ; /* Waits until regulator is stable. */
146
147 /* Initial clocks setup and wait for MSI stabilization, the MSI clock is
148 always enabled because it is the fallback clock when PLL the fails.
149 Trim fields are not altered from reset values.*/
150 RCC->CFGR = 0;
151 RCC->ICSCR = (RCC->ICSCR & ~STM32_MSIRANGE_MASK) | STM32_MSIRANGE;
152 RCC->CR = RCC_CR_MSION;
153 while ((RCC->CR & RCC_CR_MSIRDY) == 0)
154 ; /* Waits until MSI is stable. */
155
156#if STM32_HSI16_ENABLED
157 /* HSI activation.*/
158 RCC->CR |= RCC_CR_HSION;
159 while ((RCC->CR & RCC_CR_HSIRDY) == 0)
160 ; /* Waits until HSI16 is stable. */
161
162#if STM32_HSI16_DIVIDER_ENABLED
163 RCC->CR |= RCC_CR_HSIDIVEN;
164 while ((RCC->CR & RCC_CR_HSIDIVF) == 0)
165 ;
166#endif
167#endif
168
169#if STM32_HSE_ENABLED
170#if defined(STM32_HSE_BYPASS)
171 /* HSE Bypass.*/
172 RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP;
173#endif
174 /* HSE activation.*/
175 RCC->CR |= RCC_CR_HSEON;
176 while ((RCC->CR & RCC_CR_HSERDY) == 0)
177 ; /* Waits until HSE is stable. */
178#endif
179
180#if STM32_LSI_ENABLED
181 /* LSI activation.*/
182 RCC->CSR |= RCC_CSR_LSION;
183 while ((RCC->CSR & RCC_CSR_LSIRDY) == 0)
184 ; /* Waits until LSI is stable. */
185#endif
186
187#if STM32_LSE_ENABLED
188 /* LSE activation, have to unlock the register.*/
189 if ((RCC->CSR & RCC_CSR_LSEON) == 0) {
190 PWR->CR |= PWR_CR_DBP;
191#if defined(STM32_LSE_BYPASS)
192 /* LSE Bypass.*/
193 RCC->CSR |= STM32_LSEDRV | RCC_CSR_LSEBYP;
194#else
195 /* No LSE Bypass.*/
196 RCC->CSR |= STM32_LSEDRV;
197#endif
198 RCC->CSR |= RCC_CSR_LSEON;
199 PWR->CR &= ~PWR_CR_DBP;
200 }
201 while ((RCC->CSR & RCC_CSR_LSERDY) == 0)
202 ; /* Waits until LSE is stable. */
203#endif
204
205#if STM32_ACTIVATE_PLL
206 /* PLL activation.*/
207 RCC->CFGR |= STM32_PLLDIV | STM32_PLLMUL | STM32_PLLSRC;
208 RCC->CR |= RCC_CR_PLLON;
209 while (!(RCC->CR & RCC_CR_PLLRDY))
210 ; /* Waits until PLL is stable. */
211#endif
212
213#if STM32_ACTIVATE_HSI48
214 /* Enabling SYSCFG clock. */
215 rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true);
216 /* Configuring SYSCFG to enable VREFINT and HSI48 VREFINT buffer. */
217 SYSCFG->CFGR3 = STM32_VREFINT_EN | SYSCFG_CFGR3_ENREF_HSI48;
218
219 while (!(SYSCFG->CFGR3 & SYSCFG_CFGR3_VREFINT_RDYF))
220 ; /* Waits until VREFINT is stable. */
221 /* Disabling SYSCFG clock. */
222 rccDisableAPB2(RCC_APB2ENR_SYSCFGEN);
223
224 /* Enabling HSI48. */
225 RCC->CRRCR |= RCC_CRRCR_HSI48ON;
226 while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY))
227 ; /* Waits until HSI48 is stable. */
228#endif
229
230 /* Other clock-related settings (dividers, MCO etc).*/
231 RCC->CR |= STM32_RTCPRE;
232 RCC->CFGR |= STM32_MCOPRE | STM32_MCOSEL |
233 STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE;
234 RCC->CSR |= STM32_RTCSEL;
235
236 /* Flash setup and final clock selection.*/
237#if defined(STM32_FLASHBITS)
238 FLASH->ACR = STM32_FLASHBITS;
239 while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) !=
240 (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) {
241 }
242#endif
243
244 /* Switching to the configured clock source if it is different from MSI. */
245#if (STM32_SW != STM32_SW_MSI)
246 RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */
247 while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
248 ;
249#endif
250
251 /* Peripherals clock sources setup.*/
252 RCC->CCIPR = STM32_HSI48SEL | STM32_LPTIM1SEL | STM32_I2C1SEL |
253 STM32_LPUART1SEL | STM32_USART2SEL | STM32_USART1SEL;
254
255 /* SYSCFG clock enabled here because it is a multi-functional unit shared
256 among multiple drivers.*/
257 rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true);
258#endif /* STM32_NO_INIT */
259}
260
261/** @} */