diff options
Diffstat (limited to 'lib/chibios-contrib/os/hal/ports/WB32/WB32F3G71xx/hal_lld.c')
-rw-r--r-- | lib/chibios-contrib/os/hal/ports/WB32/WB32F3G71xx/hal_lld.c | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/WB32F3G71xx/hal_lld.c b/lib/chibios-contrib/os/hal/ports/WB32/WB32F3G71xx/hal_lld.c new file mode 100644 index 000000000..e38df836f --- /dev/null +++ b/lib/chibios-contrib/os/hal/ports/WB32/WB32F3G71xx/hal_lld.c | |||
@@ -0,0 +1,387 @@ | |||
1 | /* | ||
2 | Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd | ||
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 WB32F3G71xx/hal_lld.c | ||
19 | * @brief WB32F3G71xx 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 System Clock Frequency (Core Clock) | ||
37 | */ | ||
38 | uint32_t SystemCoreClock = WB32_MAINCLK; | ||
39 | |||
40 | /*===========================================================================*/ | ||
41 | /* Driver local variables and types. */ | ||
42 | /*===========================================================================*/ | ||
43 | |||
44 | /*===========================================================================*/ | ||
45 | /* Driver local functions. */ | ||
46 | /*===========================================================================*/ | ||
47 | |||
48 | /*===========================================================================*/ | ||
49 | /* Driver interrupt handlers. */ | ||
50 | /*===========================================================================*/ | ||
51 | |||
52 | /*===========================================================================*/ | ||
53 | /* Driver exported functions. */ | ||
54 | /*===========================================================================*/ | ||
55 | |||
56 | /** | ||
57 | * @brief Low level HAL driver initialization. | ||
58 | * | ||
59 | * @notapi | ||
60 | */ | ||
61 | void hal_lld_init(void) { | ||
62 | |||
63 | void SystemCoreClockUpdate(void); | ||
64 | SystemCoreClockUpdate(); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * @brief Update SystemCoreClock variable according to Clock Register Values. | ||
69 | * The SystemCoreClock variable contains the core clock (HCLK), it can | ||
70 | * be used by the user application to setup the SysTick timer or configure | ||
71 | * other parameters. | ||
72 | * @note Each time the core clock (HCLK) changes, this function must be called | ||
73 | * to update SystemCoreClock variable value. Otherwise, any configuration | ||
74 | * based on this variable will be incorrect. | ||
75 | * @param None | ||
76 | * @return None | ||
77 | */ | ||
78 | void SystemCoreClockUpdate(void) { | ||
79 | |||
80 | uint32_t ahbprediv, pllprediv, pllmul, mainclk; | ||
81 | |||
82 | switch (RCC->MAINCLKSRC) { | ||
83 | case 0x00: /* MHSI used as main clock */ | ||
84 | mainclk = 8000000; | ||
85 | break; | ||
86 | case 0x01: /* FHSI used as main clock */ | ||
87 | mainclk = 48000000; | ||
88 | break; | ||
89 | case 0x03: /* HSE used as main clock */ | ||
90 | mainclk = WB32_HSECLK; | ||
91 | break; | ||
92 | case 0x02: /* PLL used as main clock */ | ||
93 | pllprediv = | ||
94 | (((RCC->PLLPRE & (RCC_PLLPRE_RATIO_Msk | RCC_PLLPRE_DIVEN)) + 1) >> 1) + 1; | ||
95 | pllmul = (0x03 - ((ANCTL->PLLCR >> 6) & 0x03)) * 4 + 12; | ||
96 | if (RCC->PLLSRC == RCC_PLLSRC_HSE) { | ||
97 | mainclk = WB32_HSECLK * pllmul / pllprediv; | ||
98 | } | ||
99 | else { | ||
100 | mainclk = 8000000 * pllmul / pllprediv; | ||
101 | } | ||
102 | break; | ||
103 | default: | ||
104 | mainclk = 8000000; | ||
105 | break; | ||
106 | } | ||
107 | |||
108 | ahbprediv = | ||
109 | (((RCC->AHBPRE & (RCC_AHBPRE_RATIO_Msk | RCC_AHBPRE_DIVEN)) + 1) >> 1) + 1; | ||
110 | SystemCoreClock = mainclk / ahbprediv; | ||
111 | } | ||
112 | |||
113 | #if defined(WB32F3G71xx) | ||
114 | |||
115 | /** | ||
116 | * @brief Configures the main clock frequency, AHBCLK, APB1CLK and APB2CLK prescalers. | ||
117 | * @note This function should be used only after reset. | ||
118 | * @param None | ||
119 | * @return None | ||
120 | */ | ||
121 | static void SetSysClock(void) { | ||
122 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; | ||
123 | |||
124 | /* Unlocks write to ANCTL registers */ | ||
125 | PWR->ANAKEY1 = 0x03; | ||
126 | PWR->ANAKEY2 = 0x0C; | ||
127 | |||
128 | /* APB1CLK = MAINCLK / WB32_PPRE1*/ | ||
129 | RCC->APB1PRE = RCC_APB1PRE_SRCEN; | ||
130 | #if WB32_PPRE1 == 1 | ||
131 | RCC->APB1PRE |= 0x00; | ||
132 | #else | ||
133 | RCC->APB1PRE |= (WB32_PPRE1 - 2); | ||
134 | RCC->APB1PRE |= 0x01; | ||
135 | #endif /* WB32_PPRE1 == 1 */ | ||
136 | |||
137 | #if WB32_HSE_ENABLED == TRUE | ||
138 | /* Configure PD0 and PD1 to analog mode */ | ||
139 | RCC->APB1ENR = RCC_APB1ENR_BMX1EN | RCC_APB1ENR_GPIODEN; | ||
140 | GPIOD->CFGMSK = 0xFFFC; | ||
141 | GPIOD->MODER = 0x0F; | ||
142 | |||
143 | /* Enable HSE */ | ||
144 | ANCTL->HSECR1 = ANCTL_HSECR1_PADOEN; | ||
145 | ANCTL->HSECR0 = ANCTL_HSECR0_HSEON; | ||
146 | |||
147 | /* Wait till HSE is ready and if Time out is reached exit */ | ||
148 | do { | ||
149 | HSEStatus = ANCTL->HSESR & ANCTL_HSESR_HSERDY; | ||
150 | StartUpCounter++; | ||
151 | } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); | ||
152 | |||
153 | if (HSEStatus == 0) { | ||
154 | /* If HSE fails to start-up, the application will have wrong clock | ||
155 | * configuration. User can add here some code to deal with this error */ | ||
156 | while (1) | ||
157 | ; | ||
158 | } | ||
159 | #endif /* WB32_HSE_ENABLED == TRUE */ | ||
160 | /* Configure Flash prefetch, Cache and wait state */ | ||
161 | #if WB32_MAINCLK <= 32000000 | ||
162 | CACHE->CR = CACHE_CR_LATENCY_0WS; | ||
163 | #elif WB32_MAINCLK <= 48000000 | ||
164 | CACHE->CR = CACHE_CR_CHEEN | CACHE_CR_PREFEN_ON | CACHE_CR_LATENCY_1WS; | ||
165 | #elif WB32_MAINCLK <= 72000000 | ||
166 | CACHE->CR = CACHE_CR_CHEEN | CACHE_CR_PREFEN_ON | CACHE_CR_LATENCY_2WS; | ||
167 | #else | ||
168 | CACHE->CR = CACHE_CR_CHEEN | CACHE_CR_PREFEN_ON | CACHE_CR_LATENCY_3WS; | ||
169 | #endif | ||
170 | |||
171 | /* AHBCLK = WB32_HPRE */ | ||
172 | #if WB32_HPRE == 1 | ||
173 | RCC->AHBPRE = 0x00; | ||
174 | #else | ||
175 | RCC->AHBPRE = (WB32_HPRE - 2); | ||
176 | RCC->AHBPRE |= 0x01; | ||
177 | #endif /* WB32_HPRE == 1 */ | ||
178 | |||
179 | /* APB2CLK = MAINCLK / WB32_PPRE2 */ | ||
180 | RCC->APB2PRE = RCC_APB2PRE_SRCEN; | ||
181 | #if WB32_PPRE2 == 1 | ||
182 | RCC->APB2PRE |= 0x00; | ||
183 | #else | ||
184 | RCC->APB2PRE |= (WB32_PPRE2 - 2); | ||
185 | RCC->APB2PRE |= 0x01; | ||
186 | #endif /* WB32_PPRE2 == 1 */ | ||
187 | |||
188 | #if WB32_PLL_ENABLED == TRUE | ||
189 | /* PLL configuration: | ||
190 | PLLCLK = WB32_HSECLK / WB32_PLLDIV_VALUE * WB32_PLLMUL_VALUE*/ | ||
191 | RCC->PLLSRC = WB32_PLLSRC; | ||
192 | RCC->PLLPRE = RCC_PLLPRE_SRCEN; | ||
193 | |||
194 | #if WB32_PLLDIV_VALUE == 1 | ||
195 | RCC->PLLPRE |= 0x00; | ||
196 | #else | ||
197 | RCC->PLLPRE |= (WB32_PLLDIV_VALUE - 2); | ||
198 | RCC->PLLPRE |= 0x01; | ||
199 | #endif /* WB32_PLLDIV_VALUE == 1 */ | ||
200 | |||
201 | #if WB32_PLLMUL_VALUE == 12 | ||
202 | ANCTL->PLLCR = (0x3U << 6); | ||
203 | #elif WB32_PLLMUL_VALUE == 16 | ||
204 | ANCTL->PLLCR = (0x2U << 6); | ||
205 | #elif WB32_PLLMUL_VALUE == 20 | ||
206 | ANCTL->PLLCR = (0x1U << 6); | ||
207 | #elif WB32_PLLMUL_VALUE == 24 | ||
208 | ANCTL->PLLCR = (0x0U << 6); | ||
209 | #endif | ||
210 | |||
211 | /* Enable PLL */ | ||
212 | ANCTL->PLLENR = ANCTL_PLLENR_PLLON; | ||
213 | /* Wait till PLL is ready */ | ||
214 | while (ANCTL->PLLSR != 0x03) { | ||
215 | } | ||
216 | #endif /* WB32_PLL_ENABLED == TRUE */ | ||
217 | |||
218 | /* Select WB32_MAINCLKSRC as system clock source */ | ||
219 | RCC->MAINCLKSRC = WB32_MAINCLKSRC; | ||
220 | RCC->MAINCLKUEN = RCC_MAINCLKUEN_ENA; | ||
221 | |||
222 | /* Locks write to ANCTL registers */ | ||
223 | PWR->ANAKEY1 = 0x00; | ||
224 | PWR->ANAKEY2 = 0x00; | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * @brief Clocks initialization. | ||
229 | * @note None | ||
230 | * @param None | ||
231 | * @return None | ||
232 | */ | ||
233 | void wb32_clock_init(void) { | ||
234 | |||
235 | #if WB32_NO_INIT == FALSE | ||
236 | /* Unlocks write to ANCTL registers */ | ||
237 | PWR->ANAKEY1 = 0x03; | ||
238 | PWR->ANAKEY2 = 0x0C; | ||
239 | |||
240 | /* Turn off POR */ | ||
241 | ANCTL->PORCR = 0x7BE; | ||
242 | |||
243 | /* Locks write to ANCTL registers */ | ||
244 | PWR->ANAKEY1 = 0x00; | ||
245 | PWR->ANAKEY2 = 0x00; | ||
246 | |||
247 | SetSysClock(); | ||
248 | |||
249 | rccEnableAPB1(RCC_APB1ENR_BMX1EN); | ||
250 | rccEnableAPB2(RCC_APB2ENR_BMX2EN); | ||
251 | |||
252 | SCB->VTOR = FLASH_BASE; /* Vector Table Relocation in Internal FLASH. */ | ||
253 | |||
254 | #endif /* WB32_NO_INIT == FALSE */ | ||
255 | } | ||
256 | |||
257 | #if HAL_USE_USB || defined(__DOXYGEN__) | ||
258 | |||
259 | /** | ||
260 | * @brief wb32 usb initialization. | ||
261 | * @param[in] usbp pointer to the @p USBDriver object | ||
262 | * @return None | ||
263 | */ | ||
264 | void wb32_usb_init(USBDriver *usbp) { | ||
265 | |||
266 | /* Clock activation.*/ | ||
267 | #if WB32_USB_USE_USB1 | ||
268 | if (&USBD1 == usbp) { | ||
269 | RCC->AHBENR1 |= RCC_AHBENR1_CRCSFMEN; | ||
270 | |||
271 | /* Enable USB peripheral clock */ | ||
272 | RCC->AHBENR1 |= RCC_AHBENR1_USBEN; | ||
273 | |||
274 | /* Configure USB FIFO clock source */ | ||
275 | RCC->USBFIFOCLKSRC = RCC_USBFIFOCLKSRC_USBCLK; | ||
276 | |||
277 | /* Enable USB FIFO clock */ | ||
278 | RCC->USBFIFOCLKENR = RCC_USBFIFOCLKENR_CLKEN; | ||
279 | |||
280 | /* Configure and enable USB PHY */ | ||
281 | SFM->USBPCON = 0x02; | ||
282 | |||
283 | /* Configure and enable USBCLK */ | ||
284 | #if (WB32_USBPRE == WB32_USBPRE_DIV1P5) | ||
285 | RCC->USBCLKENR = RCC_USBCLKENR_CLKEN; | ||
286 | RCC->USBPRE = RCC_USBPRE_SRCEN; | ||
287 | RCC->USBPRE |= RCC_USBPRE_RATIO_1_5; | ||
288 | RCC->USBPRE |= RCC_USBPRE_DIVEN; | ||
289 | #elif (WB32_USBPRE == WB32_USBPRE_DIV1) | ||
290 | RCC->USBCLKENR = RCC_USBCLKENR_CLKEN; | ||
291 | RCC->USBPRE = RCC_USBPRE_SRCEN; | ||
292 | RCC->USBPRE |= 0x00; | ||
293 | #elif (WB32_USBPRE == WB32_USBPRE_DIV2) | ||
294 | RCC->USBCLKENR = RCC_USBCLKENR_CLKEN; | ||
295 | RCC->USBPRE = RCC_USBPRE_SRCEN; | ||
296 | RCC->USBPRE |= RCC_USBPRE_RATIO_2; | ||
297 | RCC->USBPRE |= RCC_USBPRE_DIVEN; | ||
298 | #elif (WB32_USBPRE == WB32_USBPRE_DIV3) | ||
299 | RCC->USBCLKENR = RCC_USBCLKENR_CLKEN; | ||
300 | RCC->USBPRE = RCC_USBPRE_SRCEN; | ||
301 | RCC->USBPRE |= RCC_USBPRE_RATIO_3; | ||
302 | RCC->USBPRE |= RCC_USBPRE_DIVEN; | ||
303 | #else | ||
304 | #error "invalid WB32_USBPRE value specified" | ||
305 | #endif | ||
306 | } | ||
307 | #endif | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * @brief wb32 usb deinitialization. | ||
312 | * @param[in] usbp pointer to the @p USBDriver object | ||
313 | * @return None | ||
314 | */ | ||
315 | void wb32_usb_deinit(USBDriver *usbp) { | ||
316 | |||
317 | #if WB32_USB_USE_USB1 | ||
318 | if (&USBD1 == usbp) { | ||
319 | /* Disable USBCLK */ | ||
320 | RCC->USBPRE &= RCC_USBPRE_SRCEN; | ||
321 | RCC->USBPRE = 0x00; | ||
322 | RCC->USBCLKENR = 0x00; | ||
323 | |||
324 | /* Disable USB FIFO clock */ | ||
325 | RCC->USBFIFOCLKENR = 0x0000; | ||
326 | |||
327 | /* Disable USB peripheral clock */ | ||
328 | RCC->AHBENR1 &= ~RCC_AHBENR1_USBEN; | ||
329 | } | ||
330 | #endif | ||
331 | } | ||
332 | |||
333 | /** | ||
334 | * @brief wb32 usb connect. | ||
335 | * @param[in] usbp pointer to the @p USBDriver object | ||
336 | * @return None | ||
337 | */ | ||
338 | void wb32_usb_connect(USBDriver *usbp) { | ||
339 | |||
340 | /* Enable BMX1, GPIOA clock */ | ||
341 | RCC->APB1ENR |= RCC_APB1ENR_BMX1EN | RCC_APB1ENR_GPIOAEN; | ||
342 | |||
343 | GPIOA->CFGMSK = (~(GPIO_CFGMSK_CFGMSK11 | GPIO_CFGMSK_CFGMSK12)); | ||
344 | /* Configure the drive current of PA11 and PA12 */ | ||
345 | GPIOA->CURRENT = (0x3 << 22) | (0x3 << 24); | ||
346 | /* Configure PA11 and PA12 as Alternate function mode */ | ||
347 | GPIOA->MODER = (0x2 << 22) | (0x2 << 24); | ||
348 | GPIOA->OTYPER = 0x00; | ||
349 | GPIOA->OSPEEDR = 0x00; | ||
350 | GPIOA->PUPDR = 0x00; | ||
351 | GPIOA->AFRH = (3 << 12) | (3 << 16); | ||
352 | |||
353 | USB->POWER = USB_POWER_SUSEN; | ||
354 | USB->INTRUSBE = USB_INTRUSBE_RSTIE | USB_INTRUSBE_RSUIE | USB_INTRUSBE_SUSIE; | ||
355 | } | ||
356 | |||
357 | /** | ||
358 | * @brief wb32 usb disconnect. | ||
359 | * @param[in] usbp pointer to the @p USBDriver object | ||
360 | * @return None | ||
361 | */ | ||
362 | void wb32_usb_disconnect(USBDriver *usbp) { | ||
363 | |||
364 | /* Enable BMX1, GPIOA clock */ | ||
365 | RCC->APB1ENR |= RCC_APB1ENR_BMX1EN | RCC_APB1ENR_GPIOAEN; | ||
366 | |||
367 | GPIOA->CFGMSK = (~(GPIO_CFGMSK_CFGMSK11 | GPIO_CFGMSK_CFGMSK12)); | ||
368 | /* Configure PA11 and PA12 as input mode */ | ||
369 | GPIOA->MODER = 0x00; | ||
370 | GPIOA->OSPEEDR = 0x00; | ||
371 | GPIOA->PUPDR = 0x00; | ||
372 | /* Configure PA12(D+) as open-drain output mode and output low level */ | ||
373 | GPIOA->CFGMSK = (~GPIO_CFGMSK_CFGMSK12); | ||
374 | GPIOA->MODER = (0x1 << 24); | ||
375 | GPIOA->OTYPER = (0x1 << 12); | ||
376 | GPIOA->AFRH = 0x00; | ||
377 | GPIOA->BSRR = (0x1000 << 16); | ||
378 | } | ||
379 | #endif | ||
380 | |||
381 | #else | ||
382 | |||
383 | #error "not defined wb32_clock_init" | ||
384 | |||
385 | #endif | ||
386 | |||
387 | /** @} */ | ||