aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/os/hal/ports/WB32/WB32F3G71xx/hal_lld.c
diff options
context:
space:
mode:
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.c387
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 */
38uint32_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 */
61void 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 */
78void 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 */
121static 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 */
233void 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 */
264void 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 */
315void 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 */
338void 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 */
362void 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/** @} */