aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1')
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/driver.mk20
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.c439
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.h358
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.c622
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.h395
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.c674
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.h453
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.c270
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.h369
-rw-r--r--lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/wb32_tim.h534
10 files changed, 4134 insertions, 0 deletions
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/driver.mk b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/driver.mk
new file mode 100644
index 000000000..7ca8c939f
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/driver.mk
@@ -0,0 +1,20 @@
1PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.c
2
3ifeq ($(USE_SMART_BUILD),yes)
4ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),)
5PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.c
6endif
7ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),)
8PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.c
9endif
10ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),)
11PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.c
12endif
13else
14PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.c
15PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.c
16PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.c
17endif
18
19PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1
20
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.c b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.c
new file mode 100644
index 000000000..9fe49bd2e
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.c
@@ -0,0 +1,439 @@
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 TIMv1/hal_gpt_lld.c
19 * @brief WB32 GPT subsystem low level driver source.
20 *
21 * @addtogroup GPT
22 * @{
23 */
24
25#include "hal.h"
26
27#if HAL_USE_GPT || defined(__DOXYGEN__)
28
29/*===========================================================================*/
30/* Driver local definitions. */
31/*===========================================================================*/
32
33/*===========================================================================*/
34/* Driver exported variables. */
35/*===========================================================================*/
36
37/**
38 * @brief GPTD1 driver identifier.
39 * @note The driver GPTD1 allocates the complex timer TIM1 when enabled.
40 */
41#if WB32_GPT_USE_TIM1 || defined(__DOXYGEN__)
42GPTDriver GPTD1;
43#endif
44
45/**
46 * @brief GPTD2 driver identifier.
47 * @note The driver GPTD2 allocates the timer TIM2 when enabled.
48 */
49#if WB32_GPT_USE_TIM2 || defined(__DOXYGEN__)
50GPTDriver GPTD2;
51#endif
52
53/**
54 * @brief GPTD3 driver identifier.
55 * @note The driver GPTD3 allocates the timer TIM3 when enabled.
56 */
57#if WB32_GPT_USE_TIM3 || defined(__DOXYGEN__)
58GPTDriver GPTD3;
59#endif
60
61/**
62 * @brief GPTD4 driver identifier.
63 * @note The driver GPTD4 allocates the timer TIM4 when enabled.
64 */
65#if WB32_GPT_USE_TIM4 || defined(__DOXYGEN__)
66GPTDriver GPTD4;
67#endif
68
69/*===========================================================================*/
70/* Driver local variables and types. */
71/*===========================================================================*/
72
73/*===========================================================================*/
74/* Driver local functions. */
75/*===========================================================================*/
76
77/*===========================================================================*/
78/* Driver interrupt handlers. */
79/*===========================================================================*/
80
81#if WB32_GPT_USE_TIM1 || defined(__DOXYGEN__)
82#if !defined(WB32_TIM1_SUPPRESS_ISR)
83#if !defined(WB32_TIM1_UP_IRQ_VECTOR)
84#error "WB32_TIM1_UP_IRQ_VECTOR not defined"
85#endif
86/**
87 * @brief TIM1 interrupt handler.
88 *
89 * @isr
90 */
91OSAL_IRQ_HANDLER(WB32_TIM1_UP_IRQ_VECTOR) {
92
93 OSAL_IRQ_PROLOGUE();
94
95 gpt_lld_serve_interrupt(&GPTD1);
96
97 OSAL_IRQ_EPILOGUE();
98}
99#endif /* !defined(WB32_TIM1_SUPPRESS_ISR) */
100#endif /* WB32_GPT_USE_TIM1 */
101
102#if WB32_GPT_USE_TIM2 || defined(__DOXYGEN__)
103#if !defined(WB32_TIM2_SUPPRESS_ISR)
104#if !defined(WB32_TIM2_IRQ_VECTOR)
105#error "WB32_TIM2_IRQ_VECTOR not defined"
106#endif
107/**
108 * @brief TIM2 interrupt handler.
109 *
110 * @isr
111 */
112OSAL_IRQ_HANDLER(WB32_TIM2_IRQ_VECTOR) {
113
114 OSAL_IRQ_PROLOGUE();
115
116 gpt_lld_serve_interrupt(&GPTD2);
117
118 OSAL_IRQ_EPILOGUE();
119}
120#endif /* !defined(WB32_TIM2_SUPPRESS_ISR) */
121#endif /* WB32_GPT_USE_TIM2 */
122
123#if WB32_GPT_USE_TIM3 || defined(__DOXYGEN__)
124#if !defined(WB32_TIM3_SUPPRESS_ISR)
125#if !defined(WB32_TIM3_IRQ_VECTOR)
126#error "WB32_TIM3_IRQ_VECTOR not defined"
127#endif
128/**
129 * @brief TIM3 interrupt handler.
130 *
131 * @isr
132 */
133OSAL_IRQ_HANDLER(WB32_TIM3_IRQ_VECTOR) {
134
135 OSAL_IRQ_PROLOGUE();
136
137 gpt_lld_serve_interrupt(&GPTD3);
138
139 OSAL_IRQ_EPILOGUE();
140}
141#endif /* !defined(WB32_TIM3_SUPPRESS_ISR) */
142#endif /* WB32_GPT_USE_TIM3 */
143
144#if WB32_GPT_USE_TIM4 || defined(__DOXYGEN__)
145#if !defined(WB32_TIM4_SUPPRESS_ISR)
146#if !defined(WB32_TIM4_IRQ_VECTOR)
147#error "WB32_TIM4_IRQ_VECTOR not defined"
148#endif
149/**
150 * @brief TIM4 interrupt handler.
151 *
152 * @isr
153 */
154OSAL_IRQ_HANDLER(WB32_TIM4_IRQ_VECTOR) {
155
156 OSAL_IRQ_PROLOGUE();
157
158 gpt_lld_serve_interrupt(&GPTD4);
159
160 OSAL_IRQ_EPILOGUE();
161}
162#endif /* !defined(WB32_TIM4_SUPPRESS_ISR) */
163#endif /* WB32_GPT_USE_TIM4 */
164
165/*===========================================================================*/
166/* Driver exported functions. */
167/*===========================================================================*/
168
169/**
170 * @brief Low level GPT driver initialization.
171 *
172 * @notapi
173 */
174void gpt_lld_init(void) {
175
176#if WB32_GPT_USE_TIM1
177 /* Driver initialization.*/
178 GPTD1.tim = WB32_TIM1;
179 gptObjectInit(&GPTD1);
180#endif
181
182#if WB32_GPT_USE_TIM2
183 /* Driver initialization.*/
184 GPTD2.tim = WB32_TIM2;
185 gptObjectInit(&GPTD2);
186#endif
187
188#if WB32_GPT_USE_TIM3
189 /* Driver initialization.*/
190 GPTD3.tim = WB32_TIM3;
191 gptObjectInit(&GPTD3);
192#endif
193
194#if WB32_GPT_USE_TIM4
195 /* Driver initialization.*/
196 GPTD4.tim = WB32_TIM4;
197 gptObjectInit(&GPTD4);
198#endif
199}
200
201/**
202 * @brief Configures and activates the GPT peripheral.
203 *
204 * @param[in] gptp pointer to the @p GPTDriver object
205 *
206 * @notapi
207 */
208void gpt_lld_start(GPTDriver *gptp) {
209 uint16_t psc;
210
211 if (gptp->state == GPT_STOP) {
212 /* Clock activation.*/
213#if WB32_GPT_USE_TIM1
214 if (&GPTD1 == gptp) {
215 rccEnableTIM1();
216 rccResetTIM1();
217#if !defined(WB32_TIM1_SUPPRESS_ISR)
218 nvicEnableVector(WB32_TIM1_UP_NUMBER, WB32_GPT_TIM1_IRQ_PRIORITY);
219#endif
220#if defined(WB32_TIM1CLK)
221 gptp->clock = WB32_TIM1CLK;
222#else
223 gptp->clock = WB32_TIMCLK1;
224#endif
225 }
226#endif
227
228#if WB32_GPT_USE_TIM2
229 if (&GPTD2 == gptp) {
230 rccEnableTIM2();
231 rccResetTIM2();
232#if !defined(WB32_TIM2_SUPPRESS_ISR)
233 nvicEnableVector(WB32_TIM2_NUMBER, WB32_GPT_TIM2_IRQ_PRIORITY);
234#endif
235#if defined(WB32_TIM2CLK)
236 gptp->clock = WB32_TIM2CLK;
237#else
238 gptp->clock = WB32_TIMCLK1;
239#endif
240 }
241#endif
242
243#if WB32_GPT_USE_TIM3
244 if (&GPTD3 == gptp) {
245 rccEnableTIM3();
246 rccResetTIM3();
247#if !defined(WB32_TIM3_SUPPRESS_ISR)
248 nvicEnableVector(WB32_TIM3_NUMBER, WB32_GPT_TIM3_IRQ_PRIORITY);
249#endif
250#if defined(WB32_TIM3CLK)
251 gptp->clock = WB32_TIM3CLK;
252#else
253 gptp->clock = WB32_TIMCLK1;
254#endif
255 }
256#endif
257
258#if WB32_GPT_USE_TIM4
259 if (&GPTD4 == gptp) {
260 rccEnableTIM4();
261 rccResetTIM4();
262#if !defined(WB32_TIM4_SUPPRESS_ISR)
263 nvicEnableVector(WB32_TIM4_NUMBER, WB32_GPT_TIM4_IRQ_PRIORITY);
264#endif
265#if defined(WB32_TIM4CLK)
266 gptp->clock = WB32_TIM4CLK;
267#else
268 gptp->clock = WB32_TIMCLK1;
269#endif
270 }
271#endif
272 }
273
274 /* Prescaler value calculation.*/
275 psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1);
276 osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock,
277 "invalid frequency");
278
279 /* Timer configuration.*/
280 /* Initially stopped.*/
281 gptp->tim->CR1 = 0;
282 gptp->tim->CR2 = gptp->config->cr2;
283 /* Prescaler value.*/
284 gptp->tim->PSC = psc;
285 /* Clear pending IRQs.*/
286 gptp->tim->SR = 0;
287 /* DMA-related DIER bits.*/
288 gptp->tim->DIER = gptp->config->dier & ~WB32_TIM_DIER_IRQ_MASK;
289}
290
291/**
292 * @brief Deactivates the GPT peripheral.
293 *
294 * @param[in] gptp pointer to the @p GPTDriver object
295 *
296 * @notapi
297 */
298void gpt_lld_stop(GPTDriver *gptp) {
299
300 if (gptp->state == GPT_READY) {
301 /* Timer disabled.*/
302 gptp->tim->CR1 = 0;
303 /* All IRQs disabled.*/
304 gptp->tim->DIER = 0;
305 /* Clear pending IRQs.*/
306 gptp->tim->SR = 0;
307
308#if WB32_GPT_USE_TIM1
309 if (&GPTD1 == gptp) {
310#if !defined(WB32_TIM1_SUPPRESS_ISR)
311 nvicDisableVector(WB32_TIM1_UP_NUMBER);
312#endif
313 rccDisableTIM1();
314 }
315#endif
316
317#if WB32_GPT_USE_TIM2
318 if (&GPTD2 == gptp) {
319#if !defined(WB32_TIM2_SUPPRESS_ISR)
320 nvicDisableVector(WB32_TIM2_NUMBER);
321#endif
322 rccDisableTIM2();
323 }
324#endif
325
326#if WB32_GPT_USE_TIM3
327 if (&GPTD3 == gptp) {
328#if !defined(WB32_TIM3_SUPPRESS_ISR)
329 nvicDisableVector(WB32_TIM3_NUMBER);
330#endif
331 rccDisableTIM3();
332 }
333#endif
334
335#if WB32_GPT_USE_TIM4
336 if (&GPTD4 == gptp) {
337#if !defined(WB32_TIM4_SUPPRESS_ISR)
338 nvicDisableVector(WB32_TIM4_NUMBER);
339#endif
340 rccDisableTIM4();
341 }
342#endif
343 }
344}
345
346/**
347 * @brief Starts the timer in continuous mode.
348 *
349 * @param[in] gptp pointer to the @p GPTDriver object
350 * @param[in] interval period in ticks
351 *
352 * @notapi
353 */
354void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
355
356 /* Time constant.*/
357 gptp->tim->ARR = (uint32_t)(interval - 1U);
358 /* Update event.*/
359 gptp->tim->EGR = WB32_TIM_EGR_UG;
360 /* Reset counter.*/
361 gptp->tim->CNT = 0;
362
363 /* After generating the UG event it takes several clock cycles before SR bit
364 0 goes to 1. This is why the clearing of CNT has been inserted before the
365 clearing of SR, to give it some time.*/
366 /* Clear pending IRQs.*/
367 gptp->tim->SR = 0;
368 if (NULL != gptp->config->callback) {
369 /* Update Event IRQ enabled.*/
370 gptp->tim->DIER |= WB32_TIM_DIER_UIE;
371 }
372 gptp->tim->CR1 = WB32_TIM_CR1_ARPE | WB32_TIM_CR1_URS | WB32_TIM_CR1_CEN;
373}
374
375/**
376 * @brief Stops the timer.
377 *
378 * @param[in] gptp pointer to the @p GPTDriver object
379 *
380 * @notapi
381 */
382void gpt_lld_stop_timer(GPTDriver *gptp) {
383
384 /* Initially stopped.*/
385 gptp->tim->CR1 = 0;
386 /* Clear pending IRQs.*/
387 gptp->tim->SR = 0;
388
389 /* All interrupts disabled.*/
390 gptp->tim->DIER &= ~WB32_TIM_DIER_IRQ_MASK;
391}
392
393/**
394 * @brief Starts the timer in one shot mode and waits for completion.
395 * @details This function specifically polls the timer waiting for completion
396 * in order to not have extra delays caused by interrupt servicing,
397 * this function is only recommended for short delays.
398 *
399 * @param[in] gptp pointer to the @p GPTDriver object
400 * @param[in] interval time interval in ticks
401 *
402 * @notapi
403 */
404void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
405
406 /* Time constant.*/
407 gptp->tim->ARR = (uint32_t)(interval - 1U);
408 /* Update event.*/
409 gptp->tim->EGR = WB32_TIM_EGR_UG;
410 /* Clear pending IRQs.*/
411 gptp->tim->SR = 0;
412 gptp->tim->CR1 = WB32_TIM_CR1_OPM | WB32_TIM_CR1_URS | WB32_TIM_CR1_CEN;
413 while (!(gptp->tim->SR & WB32_TIM_SR_UIF))
414 ;
415 /* Clear pending IRQs.*/
416 gptp->tim->SR = 0;
417}
418
419/**
420 * @brief Shared IRQ handler.
421 *
422 * @param[in] gptp pointer to a @p GPTDriver object
423 *
424 * @notapi
425 */
426void gpt_lld_serve_interrupt(GPTDriver *gptp) {
427 uint32_t sr;
428
429 sr = gptp->tim->SR;
430 sr &= gptp->tim->DIER & WB32_TIM_DIER_IRQ_MASK;
431 gptp->tim->SR = ~sr;
432 if ((sr & WB32_TIM_SR_UIF) != 0) {
433 _gpt_isr_invoke_cb(gptp);
434 }
435}
436
437#endif /* HAL_USE_GPT */
438
439/** @} */
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.h b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.h
new file mode 100644
index 000000000..f1ed11879
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.h
@@ -0,0 +1,358 @@
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 TIMv1/hal_gpt_lld.h
19 * @brief WB32 GPT subsystem low level driver header.
20 *
21 * @addtogroup GPT
22 * @{
23 */
24
25#ifndef HAL_GPT_LLD_H
26#define HAL_GPT_LLD_H
27
28#include "wb32_tim.h"
29
30#if HAL_USE_GPT || defined(__DOXYGEN__)
31
32/*===========================================================================*/
33/* Driver constants. */
34/*===========================================================================*/
35
36/*===========================================================================*/
37/* Driver pre-compile time settings. */
38/*===========================================================================*/
39
40/**
41 * @name Configuration options
42 * @{
43 */
44/**
45 * @brief GPTD1 driver enable switch.
46 * @details If set to @p TRUE the support for GPTD1 is included.
47 * @note The default is @p FALSE.
48 */
49#if !defined(WB32_GPT_USE_TIM1) || defined(__DOXYGEN__)
50#define WB32_GPT_USE_TIM1 FALSE
51#endif
52
53/**
54 * @brief GPTD2 driver enable switch.
55 * @details If set to @p TRUE the support for GPTD2 is included.
56 * @note The default is @p FALSE.
57 */
58#if !defined(WB32_GPT_USE_TIM2) || defined(__DOXYGEN__)
59#define WB32_GPT_USE_TIM2 FALSE
60#endif
61
62/**
63 * @brief GPTD3 driver enable switch.
64 * @details If set to @p TRUE the support for GPTD3 is included.
65 * @note The default is @p FALSE.
66 */
67#if !defined(WB32_GPT_USE_TIM3) || defined(__DOXYGEN__)
68#define WB32_GPT_USE_TIM3 FALSE
69#endif
70
71/**
72 * @brief GPTD4 driver enable switch.
73 * @details If set to @p TRUE the support for GPTD4 is included.
74 * @note The default is @p FALSE.
75 */
76#if !defined(WB32_GPT_USE_TIM4) || defined(__DOXYGEN__)
77#define WB32_GPT_USE_TIM4 FALSE
78#endif
79
80/**
81 * @brief GPTD1 interrupt priority level setting.
82 */
83#if !defined(WB32_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
84#define WB32_GPT_TIM1_IRQ_PRIORITY 7
85#endif
86
87/**
88 * @brief GPTD2 interrupt priority level setting.
89 */
90#if !defined(WB32_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
91#define WB32_GPT_TIM2_IRQ_PRIORITY 7
92#endif
93
94/**
95 * @brief GPTD3 interrupt priority level setting.
96 */
97#if !defined(WB32_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
98#define WB32_GPT_TIM3_IRQ_PRIORITY 7
99#endif
100
101/**
102 * @brief GPTD4 interrupt priority level setting.
103 */
104#if !defined(WB32_GPT_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
105#define WB32_GPT_TIM4_IRQ_PRIORITY 7
106#endif
107
108/** @} */
109
110/*===========================================================================*/
111/* Derived constants and error checks. */
112/*===========================================================================*/
113
114#if !defined(WB32_HAS_TIM1)
115#define WB32_HAS_TIM1 FALSE
116#endif
117
118#if !defined(WB32_HAS_TIM2)
119#define WB32_HAS_TIM2 FALSE
120#endif
121
122#if !defined(WB32_HAS_TIM3)
123#define WB32_HAS_TIM3 FALSE
124#endif
125
126#if !defined(WB32_HAS_TIM4)
127#define WB32_HAS_TIM4 FALSE
128#endif
129
130#if WB32_GPT_USE_TIM1 && !WB32_HAS_TIM1
131#error "TIM1 not present in the selected device"
132#endif
133
134#if WB32_GPT_USE_TIM2 && !WB32_HAS_TIM2
135#error "TIM2 not present in the selected device"
136#endif
137
138#if WB32_GPT_USE_TIM3 && !WB32_HAS_TIM3
139#error "TIM3 not present in the selected device"
140#endif
141
142#if WB32_GPT_USE_TIM4 && !WB32_HAS_TIM4
143#error "TIM4 not present in the selected device"
144#endif
145
146#if !WB32_GPT_USE_TIM1 && !WB32_GPT_USE_TIM2 && \
147 !WB32_GPT_USE_TIM3 && !WB32_GPT_USE_TIM4
148#error "GPT driver activated but no TIM peripheral assigned"
149#endif
150
151/* Checks on allocation of TIMx units.*/
152#if WB32_GPT_USE_TIM1
153#if defined(WB32_TIM1_IS_USED)
154#error "GPTD1 requires TIM1 but the timer is already used"
155#else
156#define WB32_TIM1_IS_USED
157#endif
158#endif
159
160#if WB32_GPT_USE_TIM2
161#if defined(WB32_TIM2_IS_USED)
162#error "GPTD2 requires TIM2 but the timer is already used"
163#else
164#define WB32_TIM2_IS_USED
165#endif
166#endif
167
168#if WB32_GPT_USE_TIM3
169#if defined(WB32_TIM3_IS_USED)
170#error "GPTD3 requires TIM3 but the timer is already used"
171#else
172#define WB32_TIM3_IS_USED
173#endif
174#endif
175
176#if WB32_GPT_USE_TIM4
177#if defined(WB32_TIM4_IS_USED)
178#error "GPTD4 requires TIM4 but the timer is already used"
179#else
180#define WB32_TIM4_IS_USED
181#endif
182#endif
183
184/* IRQ priority checks.*/
185#if WB32_GPT_USE_TIM1 && !defined(WB32_TIM1_SUPPRESS_ISR) && \
186 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_GPT_TIM1_IRQ_PRIORITY)
187#error "Invalid IRQ priority assigned to TIM1"
188#endif
189
190#if WB32_GPT_USE_TIM2 && !defined(WB32_TIM2_SUPPRESS_ISR) && \
191 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_GPT_TIM2_IRQ_PRIORITY)
192#error "Invalid IRQ priority assigned to TIM2"
193#endif
194
195#if WB32_GPT_USE_TIM3 && !defined(WB32_TIM3_SUPPRESS_ISR) && \
196 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_GPT_TIM3_IRQ_PRIORITY)
197#error "Invalid IRQ priority assigned to TIM3"
198#endif
199
200#if WB32_GPT_USE_TIM4 && !defined(WB32_TIM_SUPPRESS_ISR) && \
201 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_GPT_TIM4_IRQ_PRIORITY)
202#error "Invalid IRQ priority assigned to TIM4"
203#endif
204
205/*===========================================================================*/
206/* Driver data structures and types. */
207/*===========================================================================*/
208
209/**
210 * @brief GPT frequency type.
211 */
212typedef uint32_t gptfreq_t;
213
214/**
215 * @brief GPT counter type.
216 */
217typedef uint32_t gptcnt_t;
218
219/**
220 * @brief Driver configuration structure.
221 * @note It could be empty on some architectures.
222 */
223typedef struct {
224 /**
225 * @brief Timer clock in Hz.
226 * @note The low level can use assertions in order to catch invalid
227 * frequency specifications.
228 */
229 gptfreq_t frequency;
230 /**
231 * @brief Timer callback pointer.
232 * @note This callback is invoked on GPT counter events.
233 * @note This callback can be set to @p NULL but in that case the
234 * one-shot mode cannot be used.
235 */
236 gptcallback_t callback;
237 /* End of the mandatory fields.*/
238 /**
239 * @brief TIM CR2 register initialization data.
240 * @note The value of this field should normally be equal to zero.
241 */
242 uint32_t cr2;
243 /**
244 * @brief TIM DIER register initialization data.
245 * @note The value of this field should normally be equal to zero.
246 * @note Only the DMA-related bits can be specified in this field.
247 */
248 uint32_t dier;
249} GPTConfig;
250
251/**
252 * @brief Structure representing a GPT driver.
253 */
254struct GPTDriver {
255 /**
256 * @brief Driver state.
257 */
258 gptstate_t state;
259 /**
260 * @brief Current configuration data.
261 */
262 const GPTConfig *config;
263#if defined(GPT_DRIVER_EXT_FIELDS)
264 GPT_DRIVER_EXT_FIELDS
265#endif
266 /* End of the mandatory fields.*/
267 /**
268 * @brief Timer base clock.
269 */
270 uint32_t clock;
271 /**
272 * @brief Pointer to the TIMx registers block.
273 */
274 wb32_tim_t *tim;
275};
276
277/*===========================================================================*/
278/* Driver macros. */
279/*===========================================================================*/
280
281/**
282 * @brief Changes the interval of GPT peripheral.
283 * @details This function changes the interval of a running GPT unit.
284 * @pre The GPT unit must be running in continuous mode.
285 * @post The GPT unit interval is changed to the new value.
286 * @note The function has effect at the next cycle start.
287 *
288 * @param[in] gptp pointer to a @p GPTDriver object
289 * @param[in] interval new cycle time in timer ticks
290 *
291 * @notapi
292 */
293#define gpt_lld_change_interval(gptp, interval) \
294 ((gptp)->tim->ARR = (uint32_t)((interval) - 1U))
295
296/**
297 * @brief Returns the interval of GPT peripheral.
298 * @pre The GPT unit must be running in continuous mode.
299 *
300 * @param[in] gptp pointer to a @p GPTDriver object
301 * @return The current interval.
302 *
303 * @notapi
304 */
305#define gpt_lld_get_interval(gptp) ((gptcnt_t)((gptp)->tim->ARR + 1U))
306
307/**
308 * @brief Returns the counter value of GPT peripheral.
309 * @pre The GPT unit must be running in continuous mode.
310 * @note The nature of the counter is not defined, it may count upward
311 * or downward, it could be continuously running or not.
312 *
313 * @param[in] gptp pointer to a @p GPTDriver object
314 * @return The current counter value.
315 *
316 * @notapi
317 */
318#define gpt_lld_get_counter(gptp) ((gptcnt_t)(gptp)->tim->CNT)
319
320/*===========================================================================*/
321/* External declarations. */
322/*===========================================================================*/
323
324#if WB32_GPT_USE_TIM1 && !defined(__DOXYGEN__)
325extern GPTDriver GPTD1;
326#endif
327
328#if WB32_GPT_USE_TIM2 && !defined(__DOXYGEN__)
329extern GPTDriver GPTD2;
330#endif
331
332#if WB32_GPT_USE_TIM3 && !defined(__DOXYGEN__)
333extern GPTDriver GPTD3;
334#endif
335
336#if WB32_GPT_USE_TIM4 && !defined(__DOXYGEN__)
337extern GPTDriver GPTD4;
338#endif
339
340#ifdef __cplusplus
341extern "C" {
342#endif
343 void gpt_lld_init(void);
344 void gpt_lld_start(GPTDriver *gptp);
345 void gpt_lld_stop(GPTDriver *gptp);
346 void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
347 void gpt_lld_stop_timer(GPTDriver *gptp);
348 void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
349 void gpt_lld_serve_interrupt(GPTDriver *gptp);
350#ifdef __cplusplus
351}
352#endif
353
354#endif /* HAL_USE_GPT */
355
356#endif /* HAL_GPT_LLD_H */
357
358/** @} */
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.c b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.c
new file mode 100644
index 000000000..8a78ffbf7
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.c
@@ -0,0 +1,622 @@
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 Concepts and parts of this file have been contributed by Fabio Utzig and
18 Xo Wang.
19 */
20
21/**
22 * @file TIMv1/hal_icu_lld.c
23 * @brief WB32 ICU subsystem low level driver header.
24 *
25 * @addtogroup ICU
26 * @{
27 */
28
29#include "hal.h"
30
31#if HAL_USE_ICU || defined(__DOXYGEN__)
32
33/*===========================================================================*/
34/* Driver local definitions. */
35/*===========================================================================*/
36
37/*===========================================================================*/
38/* Driver exported variables. */
39/*===========================================================================*/
40
41/**
42 * @brief ICUD1 driver identifier.
43 * @note The driver ICUD1 allocates the complex timer TIM1 when enabled.
44 */
45#if WB32_ICU_USE_TIM1 || defined(__DOXYGEN__)
46ICUDriver ICUD1;
47#endif
48
49/**
50 * @brief ICUD2 driver identifier.
51 * @note The driver ICUD1 allocates the timer TIM2 when enabled.
52 */
53#if WB32_ICU_USE_TIM2 || defined(__DOXYGEN__)
54ICUDriver ICUD2;
55#endif
56
57/**
58 * @brief ICUD3 driver identifier.
59 * @note The driver ICUD1 allocates the timer TIM3 when enabled.
60 */
61#if WB32_ICU_USE_TIM3 || defined(__DOXYGEN__)
62ICUDriver ICUD3;
63#endif
64
65/**
66 * @brief ICUD4 driver identifier.
67 * @note The driver ICUD4 allocates the timer TIM4 when enabled.
68 */
69#if WB32_ICU_USE_TIM4 || defined(__DOXYGEN__)
70ICUDriver ICUD4;
71#endif
72
73/*===========================================================================*/
74/* Driver local variables and types. */
75/*===========================================================================*/
76
77/*===========================================================================*/
78/* Driver local functions. */
79/*===========================================================================*/
80
81static bool icu_lld_wait_edge(ICUDriver *icup) {
82 uint32_t sr;
83 bool result;
84
85 /* Polled mode so re-enabling the interrupts while the operation is
86 performed.*/
87 osalSysUnlock();
88
89 /* Polling the right bit depending on the input channel.*/
90 if (icup->config->channel == ICU_CHANNEL_1) {
91 /* Waiting for an edge.*/
92 while (((sr = icup->tim->SR) & (WB32_TIM_SR_CC1IF | WB32_TIM_SR_UIF)) == 0)
93 ;
94 }
95 else {
96 /* Waiting for an edge.*/
97 while (((sr = icup->tim->SR) & (WB32_TIM_SR_CC2IF | WB32_TIM_SR_UIF)) == 0)
98 ;
99 }
100
101 /* Edge or overflow?*/
102 result = (sr & WB32_TIM_SR_UIF) != 0 ? true : false;
103
104 /* Done, disabling interrupts again.*/
105 osalSysLock();
106
107 /* Resetting all flags.*/
108 icup->tim->SR &= ~(WB32_TIM_SR_CC1IF | WB32_TIM_SR_CC2IF | WB32_TIM_SR_UIF);
109
110 return result;
111}
112
113/*===========================================================================*/
114/* Driver interrupt handlers. */
115/*===========================================================================*/
116
117#if WB32_ICU_USE_TIM1 || defined(__DOXYGEN__)
118#if !defined(WB32_TIM1_SUPPRESS_ISR)
119#if !defined(WB32_TIM1_UP_IRQ_VECTOR)
120#error "WB32_TIM1_UP_IRQ_VECTOR not defined"
121#endif
122/**
123 * @brief TIM1 compare interrupt handler.
124 *
125 * @isr
126 */
127OSAL_IRQ_HANDLER(WB32_TIM1_UP_IRQ_VECTOR) {
128
129 OSAL_IRQ_PROLOGUE();
130
131 icu_lld_serve_interrupt(&ICUD1);
132
133 OSAL_IRQ_EPILOGUE();
134}
135
136#if !defined(WB32_TIM1_CC_IRQ_VECTOR)
137#error "WB32_TIM1_CC_IRQ_VECTOR not defined"
138#endif
139/**
140 * @brief TIM1 compare interrupt handler.
141 *
142 * @isr
143 */
144OSAL_IRQ_HANDLER(WB32_TIM1_CC_IRQ_VECTOR) {
145
146 OSAL_IRQ_PROLOGUE();
147
148 icu_lld_serve_interrupt(&ICUD1);
149
150 OSAL_IRQ_EPILOGUE();
151}
152#endif /* !defined(WB32_TIM1_SUPPRESS_ISR) */
153#endif /* WB32_ICU_USE_TIM1 */
154
155#if WB32_ICU_USE_TIM2 || defined(__DOXYGEN__)
156#if !defined(WB32_TIM2_SUPPRESS_ISR)
157#if !defined(WB32_TIM2_IRQ_VECTOR)
158#error "WB32_TIM2_IRQ_VECTOR not defined"
159#endif
160/**
161 * @brief TIM2 interrupt handler.
162 *
163 * @isr
164 */
165OSAL_IRQ_HANDLER(WB32_TIM2_IRQ_VECTOR) {
166
167 OSAL_IRQ_PROLOGUE();
168
169 icu_lld_serve_interrupt(&ICUD2);
170
171 OSAL_IRQ_EPILOGUE();
172}
173#endif /* !defined(WB32_TIM2_SUPPRESS_ISR) */
174#endif /* WB32_ICU_USE_TIM2 */
175
176#if WB32_ICU_USE_TIM3 || defined(__DOXYGEN__)
177#if !defined(WB32_TIM3_SUPPRESS_ISR)
178#if !defined(WB32_TIM3_IRQ_VECTOR)
179#error "WB32_TIM3_IRQ_VECTOR not defined"
180#endif
181/**
182 * @brief TIM3 interrupt handler.
183 *
184 * @isr
185 */
186OSAL_IRQ_HANDLER(WB32_TIM3_IRQ_VECTOR) {
187
188 OSAL_IRQ_PROLOGUE();
189
190 icu_lld_serve_interrupt(&ICUD3);
191
192 OSAL_IRQ_EPILOGUE();
193}
194#endif /* !defined(WB32_TIM3_SUPPRESS_ISR) */
195#endif /* WB32_ICU_USE_TIM3 */
196
197#if WB32_ICU_USE_TIM4 || defined(__DOXYGEN__)
198#if !defined(WB32_TIM4_SUPPRESS_ISR)
199#if !defined(WB32_TIM4_IRQ_VECTOR)
200#error "WB32_TIM4_IRQ_VECTOR not defined"
201#endif
202/**
203 * @brief TIM4 interrupt handler.
204 *
205 * @isr
206 */
207OSAL_IRQ_HANDLER(WB32_TIM4_IRQ_VECTOR) {
208
209 OSAL_IRQ_PROLOGUE();
210
211 icu_lld_serve_interrupt(&ICUD4);
212
213 OSAL_IRQ_EPILOGUE();
214}
215#endif /* !defined(WB32_TIM4_SUPPRESS_ISR) */
216#endif /* WB32_ICU_USE_TIM4 */
217
218/*===========================================================================*/
219/* Driver exported functions. */
220/*===========================================================================*/
221
222/**
223 * @brief Low level ICU driver initialization.
224 *
225 * @notapi
226 */
227void icu_lld_init(void) {
228
229#if WB32_ICU_USE_TIM1
230 /* Driver initialization.*/
231 icuObjectInit(&ICUD1);
232 ICUD1.tim = WB32_TIM1;
233#endif
234
235#if WB32_ICU_USE_TIM2
236 /* Driver initialization.*/
237 icuObjectInit(&ICUD2);
238 ICUD2.tim = WB32_TIM2;
239#endif
240
241#if WB32_ICU_USE_TIM3
242 /* Driver initialization.*/
243 icuObjectInit(&ICUD3);
244 ICUD3.tim = WB32_TIM3;
245#endif
246
247#if WB32_ICU_USE_TIM4
248 /* Driver initialization.*/
249 icuObjectInit(&ICUD4);
250 ICUD4.tim = WB32_TIM4;
251#endif
252}
253
254/**
255 * @brief Configures and activates the ICU peripheral.
256 *
257 * @param[in] icup pointer to the @p ICUDriver object
258 *
259 * @notapi
260 */
261void icu_lld_start(ICUDriver *icup) {
262 uint32_t psc;
263
264 osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) ||
265 (icup->config->channel == ICU_CHANNEL_2),
266 "invalid input");
267
268 if (icup->state == ICU_STOP) {
269 /* Clock activation and timer reset.*/
270#if WB32_ICU_USE_TIM1
271 if (&ICUD1 == icup) {
272 rccEnableTIM1();
273 rccResetTIM1();
274#if !defined(WB32_TIM1_SUPPRESS_ISR)
275 nvicEnableVector(WB32_TIM1_UP_NUMBER, WB32_ICU_TIM1_IRQ_PRIORITY);
276 nvicEnableVector(WB32_TIM1_CC_NUMBER, WB32_ICU_TIM1_IRQ_PRIORITY);
277#endif
278#if defined(WB32_TIM1CLK)
279 icup->clock = WB32_TIM1CLK;
280#else
281 icup->clock = WB32_TIMCLK1;
282#endif
283 }
284#endif
285
286#if WB32_ICU_USE_TIM2
287 if (&ICUD2 == icup) {
288 rccEnableTIM2();
289 rccResetTIM2();
290#if !defined(WB32_TIM2_SUPPRESS_ISR)
291 nvicEnableVector(WB32_TIM2_NUMBER, WB32_ICU_TIM2_IRQ_PRIORITY);
292#endif
293#if defined(WB32_TIM2CLK)
294 icup->clock = WB32_TIM2CLK;
295#else
296 icup->clock = WB32_TIMCLK1;
297#endif
298 }
299#endif
300
301#if WB32_ICU_USE_TIM3
302 if (&ICUD3 == icup) {
303 rccEnableTIM3();
304 rccResetTIM3();
305#if !defined(WB32_TIM3_SUPPRESS_ISR)
306 nvicEnableVector(WB32_TIM3_NUMBER, WB32_ICU_TIM3_IRQ_PRIORITY);
307#endif
308#if defined(WB32_TIM3CLK)
309 icup->clock = WB32_TIM3CLK;
310#else
311 icup->clock = WB32_TIMCLK1;
312#endif
313 }
314#endif
315
316#if WB32_ICU_USE_TIM4
317 if (&ICUD4 == icup) {
318 rccEnableTIM4();
319 rccResetTIM4();
320#if !defined(WB32_TIM4_SUPPRESS_ISR)
321 nvicEnableVector(WB32_TIM4_NUMBER, WB32_ICU_TIM4_IRQ_PRIORITY);
322#endif
323#if defined(WB32_TIM4CLK)
324 icup->clock = WB32_TIM4CLK;
325#else
326 icup->clock = WB32_TIMCLK1;
327#endif
328 }
329#endif
330 }
331 else {
332 /* Driver re-configuration scenario, it must be stopped first.*/
333 /* Timer disabled.*/
334 icup->tim->CR1 = 0;
335 /* Comparator 1 disabled.*/
336 icup->tim->CCR[0] = 0;
337 /* Comparator 2 disabled.*/
338 icup->tim->CCR[1] = 0;
339 /* Counter reset to zero.*/
340 icup->tim->CNT = 0;
341 }
342
343 /* Timer configuration.*/
344 /* Clear eventual pending IRQs.*/
345 icup->tim->SR = 0;
346 /* DMA-related DIER settings.*/
347 icup->tim->DIER = icup->config->dier & ~WB32_TIM_DIER_IRQ_MASK;
348 psc = (icup->clock / icup->config->frequency) - 1;
349 osalDbgAssert((psc <= 0xFFFF) &&
350 ((psc + 1) * icup->config->frequency) == icup->clock,
351 "invalid frequency");
352 icup->tim->PSC = psc;
353 if (icup->config->arr == 0U) {
354 /* Zero is an invalid value and is turned in maximum value, also
355 for legacy configurations compatibility.*/
356 icup->tim->ARR = 0xFFFFFFFFU;
357 }
358 else {
359 icup->tim->ARR = icup->config->arr;
360 }
361
362 if (icup->config->channel == ICU_CHANNEL_1) {
363 /* Selected input 1.
364 CCMR1_CC1S = 01 = CH1 Input on TI1.
365 CCMR1_CC2S = 10 = CH2 Input on TI1.*/
366 icup->tim->CCMR1 = WB32_TIM_CCMR1_CC1S(1) | WB32_TIM_CCMR1_CC2S(2);
367
368 /* SMCR_TS = 101, input is TI1FP1.
369 SMCR_SMS = 100, reset on rising edge.*/
370 icup->tim->SMCR = WB32_TIM_SMCR_TS(5) | WB32_TIM_SMCR_SMS(4);
371
372 /* The CCER settings depend on the selected trigger mode.
373 ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
374 ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/
375 if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH)
376 icup->tim->CCER = WB32_TIM_CCER_CC1E | WB32_TIM_CCER_CC2E |
377 WB32_TIM_CCER_CC2P;
378 else
379 icup->tim->CCER = WB32_TIM_CCER_CC1E | WB32_TIM_CCER_CC1P |
380 WB32_TIM_CCER_CC2E;
381
382 /* Direct pointers to the capture registers in order to make
383 reading data faster from within callbacks.*/
384 icup->wccrp = &icup->tim->CCR[1];
385 icup->pccrp = &icup->tim->CCR[0];
386 }
387 else {
388 /* Selected input 2.
389 CCMR1_CC1S = 10 = CH1 Input on TI2.
390 CCMR1_CC2S = 01 = CH2 Input on TI2.*/
391 icup->tim->CCMR1 = WB32_TIM_CCMR1_CC1S(2) | WB32_TIM_CCMR1_CC2S(1);
392
393 /* SMCR_TS = 110, input is TI2FP2.
394 SMCR_SMS = 100, reset on rising edge.*/
395 icup->tim->SMCR = WB32_TIM_SMCR_TS(6) | WB32_TIM_SMCR_SMS(4);
396
397 /* The CCER settings depend on the selected trigger mode.
398 ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
399 ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/
400 if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH)
401 icup->tim->CCER = WB32_TIM_CCER_CC1E | WB32_TIM_CCER_CC1P |
402 WB32_TIM_CCER_CC2E;
403 else
404 icup->tim->CCER = WB32_TIM_CCER_CC1E | WB32_TIM_CCER_CC2E |
405 WB32_TIM_CCER_CC2P;
406
407 /* Direct pointers to the capture registers in order to make reading
408 data faster from within callbacks.*/
409 icup->wccrp = &icup->tim->CCR[0];
410 icup->pccrp = &icup->tim->CCR[1];
411 }
412}
413
414/**
415 * @brief Deactivates the ICU peripheral.
416 *
417 * @param[in] icup pointer to the @p ICUDriver object
418 *
419 * @notapi
420 */
421void icu_lld_stop(ICUDriver *icup) {
422
423 if (icup->state == ICU_READY) {
424 /* Clock deactivation.*/
425 /* Timer disabled. */
426 icup->tim->CR1 = 0;
427 /* All IRQs disabled. */
428 icup->tim->DIER = 0;
429 /* Clear eventual pending IRQs. */
430 icup->tim->SR = 0;
431
432#if WB32_ICU_USE_TIM1
433 if (&ICUD1 == icup) {
434#if !defined(WB32_TIM1_SUPPRESS_ISR)
435 nvicDisableVector(WB32_TIM1_UP_NUMBER);
436 nvicDisableVector(WB32_TIM1_CC_NUMBER);
437#endif
438 rccDisableTIM1();
439 }
440#endif
441
442#if WB32_ICU_USE_TIM2
443 if (&ICUD2 == icup) {
444#if !defined(WB32_TIM2_SUPPRESS_ISR)
445 nvicDisableVector(WB32_TIM2_NUMBER);
446#endif
447 rccDisableTIM2();
448 }
449#endif
450
451#if WB32_ICU_USE_TIM3
452 if (&ICUD3 == icup) {
453#if !defined(WB32_TIM3_SUPPRESS_ISR)
454 nvicDisableVector(WB32_TIM3_NUMBER);
455#endif
456 rccDisableTIM3();
457 }
458#endif
459
460#if WB32_ICU_USE_TIM4
461 if (&ICUD4 == icup) {
462#if !defined(WB32_TIM4_SUPPRESS_ISR)
463 nvicDisableVector(WB32_TIM4_NUMBER);
464#endif
465 rccDisableTIM4();
466 }
467#endif
468 }
469}
470
471/**
472 * @brief Starts the input capture.
473 *
474 * @param[in] icup pointer to the @p ICUDriver object
475 *
476 * @notapi
477 */
478void icu_lld_start_capture(ICUDriver *icup) {
479
480 /* Triggering an UG and clearing the IRQ status.*/
481 icup->tim->EGR |= WB32_TIM_EGR_UG;
482 icup->tim->SR = 0;
483
484 /* Timer is started.*/
485 icup->tim->CR1 = WB32_TIM_CR1_URS | WB32_TIM_CR1_CEN;
486}
487
488/**
489 * @brief Waits for a completed capture.
490 * @note The operation is performed in polled mode.
491 * @note In order to use this function notifications must be disabled.
492 *
493 * @param[in] icup pointer to the @p ICUDriver object
494 * @return The capture status.
495 * @retval false if the capture is successful.
496 * @retval true if a timer overflow occurred.
497 *
498 * @notapi
499 */
500bool icu_lld_wait_capture(ICUDriver *icup) {
501
502 /* If the driver is still in the ICU_WAITING state then we need to
503 wait for the first activation edge.*/
504 if (icup->state == ICU_WAITING)
505 if (icu_lld_wait_edge(icup))
506 return true;
507
508 /* This edge marks the availability of a capture result.*/
509 return icu_lld_wait_edge(icup);
510}
511
512/**
513 * @brief Stops the input capture.
514 *
515 * @param[in] icup pointer to the @p ICUDriver object
516 *
517 * @notapi
518 */
519void icu_lld_stop_capture(ICUDriver *icup) {
520
521 /* Timer stopped.*/
522 icup->tim->CR1 = 0;
523
524 /* All interrupts disabled.*/
525 icup->tim->DIER &= ~WB32_TIM_DIER_IRQ_MASK;
526}
527
528/**
529 * @brief Enables notifications.
530 * @pre The ICU unit must have been activated using @p icuStart() and the
531 * capture started using @p icuStartCapture().
532 * @note If the notification is already enabled then the call has no effect.
533 *
534 * @param[in] icup pointer to the @p ICUDriver object
535 *
536 * @notapi
537 */
538void icu_lld_enable_notifications(ICUDriver *icup) {
539 uint32_t dier = icup->tim->DIER;
540
541 /* If interrupts were already enabled then the operation is skipped.
542 This is done in order to avoid clearing the SR and risk losing pending
543 interrupts.*/
544 if ((dier & WB32_TIM_DIER_IRQ_MASK) == 0) {
545 /* Previously triggered IRQs are ignored, status cleared.*/
546 icup->tim->SR = 0;
547
548 if (icup->config->channel == ICU_CHANNEL_1) {
549 /* Enabling periodic callback on CC1.*/
550 dier |= WB32_TIM_DIER_CC1IE;
551
552 /* Optionally enabling width callback on CC2.*/
553 if (icup->config->width_cb != NULL)
554 dier |= WB32_TIM_DIER_CC2IE;
555 }
556 else {
557 /* Enabling periodic callback on CC2.*/
558 dier |= WB32_TIM_DIER_CC2IE;
559
560 /* Optionally enabling width callback on CC1.*/
561 if (icup->config->width_cb != NULL)
562 dier |= WB32_TIM_DIER_CC1IE;
563 }
564
565 /* If an overflow callback is defined then also the overflow
566 callback is enabled.*/
567 if (icup->config->overflow_cb != NULL)
568 dier |= WB32_TIM_DIER_UIE;
569
570 /* One single atomic write.*/
571 icup->tim->DIER = dier;
572 }
573}
574
575/**
576 * @brief Disables notifications.
577 * @pre The ICU unit must have been activated using @p icuStart() and the
578 * capture started using @p icuStartCapture().
579 * @note If the notification is already disabled then the call has no effect.
580 *
581 * @param[in] icup pointer to the @p ICUDriver object
582 *
583 * @notapi
584 */
585void icu_lld_disable_notifications(ICUDriver *icup) {
586
587 /* All interrupts disabled.*/
588 icup->tim->DIER &= ~WB32_TIM_DIER_IRQ_MASK;
589}
590
591/**
592 * @brief Shared IRQ handler.
593 *
594 * @param[in] icup pointer to the @p ICUDriver object
595 *
596 * @notapi
597 */
598void icu_lld_serve_interrupt(ICUDriver *icup) {
599 uint32_t sr;
600
601 sr = icup->tim->SR;
602 sr &= icup->tim->DIER & WB32_TIM_DIER_IRQ_MASK;
603 icup->tim->SR = ~sr;
604 if (icup->config->channel == ICU_CHANNEL_1) {
605 if ((sr & WB32_TIM_SR_CC2IF) != 0)
606 _icu_isr_invoke_width_cb(icup);
607 if ((sr & WB32_TIM_SR_CC1IF) != 0)
608 _icu_isr_invoke_period_cb(icup);
609 }
610 else {
611 if ((sr & WB32_TIM_SR_CC1IF) != 0)
612 _icu_isr_invoke_width_cb(icup);
613 if ((sr & WB32_TIM_SR_CC2IF) != 0)
614 _icu_isr_invoke_period_cb(icup);
615 }
616 if ((sr & WB32_TIM_SR_UIF) != 0)
617 _icu_isr_invoke_overflow_cb(icup);
618}
619
620#endif /* HAL_USE_ICU */
621
622/** @} */
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.h b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.h
new file mode 100644
index 000000000..acd12932d
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.h
@@ -0,0 +1,395 @@
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 TIMv1/hal_icu_lld.h
19 * @brief WB32 ICU subsystem low level driver header.
20 *
21 * @addtogroup ICU
22 * @{
23 */
24
25#ifndef HAL_ICU_LLD_H
26#define HAL_ICU_LLD_H
27
28#if HAL_USE_ICU || defined(__DOXYGEN__)
29
30#include "wb32_tim.h"
31
32/*===========================================================================*/
33/* Driver constants. */
34/*===========================================================================*/
35
36/*===========================================================================*/
37/* Driver pre-compile time settings. */
38/*===========================================================================*/
39
40/**
41 * @name Configuration options
42 * @{
43 */
44/**
45 * @brief ICUD1 driver enable switch.
46 * @details If set to @p TRUE the support for ICUD1 is included.
47 * @note The default is @p FALSE.
48 */
49#if !defined(WB32_ICU_USE_TIM1) || defined(__DOXYGEN__)
50#define WB32_ICU_USE_TIM1 FALSE
51#endif
52
53/**
54 * @brief ICUD2 driver enable switch.
55 * @details If set to @p TRUE the support for ICUD2 is included.
56 * @note The default is @p FALSE.
57 */
58#if !defined(WB32_ICU_USE_TIM2) || defined(__DOXYGEN__)
59#define WB32_ICU_USE_TIM2 FALSE
60#endif
61
62/**
63 * @brief ICUD3 driver enable switch.
64 * @details If set to @p TRUE the support for ICUD3 is included.
65 * @note The default is @p FALSE.
66 */
67#if !defined(WB32_ICU_USE_TIM3) || defined(__DOXYGEN__)
68#define WB32_ICU_USE_TIM3 FALSE
69#endif
70
71/**
72 * @brief ICUD4 driver enable switch.
73 * @details If set to @p TRUE the support for ICUD4 is included.
74 * @note The default is @p FALSE.
75 */
76#if !defined(WB32_ICU_USE_TIM4) || defined(__DOXYGEN__)
77#define WB32_ICU_USE_TIM4 FALSE
78#endif
79
80/**
81 * @brief ICUD1 interrupt priority level setting.
82 */
83#if !defined(WB32_ICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
84#define WB32_ICU_TIM1_IRQ_PRIORITY 7
85#endif
86
87/**
88 * @brief ICUD2 interrupt priority level setting.
89 */
90#if !defined(WB32_ICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
91#define WB32_ICU_TIM2_IRQ_PRIORITY 7
92#endif
93
94/**
95 * @brief ICUD3 interrupt priority level setting.
96 */
97#if !defined(WB32_ICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
98#define WB32_ICU_TIM3_IRQ_PRIORITY 7
99#endif
100
101/**
102 * @brief ICUD4 interrupt priority level setting.
103 */
104#if !defined(WB32_ICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
105#define WB32_ICU_TIM4_IRQ_PRIORITY 7
106#endif
107/** @} */
108
109/*===========================================================================*/
110/* Derived constants and error checks. */
111/*===========================================================================*/
112
113#if !defined(WB32_HAS_TIM1)
114#define WB32_HAS_TIM1 FALSE
115#endif
116
117#if !defined(WB32_HAS_TIM2)
118#define WB32_HAS_TIM2 FALSE
119#endif
120
121#if !defined(WB32_HAS_TIM3)
122#define WB32_HAS_TIM3 FALSE
123#endif
124
125#if !defined(WB32_HAS_TIM4)
126#define WB32_HAS_TIM4 FALSE
127#endif
128
129#if WB32_ICU_USE_TIM1 && !WB32_HAS_TIM1
130#error "TIM1 not present in the selected device"
131#endif
132
133#if WB32_ICU_USE_TIM2 && !WB32_HAS_TIM2
134#error "TIM2 not present in the selected device"
135#endif
136
137#if WB32_ICU_USE_TIM3 && !WB32_HAS_TIM3
138#error "TIM3 not present in the selected device"
139#endif
140
141#if WB32_ICU_USE_TIM4 && !WB32_HAS_TIM4
142#error "TIM4 not present in the selected device"
143#endif
144
145#if !WB32_ICU_USE_TIM1 && !WB32_ICU_USE_TIM2 && \
146 !WB32_ICU_USE_TIM3 && !WB32_ICU_USE_TIM4
147#error "ICU driver activated but no TIM peripheral assigned"
148#endif
149
150/* Checks on allocation of TIMx units.*/
151#if WB32_ICU_USE_TIM1
152#if defined(WB32_TIM1_IS_USED)
153#error "ICUD1 requires TIM1 but the timer is already used"
154#else
155#define WB32_TIM1_IS_USED
156#endif
157#endif
158
159#if WB32_ICU_USE_TIM2
160#if defined(WB32_TIM2_IS_USED)
161#error "ICUD2 requires TIM2 but the timer is already used"
162#else
163#define WB32_TIM2_IS_USED
164#endif
165#endif
166
167#if WB32_ICU_USE_TIM3
168#if defined(WB32_TIM3_IS_USED)
169#error "ICUD3 requires TIM3 but the timer is already used"
170#else
171#define WB32_TIM3_IS_USED
172#endif
173#endif
174
175#if WB32_ICU_USE_TIM4
176#if defined(WB32_TIM4_IS_USED)
177#error "ICUD4 requires TIM4 but the timer is already used"
178#else
179#define WB32_TIM4_IS_USED
180#endif
181#endif
182
183/* IRQ priority checks.*/
184#if WB32_ICU_USE_TIM1 && !defined(WB32_TIM1_SUPPRESS_ISR) && \
185 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_ICU_TIM1_IRQ_PRIORITY)
186#error "Invalid IRQ priority assigned to TIM1"
187#endif
188
189#if WB32_ICU_USE_TIM2 && !defined(WB32_TIM2_SUPPRESS_ISR) && \
190 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_ICU_TIM2_IRQ_PRIORITY)
191#error "Invalid IRQ priority assigned to TIM2"
192#endif
193
194#if WB32_ICU_USE_TIM3 && !defined(WB32_TIM3_SUPPRESS_ISR) && \
195 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_ICU_TIM3_IRQ_PRIORITY)
196#error "Invalid IRQ priority assigned to TIM3"
197#endif
198
199#if WB32_ICU_USE_TIM4 && !defined(WB32_TIM4_SUPPRESS_ISR) && \
200 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_ICU_TIM4_IRQ_PRIORITY)
201#error "Invalid IRQ priority assigned to TIM4"
202#endif
203
204/*===========================================================================*/
205/* Driver data structures and types. */
206/*===========================================================================*/
207
208/**
209 * @brief ICU driver mode.
210 */
211typedef enum {
212 ICU_INPUT_ACTIVE_HIGH = 0, /* Trigger on rising edge.*/
213 ICU_INPUT_ACTIVE_LOW = 1, /* Trigger on falling edge.*/
214} icumode_t;
215
216/**
217 * @brief ICU frequency type.
218 */
219typedef uint32_t icufreq_t;
220
221/**
222 * @brief ICU channel type.
223 */
224typedef enum {
225 ICU_CHANNEL_1 = 0, /* Use TIMxCH1.*/
226 ICU_CHANNEL_2 = 1, /* Use TIMxCH2.*/
227} icuchannel_t;
228
229/**
230 * @brief ICU counter type.
231 */
232typedef uint32_t icucnt_t;
233
234/**
235 * @brief Driver configuration structure.
236 * @note It could be empty on some architectures.
237 */
238typedef struct {
239 /**
240 * @brief Driver mode.
241 */
242 icumode_t mode;
243 /**
244 * @brief Timer clock in Hz.
245 * @note The low level can use assertions in order to catch invalid
246 * frequency specifications.
247 */
248 icufreq_t frequency;
249 /**
250 * @brief Callback for pulse width measurement.
251 */
252 icucallback_t width_cb;
253 /**
254 * @brief Callback for cycle period measurement.
255 */
256 icucallback_t period_cb;
257 /**
258 * @brief Callback for timer overflow.
259 */
260 icucallback_t overflow_cb;
261 /* End of the mandatory fields.*/
262 /**
263 * @brief Timer input channel to be used.
264 * @note Only inputs TIMx 1 and 2 are supported.
265 */
266 icuchannel_t channel;
267 /**
268 * @brief TIM DIER register initialization data.
269 * @note The value of this field should normally be equal to zero.
270 * @note Only the DMA-related bits can be specified in this field.
271 */
272 uint32_t dier;
273 /**
274 * @brief TIM ARR register initialization data.
275 * @note The value of this field should normally be equal to 0xFFFFFFFFU.
276 */
277 uint32_t arr;
278} ICUConfig;
279
280/**
281 * @brief Structure representing an ICU driver.
282 */
283struct ICUDriver {
284 /**
285 * @brief Driver state.
286 */
287 icustate_t state;
288 /**
289 * @brief Current configuration data.
290 */
291 const ICUConfig *config;
292#if defined(ICU_DRIVER_EXT_FIELDS)
293 ICU_DRIVER_EXT_FIELDS
294#endif
295 /* End of the mandatory fields.*/
296 /**
297 * @brief Timer base clock.
298 */
299 uint32_t clock;
300 /**
301 * @brief Pointer to the TIMx registers block.
302 */
303 wb32_tim_t *tim;
304 /**
305 * @brief CCR register used for width capture.
306 */
307 volatile uint32_t *wccrp;
308 /**
309 * @brief CCR register used for period capture.
310 */
311 volatile uint32_t *pccrp;
312};
313
314/*===========================================================================*/
315/* Driver macros. */
316/*===========================================================================*/
317
318/**
319 * @brief Returns the width of the latest pulse.
320 * @details The pulse width is defined as number of ticks between the start
321 * edge and the stop edge.
322 *
323 * @param[in] icup pointer to the @p ICUDriver object
324 * @return The number of ticks.
325 *
326 * @notapi
327 */
328#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1)
329
330/**
331 * @brief Returns the width of the latest cycle.
332 * @details The cycle width is defined as number of ticks between a start
333 * edge and the next start edge.
334 *
335 * @param[in] icup pointer to the @p ICUDriver object
336 * @return The number of ticks.
337 *
338 * @notapi
339 */
340#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1)
341
342/**
343 * @brief Check on notifications status.
344 *
345 * @param[in] icup pointer to the @p ICUDriver object
346 * @return The notifications status.
347 * @retval false if notifications are not enabled.
348 * @retval true if notifications are enabled.
349 *
350 * @notapi
351 */
352#define icu_lld_are_notifications_enabled(icup) \
353 (bool)(((icup)->tim->DIER & WB32_TIM_DIER_IRQ_MASK) != 0)
354
355/*===========================================================================*/
356/* External declarations. */
357/*===========================================================================*/
358
359#if WB32_ICU_USE_TIM1 && !defined(__DOXYGEN__)
360extern ICUDriver ICUD1;
361#endif
362
363#if WB32_ICU_USE_TIM2 && !defined(__DOXYGEN__)
364extern ICUDriver ICUD2;
365#endif
366
367#if WB32_ICU_USE_TIM3 && !defined(__DOXYGEN__)
368extern ICUDriver ICUD3;
369#endif
370
371#if WB32_ICU_USE_TIM4 && !defined(__DOXYGEN__)
372extern ICUDriver ICUD4;
373#endif
374
375#ifdef __cplusplus
376extern "C" {
377#endif
378 void icu_lld_init(void);
379 void icu_lld_start(ICUDriver *icup);
380 void icu_lld_stop(ICUDriver *icup);
381 void icu_lld_start_capture(ICUDriver *icup);
382 bool icu_lld_wait_capture(ICUDriver *icup);
383 void icu_lld_stop_capture(ICUDriver *icup);
384 void icu_lld_enable_notifications(ICUDriver *icup);
385 void icu_lld_disable_notifications(ICUDriver *icup);
386 void icu_lld_serve_interrupt(ICUDriver *icup);
387#ifdef __cplusplus
388}
389#endif
390
391#endif /* HAL_USE_ICU */
392
393#endif /* HAL_ICU_LLD_H */
394
395/** @} */
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.c b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.c
new file mode 100644
index 000000000..a60c08193
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.c
@@ -0,0 +1,674 @@
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 TIMv1/hal_pwm_lld.c
19 * @brief WB32 PWM subsystem low level driver header.
20 *
21 * @addtogroup PWM
22 * @{
23 */
24
25#include "hal.h"
26
27#if HAL_USE_PWM || defined(__DOXYGEN__)
28
29/*===========================================================================*/
30/* Driver local definitions. */
31/*===========================================================================*/
32
33/*===========================================================================*/
34/* Driver exported variables. */
35/*===========================================================================*/
36
37/**
38 * @brief PWMD1 driver identifier.
39 * @note The driver PWMD1 allocates the complex timer TIM1 when enabled.
40 */
41#if WB32_PWM_USE_TIM1 || defined(__DOXYGEN__)
42PWMDriver PWMD1;
43#endif
44
45/**
46 * @brief PWMD2 driver identifier.
47 * @note The driver PWMD2 allocates the timer TIM2 when enabled.
48 */
49#if WB32_PWM_USE_TIM2 || defined(__DOXYGEN__)
50PWMDriver PWMD2;
51#endif
52
53/**
54 * @brief PWMD3 driver identifier.
55 * @note The driver PWMD3 allocates the timer TIM3 when enabled.
56 */
57#if WB32_PWM_USE_TIM3 || defined(__DOXYGEN__)
58PWMDriver PWMD3;
59#endif
60
61/**
62 * @brief PWMD4 driver identifier.
63 * @note The driver PWMD4 allocates the timer TIM4 when enabled.
64 */
65#if WB32_PWM_USE_TIM4 || defined(__DOXYGEN__)
66PWMDriver PWMD4;
67#endif
68
69/*===========================================================================*/
70/* Driver local variables and types. */
71/*===========================================================================*/
72
73/*===========================================================================*/
74/* Driver local functions. */
75/*===========================================================================*/
76
77/*===========================================================================*/
78/* Driver interrupt handlers. */
79/*===========================================================================*/
80
81#if WB32_PWM_USE_TIM1 || defined(__DOXYGEN__)
82#if !defined(WB32_TIM1_SUPPRESS_ISR)
83#if !defined(WB32_TIM1_UP_IRQ_VECTOR)
84#error "WB32_TIM1_UP_IRQ_VECTOR not defined"
85#endif
86/**
87 * @brief TIM1 update interrupt handler.
88 * @note It is assumed that this interrupt is only activated if the callback
89 * pointer is not equal to @p NULL in order to not perform an extra
90 * check in a potentially critical interrupt handler.
91 *
92 * @isr
93 */
94OSAL_IRQ_HANDLER(WB32_TIM1_UP_IRQ_VECTOR) {
95
96 OSAL_IRQ_PROLOGUE();
97
98 pwm_lld_serve_interrupt(&PWMD1);
99
100 OSAL_IRQ_EPILOGUE();
101}
102
103#if !defined(WB32_TIM1_CC_IRQ_VECTOR)
104#error "WB32_TIM1_CC_IRQ_VECTOR not defined"
105#endif
106/**
107 * @brief TIM1 compare interrupt handler.
108 * @note It is assumed that the various sources are only activated if the
109 * associated callback pointer is not equal to @p NULL in order to not
110 * perform an extra check in a potentially critical interrupt handler.
111 *
112 * @isr
113 */
114OSAL_IRQ_HANDLER(WB32_TIM1_CC_IRQ_VECTOR) {
115
116 OSAL_IRQ_PROLOGUE();
117
118 pwm_lld_serve_interrupt(&PWMD1);
119
120 OSAL_IRQ_EPILOGUE();
121}
122#endif /* !defined(WB32_TIM1_SUPPRESS_ISR) */
123#endif /* WB32_PWM_USE_TIM1 */
124
125#if WB32_PWM_USE_TIM2 || defined(__DOXYGEN__)
126#if !defined(WB32_TIM2_SUPPRESS_ISR)
127#if !defined(WB32_TIM2_IRQ_VECTOR)
128#error "WB32_TIM2_IRQ_VECTOR not defined"
129#endif
130/**
131 * @brief TIM2 interrupt handler.
132 *
133 * @isr
134 */
135OSAL_IRQ_HANDLER(WB32_TIM2_IRQ_VECTOR) {
136
137 OSAL_IRQ_PROLOGUE();
138
139 pwm_lld_serve_interrupt(&PWMD2);
140
141 OSAL_IRQ_EPILOGUE();
142}
143#endif /* !defined(WB32_TIM2_SUPPRESS_ISR) */
144#endif /* WB32_PWM_USE_TIM2 */
145
146#if WB32_PWM_USE_TIM3 || defined(__DOXYGEN__)
147#if !defined(WB32_TIM3_SUPPRESS_ISR)
148#if !defined(WB32_TIM3_IRQ_VECTOR)
149#error "WB32_TIM3_IRQ_VECTOR not defined"
150#endif
151/**
152 * @brief TIM3 interrupt handler.
153 *
154 * @isr
155 */
156OSAL_IRQ_HANDLER(WB32_TIM3_IRQ_VECTOR) {
157
158 OSAL_IRQ_PROLOGUE();
159
160 pwm_lld_serve_interrupt(&PWMD3);
161
162 OSAL_IRQ_EPILOGUE();
163}
164#endif /* !defined(WB32_TIM3_SUPPRESS_ISR) */
165#endif /* WB32_PWM_USE_TIM3 */
166
167#if WB32_PWM_USE_TIM4 || defined(__DOXYGEN__)
168#if !defined(WB32_TIM4_SUPPRESS_ISR)
169#if !defined(WB32_TIM4_IRQ_VECTOR)
170#error "WB32_TIM4_IRQ_VECTOR not defined"
171#endif
172/**
173 * @brief TIM4 interrupt handler.
174 *
175 * @isr
176 */
177OSAL_IRQ_HANDLER(WB32_TIM4_IRQ_VECTOR) {
178
179 OSAL_IRQ_PROLOGUE();
180
181 pwm_lld_serve_interrupt(&PWMD4);
182
183 OSAL_IRQ_EPILOGUE();
184}
185#endif /* !defined(WB32_TIM4_SUPPRESS_ISR) */
186#endif /* WB32_PWM_USE_TIM4 */
187
188/*===========================================================================*/
189/* Driver exported functions. */
190/*===========================================================================*/
191
192/**
193 * @brief Low level PWM driver initialization.
194 *
195 * @notapi
196 */
197void pwm_lld_init(void) {
198
199#if WB32_PWM_USE_TIM1
200 /* Driver initialization.*/
201 pwmObjectInit(&PWMD1);
202 PWMD1.channels = WB32_TIM1_CHANNELS;
203 PWMD1.tim = WB32_TIM1;
204#endif
205
206#if WB32_PWM_USE_TIM2
207 /* Driver initialization.*/
208 pwmObjectInit(&PWMD2);
209 PWMD2.channels = WB32_TIM2_CHANNELS;
210 PWMD2.tim = WB32_TIM2;
211#endif
212
213#if WB32_PWM_USE_TIM3
214 /* Driver initialization.*/
215 pwmObjectInit(&PWMD3);
216 PWMD3.channels = WB32_TIM3_CHANNELS;
217 PWMD3.tim = WB32_TIM3;
218#endif
219
220#if WB32_PWM_USE_TIM4
221 /* Driver initialization.*/
222 pwmObjectInit(&PWMD4);
223 PWMD4.channels = WB32_TIM4_CHANNELS;
224 PWMD4.tim = WB32_TIM4;
225#endif
226}
227
228/**
229 * @brief Configures and activates the PWM peripheral.
230 * @note Starting a driver that is already in the @p PWM_READY state
231 * disables all the active channels.
232 *
233 * @param[in] pwmp pointer to a @p PWMDriver object
234 *
235 * @notapi
236 */
237void pwm_lld_start(PWMDriver *pwmp) {
238 uint32_t psc;
239 uint32_t ccer;
240
241 if (pwmp->state == PWM_STOP) {
242 /* Clock activation and timer reset.*/
243#if WB32_PWM_USE_TIM1
244 if (&PWMD1 == pwmp) {
245 rccEnableTIM1();
246 rccResetTIM1();
247#if !defined(WB32_TIM1_SUPPRESS_ISR)
248 nvicEnableVector(WB32_TIM1_UP_NUMBER, WB32_PWM_TIM1_IRQ_PRIORITY);
249 nvicEnableVector(WB32_TIM1_CC_NUMBER, WB32_PWM_TIM1_IRQ_PRIORITY);
250#endif
251#if defined(WB32_TIM1CLK)
252 pwmp->clock = WB32_TIM1CLK;
253#else
254 pwmp->clock = WB32_TIMCLK1;
255#endif
256 }
257#endif
258
259#if WB32_PWM_USE_TIM2
260 if (&PWMD2 == pwmp) {
261 rccEnableTIM2();
262 rccResetTIM2();
263#if !defined(WB32_TIM2_SUPPRESS_ISR)
264 nvicEnableVector(WB32_TIM2_NUMBER, WB32_PWM_TIM2_IRQ_PRIORITY);
265#endif
266#if defined(WB32_TIM2CLK)
267 pwmp->clock = WB32_TIM2CLK;
268#else
269 pwmp->clock = WB32_TIMCLK1;
270#endif
271 }
272#endif
273
274#if WB32_PWM_USE_TIM3
275 if (&PWMD3 == pwmp) {
276 rccEnableTIM3();
277 rccResetTIM3();
278#if !defined(WB32_TIM3_SUPPRESS_ISR)
279 nvicEnableVector(WB32_TIM3_NUMBER, WB32_PWM_TIM3_IRQ_PRIORITY);
280#endif
281#if defined(WB32_TIM3CLK)
282 pwmp->clock = WB32_TIM3CLK;
283#else
284 pwmp->clock = WB32_TIMCLK1;
285#endif
286 }
287#endif
288
289#if WB32_PWM_USE_TIM4
290 if (&PWMD4 == pwmp) {
291 rccEnableTIM4();
292 rccResetTIM4();
293#if !defined(WB32_TIM4_SUPPRESS_ISR)
294 nvicEnableVector(WB32_TIM4_NUMBER, WB32_PWM_TIM4_IRQ_PRIORITY);
295#endif
296#if defined(WB32_TIM4CLK)
297 pwmp->clock = WB32_TIM4CLK;
298#else
299 pwmp->clock = WB32_TIMCLK1;
300#endif
301 }
302#endif
303 /* All channels configured in PWM1 mode with preload enabled and
304 will stay that way until the driver is stopped.*/
305 pwmp->tim->CCMR1 = WB32_TIM_CCMR1_OC1M(6) | WB32_TIM_CCMR1_OC1PE |
306 WB32_TIM_CCMR1_OC2M(6) | WB32_TIM_CCMR1_OC2PE;
307 pwmp->tim->CCMR2 = WB32_TIM_CCMR2_OC3M(6) | WB32_TIM_CCMR2_OC3PE |
308 WB32_TIM_CCMR2_OC4M(6) | WB32_TIM_CCMR2_OC4PE;
309#if WB32_TIM_MAX_CHANNELS > 4
310 pwmp->tim->CCMR3 = WB32_TIM_CCMR3_OC5M(6) | WB32_TIM_CCMR3_OC5PE |
311 WB32_TIM_CCMR3_OC6M(6) | WB32_TIM_CCMR3_OC6PE;
312#endif
313 }
314 else {
315 /* Driver re-configuration scenario, it must be stopped first.*/
316 pwmp->tim->CR1 = 0; /* Timer disabled.*/
317 pwmp->tim->CCR[0] = 0; /* Comparator 1 disabled.*/
318 pwmp->tim->CCR[1] = 0; /* Comparator 2 disabled.*/
319 pwmp->tim->CCR[2] = 0; /* Comparator 3 disabled.*/
320 pwmp->tim->CCR[3] = 0; /* Comparator 4 disabled.*/
321#if WB32_TIM_MAX_CHANNELS > 4
322 if (pwmp->channels > 4) {
323 pwmp->tim->CCXR[0] = 0; /* Comparator 5 disabled.*/
324 pwmp->tim->CCXR[1] = 0; /* Comparator 6 disabled.*/
325 }
326#endif
327 pwmp->tim->CNT = 0; /* Counter reset to zero.*/
328 }
329
330 /* Timer configuration.*/
331 psc = (pwmp->clock / pwmp->config->frequency) - 1;
332 osalDbgAssert((psc <= 0xFFFF) &&
333 ((psc + 1) * pwmp->config->frequency) == pwmp->clock,
334 "invalid frequency");
335 pwmp->tim->PSC = psc;
336 pwmp->tim->ARR = pwmp->period - 1;
337 pwmp->tim->CR2 = pwmp->config->cr2;
338
339 /* Output enables and polarities setup.*/
340 ccer = 0;
341 switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) {
342 case PWM_OUTPUT_ACTIVE_LOW:
343 ccer |= WB32_TIM_CCER_CC1P;
344 /* Falls through.*/
345 case PWM_OUTPUT_ACTIVE_HIGH:
346 ccer |= WB32_TIM_CCER_CC1E;
347 /* Falls through.*/
348 default:
349 ;
350 }
351 switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) {
352 case PWM_OUTPUT_ACTIVE_LOW:
353 ccer |= WB32_TIM_CCER_CC2P;
354 /* Falls through.*/
355 case PWM_OUTPUT_ACTIVE_HIGH:
356 ccer |= WB32_TIM_CCER_CC2E;
357 /* Falls through.*/
358 default:
359 ;
360 }
361 switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) {
362 case PWM_OUTPUT_ACTIVE_LOW:
363 ccer |= WB32_TIM_CCER_CC3P;
364 /* Falls through.*/
365 case PWM_OUTPUT_ACTIVE_HIGH:
366 ccer |= WB32_TIM_CCER_CC3E;
367 /* Falls through.*/
368 default:
369 ;
370 }
371 switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) {
372 case PWM_OUTPUT_ACTIVE_LOW:
373 ccer |= WB32_TIM_CCER_CC4P;
374 /* Falls through.*/
375 case PWM_OUTPUT_ACTIVE_HIGH:
376 ccer |= WB32_TIM_CCER_CC4E;
377 /* Falls through.*/
378 default:
379 ;
380 }
381#if WB32_PWM_USE_ADVANCED
382#if WB32_PWM_USE_TIM1 && !WB32_PWM_USE_TIM8 && !WB32_PWM_USE_TIM20
383 if (&PWMD1 == pwmp) {
384#endif
385 switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
386 case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
387 ccer |= WB32_TIM_CCER_CC1NP;
388 /* Falls through.*/
389 case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
390 ccer |= WB32_TIM_CCER_CC1NE;
391 /* Falls through.*/
392 default:
393 ;
394 }
395 switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
396 case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
397 ccer |= WB32_TIM_CCER_CC2NP;
398 /* Falls through.*/
399 case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
400 ccer |= WB32_TIM_CCER_CC2NE;
401 /* Falls through.*/
402 default:
403 ;
404 }
405 switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
406 case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
407 ccer |= WB32_TIM_CCER_CC3NP;
408 /* Falls through.*/
409 case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
410 ccer |= WB32_TIM_CCER_CC3NE;
411 /* Falls through.*/
412 default:
413 ;
414 }
415 switch (pwmp->config->channels[3].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
416 case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
417 ccer |= WB32_TIM_CCER_CC4NP;
418 /* Falls through.*/
419 case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
420 ccer |= WB32_TIM_CCER_CC4NE;
421 /* Falls through.*/
422 default:
423 ;
424 }
425 }
426#endif /* WB32_PWM_USE_ADVANCED*/
427
428 pwmp->tim->CCER = ccer;
429 /* Update event. */
430 pwmp->tim->EGR = WB32_TIM_EGR_UG;
431 /* Clear pending IRQs. */
432 pwmp->tim->SR = 0;
433 /* DMA-related DIER settings. */
434 pwmp->tim->DIER = pwmp->config->dier & ~WB32_TIM_DIER_IRQ_MASK;
435#if WB32_PWM_USE_TIM1
436#if WB32_PWM_USE_ADVANCED
437 pwmp->tim->BDTR = pwmp->config->bdtr | WB32_TIM_BDTR_MOE;
438#else
439 pwmp->tim->BDTR = WB32_TIM_BDTR_MOE;
440#endif
441#endif
442 /* Timer configured and started.*/
443 pwmp->tim->CR1 = WB32_TIM_CR1_ARPE | WB32_TIM_CR1_URS | WB32_TIM_CR1_CEN;
444}
445
446/**
447 * @brief Deactivates the PWM peripheral.
448 *
449 * @param[in] pwmp pointer to a @p PWMDriver object
450 *
451 * @notapi
452 */
453void pwm_lld_stop(PWMDriver *pwmp) {
454
455 /* If in ready state then disables the PWM clock.*/
456 if (pwmp->state == PWM_READY) {
457 /* Timer disabled.*/
458 pwmp->tim->CR1 = 0;
459 /* All IRQs disabled.*/
460 pwmp->tim->DIER = 0;
461 /* Clear eventual pending IRQs.*/
462 pwmp->tim->SR = 0;
463#if WB32_PWM_USE_TIM1 || WB32_PWM_USE_TIM8 || WB32_PWM_USE_TIM20
464 pwmp->tim->BDTR = 0;
465#endif
466
467#if WB32_PWM_USE_TIM1
468 if (&PWMD1 == pwmp) {
469#if !defined(WB32_TIM1_SUPPRESS_ISR)
470 nvicDisableVector(WB32_TIM1_UP_NUMBER);
471 nvicDisableVector(WB32_TIM1_CC_NUMBER);
472#endif
473 rccDisableTIM1();
474 }
475#endif
476
477#if WB32_PWM_USE_TIM2
478 if (&PWMD2 == pwmp) {
479#if !defined(WB32_TIM2_SUPPRESS_ISR)
480 nvicDisableVector(WB32_TIM2_NUMBER);
481#endif
482 rccDisableTIM2();
483 }
484#endif
485
486#if WB32_PWM_USE_TIM3
487 if (&PWMD3 == pwmp) {
488#if !defined(WB32_TIM3_SUPPRESS_ISR)
489 nvicDisableVector(WB32_TIM3_NUMBER);
490#endif
491 rccDisableTIM3();
492 }
493#endif
494
495#if WB32_PWM_USE_TIM4
496 if (&PWMD4 == pwmp) {
497#if !defined(WB32_TIM4_SUPPRESS_ISR)
498 nvicDisableVector(WB32_TIM4_NUMBER);
499#endif
500 rccDisableTIM4();
501 }
502#endif
503 }
504}
505
506/**
507 * @brief Enables a PWM channel.
508 * @pre The PWM unit must have been activated using @p pwmStart().
509 * @post The channel is active using the specified configuration.
510 * @note The function has effect at the next cycle start.
511 * @note Channel notification is not enabled.
512 *
513 * @param[in] pwmp pointer to a @p PWMDriver object
514 * @param[in] channel PWM channel identifier (0...channels-1)
515 * @param[in] width PWM pulse width as clock pulses number
516 *
517 * @notapi
518 */
519void pwm_lld_enable_channel(PWMDriver *pwmp,
520 pwmchannel_t channel,
521 pwmcnt_t width) {
522
523 /* Changing channel duty cycle on the fly.*/
524#if WB32_TIM_MAX_CHANNELS <= 4
525 pwmp->tim->CCR[channel] = width;
526#else
527 if (channel < 4)
528 pwmp->tim->CCR[channel] = width;
529 else
530 pwmp->tim->CCXR[channel - 4] = width;
531#endif
532}
533
534/**
535 * @brief Disables a PWM channel and its notification.
536 * @pre The PWM unit must have been activated using @p pwmStart().
537 * @post The channel is disabled and its output line returned to the
538 * idle state.
539 * @note The function has effect at the next cycle start.
540 *
541 * @param[in] pwmp pointer to a @p PWMDriver object
542 * @param[in] channel PWM channel identifier (0...channels-1)
543 *
544 * @notapi
545 */
546void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
547
548#if WB32_TIM_MAX_CHANNELS <= 4
549 pwmp->tim->CCR[channel] = 0;
550 pwmp->tim->DIER &= ~(2 << channel);
551#else
552 if (channel < 4) {
553 pwmp->tim->CCR[channel] = 0;
554 pwmp->tim->DIER &= ~(2 << channel);
555 }
556 else
557 pwmp->tim->CCXR[channel - 4] = 0;
558#endif
559}
560
561/**
562 * @brief Enables the periodic activation edge notification.
563 * @pre The PWM unit must have been activated using @p pwmStart().
564 * @note If the notification is already enabled then the call has no effect.
565 *
566 * @param[in] pwmp pointer to a @p PWMDriver object
567 *
568 * @notapi
569 */
570void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) {
571 uint32_t dier = pwmp->tim->DIER;
572
573 /* If the IRQ is not already enabled care must be taken to clear it,
574 it is probably already pending because the timer is running.*/
575 if ((dier & WB32_TIM_DIER_UIE) == 0) {
576 pwmp->tim->SR = ~WB32_TIM_SR_UIF;
577 pwmp->tim->DIER = dier | WB32_TIM_DIER_UIE;
578 }
579}
580
581/**
582 * @brief Disables the periodic activation edge notification.
583 * @pre The PWM unit must have been activated using @p pwmStart().
584 * @note If the notification is already disabled then the call has no effect.
585 *
586 * @param[in] pwmp pointer to a @p PWMDriver object
587 *
588 * @notapi
589 */
590void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) {
591
592 pwmp->tim->DIER &= ~WB32_TIM_DIER_UIE;
593}
594
595/**
596 * @brief Enables a channel de-activation edge notification.
597 * @pre The PWM unit must have been activated using @p pwmStart().
598 * @pre The channel must have been activated using @p pwmEnableChannel().
599 * @note If the notification is already enabled then the call has no effect.
600 *
601 * @param[in] pwmp pointer to a @p PWMDriver object
602 * @param[in] channel PWM channel identifier (0...channels-1)
603 *
604 * @notapi
605 */
606void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
607 pwmchannel_t channel) {
608 uint32_t dier = pwmp->tim->DIER;
609
610#if WB32_TIM_MAX_CHANNELS > 4
611 /* Channels 4 and 5 do not support callbacks.*/
612 osalDbgAssert(channel < 4, "callback not supported");
613#endif
614
615 /* If the IRQ is not already enabled care must be taken to clear it,
616 it is probably already pending because the timer is running.*/
617 if ((dier & (2 << channel)) == 0) {
618 pwmp->tim->SR = ~(2 << channel);
619 pwmp->tim->DIER = dier | (2 << channel);
620 }
621}
622
623/**
624 * @brief Disables a channel de-activation edge notification.
625 * @pre The PWM unit must have been activated using @p pwmStart().
626 * @pre The channel must have been activated using @p pwmEnableChannel().
627 * @note If the notification is already disabled then the call has no effect.
628 *
629 * @param[in] pwmp pointer to a @p PWMDriver object
630 * @param[in] channel PWM channel identifier (0...channels-1)
631 *
632 * @notapi
633 */
634void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
635 pwmchannel_t channel) {
636
637 pwmp->tim->DIER &= ~(2 << channel);
638}
639
640/**
641 * @brief Common TIM2...TIM5,TIM9 IRQ handler.
642 * @note It is assumed that the various sources are only activated if the
643 * associated callback pointer is not equal to @p NULL in order to not
644 * perform an extra check in a potentially critical interrupt handler.
645 *
646 * @param[in] pwmp pointer to a @p PWMDriver object
647 *
648 * @notapi
649 */
650void pwm_lld_serve_interrupt(PWMDriver *pwmp) {
651 uint32_t sr;
652
653 sr = pwmp->tim->SR;
654 sr &= pwmp->tim->DIER & WB32_TIM_DIER_IRQ_MASK;
655 pwmp->tim->SR = ~sr;
656 if (((sr & WB32_TIM_SR_CC1IF) != 0) &&
657 (pwmp->config->channels[0].callback != NULL))
658 pwmp->config->channels[0].callback(pwmp);
659 if (((sr & WB32_TIM_SR_CC2IF) != 0) &&
660 (pwmp->config->channels[1].callback != NULL))
661 pwmp->config->channels[1].callback(pwmp);
662 if (((sr & WB32_TIM_SR_CC3IF) != 0) &&
663 (pwmp->config->channels[2].callback != NULL))
664 pwmp->config->channels[2].callback(pwmp);
665 if (((sr & WB32_TIM_SR_CC4IF) != 0) &&
666 (pwmp->config->channels[3].callback != NULL))
667 pwmp->config->channels[3].callback(pwmp);
668 if (((sr & WB32_TIM_SR_UIF) != 0) && (pwmp->config->callback != NULL))
669 pwmp->config->callback(pwmp);
670}
671
672#endif /* HAL_USE_PWM */
673
674/** @} */
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.h b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.h
new file mode 100644
index 000000000..563731d1b
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.h
@@ -0,0 +1,453 @@
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 TIMv1/hal_pwm_lld.h
19 * @brief WB32 PWM subsystem low level driver header.
20 *
21 * @addtogroup PWM
22 * @{
23 */
24
25#ifndef HAL_PWM_LLD_H
26#define HAL_PWM_LLD_H
27
28#if HAL_USE_PWM || defined(__DOXYGEN__)
29
30#include "wb32_tim.h"
31
32/*===========================================================================*/
33/* Driver constants. */
34/*===========================================================================*/
35
36/**
37 * @brief Number of PWM channels per PWM driver.
38 */
39#define PWM_CHANNELS WB32_TIM_MAX_CHANNELS
40
41/**
42 * @name WB32-specific PWM complementary output mode macros
43 * @{
44 */
45/**
46 * @brief Complementary output modes mask.
47 * @note This is an WB32-specific setting.
48 */
49#define PWM_COMPLEMENTARY_OUTPUT_MASK 0xF0
50
51/**
52 * @brief Complementary output not driven.
53 * @note This is an WB32-specific setting.
54 */
55#define PWM_COMPLEMENTARY_OUTPUT_DISABLED 0x00
56
57/**
58 * @brief Complementary output, active is logic level one.
59 * @note This is an WB32-specific setting.
60 * @note This setting is only available if the configuration option
61 * @p WB32_PWM_USE_ADVANCED is set to TRUE and only for advanced
62 * timers TIM1 and TIM8.
63 */
64#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH 0x10
65
66/**
67 * @brief Complementary output, active is logic level zero.
68 * @note This is an WB32-specific setting.
69 * @note This setting is only available if the configuration option
70 * @p WB32_PWM_USE_ADVANCED is set to TRUE and only for advanced
71 * timers TIM1 and TIM8.
72 */
73#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20
74/** @} */
75
76/*===========================================================================*/
77/* Driver pre-compile time settings. */
78/*===========================================================================*/
79
80/**
81 * @name Configuration options
82 * @{
83 */
84/**
85 * @brief If advanced timer features switch.
86 * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are
87 * enabled.
88 * @note The default is @p FALSE.
89 */
90#if !defined(WB32_PWM_USE_ADVANCED) || defined(__DOXYGEN__)
91#define WB32_PWM_USE_ADVANCED FALSE
92#endif
93
94/**
95 * @brief PWMD1 driver enable switch.
96 * @details If set to @p TRUE the support for PWMD1 is included.
97 * @note The default is @p FALSE.
98 */
99#if !defined(WB32_PWM_USE_TIM1) || defined(__DOXYGEN__)
100#define WB32_PWM_USE_TIM1 FALSE
101#endif
102
103/**
104 * @brief PWMD2 driver enable switch.
105 * @details If set to @p TRUE the support for PWMD2 is included.
106 * @note The default is @p FALSE.
107 */
108#if !defined(WB32_PWM_USE_TIM2) || defined(__DOXYGEN__)
109#define WB32_PWM_USE_TIM2 FALSE
110#endif
111
112/**
113 * @brief PWMD3 driver enable switch.
114 * @details If set to @p TRUE the support for PWMD3 is included.
115 * @note The default is @p FALSE.
116 */
117#if !defined(WB32_PWM_USE_TIM3) || defined(__DOXYGEN__)
118#define WB32_PWM_USE_TIM3 FALSE
119#endif
120
121/**
122 * @brief PWMD4 driver enable switch.
123 * @details If set to @p TRUE the support for PWMD4 is included.
124 * @note The default is @p FALSE.
125 */
126#if !defined(WB32_PWM_USE_TIM4) || defined(__DOXYGEN__)
127#define WB32_PWM_USE_TIM4 FALSE
128#endif
129
130/**
131 * @brief PWMD1 interrupt priority level setting.
132 */
133#if !defined(WB32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
134#define WB32_PWM_TIM1_IRQ_PRIORITY 7
135#endif
136
137/**
138 * @brief PWMD2 interrupt priority level setting.
139 */
140#if !defined(WB32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
141#define WB32_PWM_TIM2_IRQ_PRIORITY 7
142#endif
143
144/**
145 * @brief PWMD3 interrupt priority level setting.
146 */
147#if !defined(WB32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
148#define WB32_PWM_TIM3_IRQ_PRIORITY 7
149#endif
150
151/**
152 * @brief PWMD4 interrupt priority level setting.
153 */
154#if !defined(WB32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
155#define WB32_PWM_TIM4_IRQ_PRIORITY 7
156#endif
157
158/** @} */
159
160/*===========================================================================*/
161/* Configuration checks. */
162/*===========================================================================*/
163
164#if !defined(WB32_HAS_TIM1)
165#define WB32_HAS_TIM1 FALSE
166#endif
167
168#if !defined(WB32_HAS_TIM2)
169#define WB32_HAS_TIM2 FALSE
170#endif
171
172#if !defined(WB32_HAS_TIM3)
173#define WB32_HAS_TIM3 FALSE
174#endif
175
176#if !defined(WB32_HAS_TIM4)
177#define WB32_HAS_TIM4 FALSE
178#endif
179
180#if WB32_PWM_USE_TIM1 && !WB32_HAS_TIM1
181#error "TIM1 not present in the selected device"
182#endif
183
184#if WB32_PWM_USE_TIM2 && !WB32_HAS_TIM2
185#error "TIM2 not present in the selected device"
186#endif
187
188#if WB32_PWM_USE_TIM3 && !WB32_HAS_TIM3
189#error "TIM3 not present in the selected device"
190#endif
191
192#if WB32_PWM_USE_TIM4 && !WB32_HAS_TIM4
193#error "TIM4 not present in the selected device"
194#endif
195
196#if !WB32_PWM_USE_TIM1 && !WB32_PWM_USE_TIM2 && \
197 !WB32_PWM_USE_TIM3 && !WB32_PWM_USE_TIM4
198#error "PWM driver activated but no TIM peripheral assigned"
199#endif
200
201#if WB32_PWM_USE_ADVANCED && !WB32_PWM_USE_TIM1
202#error "advanced mode selected but no advanced timer assigned"
203#endif
204
205/* Checks on allocation of TIMx units.*/
206#if WB32_PWM_USE_TIM1
207#if defined(WB32_TIM1_IS_USED)
208#error "PWMD1 requires TIM1 but the timer is already used"
209#else
210#define WB32_TIM1_IS_USED
211#endif
212#endif
213
214#if WB32_PWM_USE_TIM2
215#if defined(WB32_TIM2_IS_USED)
216#error "PWMD2 requires TIM2 but the timer is already used"
217#else
218#define WB32_TIM2_IS_USED
219#endif
220#endif
221
222#if WB32_PWM_USE_TIM3
223#if defined(WB32_TIM3_IS_USED)
224#error "PWMD3 requires TIM3 but the timer is already used"
225#else
226#define WB32_TIM3_IS_USED
227#endif
228#endif
229
230#if WB32_PWM_USE_TIM4
231#if defined(WB32_TIM4_IS_USED)
232#error "PWMD4 requires TIM4 but the timer is already used"
233#else
234#define WB32_TIM4_IS_USED
235#endif
236#endif
237
238/* IRQ priority checks.*/
239#if WB32_PWM_USE_TIM1 && !defined(WB32_TIM1_SUPPRESS_ISR) && \
240 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_PWM_TIM1_IRQ_PRIORITY)
241#error "Invalid IRQ priority assigned to TIM1"
242#endif
243
244#if WB32_PWM_USE_TIM2 && !defined(WB32_TIM2_SUPPRESS_ISR) && \
245 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_PWM_TIM2_IRQ_PRIORITY)
246#error "Invalid IRQ priority assigned to TIM2"
247#endif
248
249#if WB32_PWM_USE_TIM3 && !defined(WB32_TIM3_SUPPRESS_ISR) && \
250 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_PWM_TIM3_IRQ_PRIORITY)
251#error "Invalid IRQ priority assigned to TIM3"
252#endif
253
254#if WB32_PWM_USE_TIM4 && !defined(WB32_TIM4_SUPPRESS_ISR) && \
255 !OSAL_IRQ_IS_VALID_PRIORITY(WB32_PWM_TIM4_IRQ_PRIORITY)
256#error "Invalid IRQ priority assigned to TIM4"
257#endif
258
259/*===========================================================================*/
260/* Driver data structures and types. */
261/*===========================================================================*/
262
263/**
264 * @brief Type of a PWM mode.
265 */
266typedef uint32_t pwmmode_t;
267
268/**
269 * @brief Type of a PWM channel.
270 */
271typedef uint8_t pwmchannel_t;
272
273/**
274 * @brief Type of a channels mask.
275 */
276typedef uint32_t pwmchnmsk_t;
277
278/**
279 * @brief Type of a PWM counter.
280 */
281typedef uint32_t pwmcnt_t;
282
283/**
284 * @brief Type of a PWM driver channel configuration structure.
285 */
286typedef struct {
287 /**
288 * @brief Channel active logic level.
289 */
290 pwmmode_t mode;
291 /**
292 * @brief Channel callback pointer.
293 * @note This callback is invoked on the channel compare event. If set to
294 * @p NULL then the callback is disabled.
295 */
296 pwmcallback_t callback;
297 /* End of the mandatory fields.*/
298} PWMChannelConfig;
299
300/**
301 * @brief Type of a PWM driver configuration structure.
302 */
303typedef struct {
304 /**
305 * @brief Timer clock in Hz.
306 * @note The low level can use assertions in order to catch invalid
307 * frequency specifications.
308 */
309 uint32_t frequency;
310 /**
311 * @brief PWM period in ticks.
312 * @note The low level can use assertions in order to catch invalid
313 * period specifications.
314 */
315 pwmcnt_t period;
316 /**
317 * @brief Periodic callback pointer.
318 * @note This callback is invoked on PWM counter reset. If set to
319 * @p NULL then the callback is disabled.
320 */
321 pwmcallback_t callback;
322 /**
323 * @brief Channels configurations.
324 */
325 PWMChannelConfig channels[PWM_CHANNELS];
326 /* End of the mandatory fields.*/
327 /**
328 * @brief TIM CR2 register initialization data.
329 * @note The value of this field should normally be equal to zero.
330 */
331 uint32_t cr2;
332#if WB32_PWM_USE_ADVANCED || defined(__DOXYGEN__)
333 /**
334 * @brief TIM BDTR (break & dead-time) register initialization data.
335 * @note The value of this field should normally be equal to zero.
336 */
337 uint32_t bdtr;
338#endif
339 /**
340 * @brief TIM DIER register initialization data.
341 * @note The value of this field should normally be equal to zero.
342 * @note Only the DMA-related bits can be specified in this field.
343 */
344 uint32_t dier;
345} PWMConfig;
346
347/**
348 * @brief Structure representing a PWM driver.
349 */
350struct PWMDriver {
351 /**
352 * @brief Driver state.
353 */
354 pwmstate_t state;
355 /**
356 * @brief Current driver configuration data.
357 */
358 const PWMConfig *config;
359 /**
360 * @brief Current PWM period in ticks.
361 */
362 pwmcnt_t period;
363 /**
364 * @brief Mask of the enabled channels.
365 */
366 pwmchnmsk_t enabled;
367 /**
368 * @brief Number of channels in this instance.
369 */
370 pwmchannel_t channels;
371#if defined(PWM_DRIVER_EXT_FIELDS)
372 PWM_DRIVER_EXT_FIELDS
373#endif
374 /* End of the mandatory fields.*/
375 /**
376 * @brief Timer base clock.
377 */
378 uint32_t clock;
379 /**
380 * @brief Pointer to the TIMx registers block.
381 */
382 wb32_tim_t *tim;
383};
384
385/*===========================================================================*/
386/* Driver macros. */
387/*===========================================================================*/
388
389/**
390 * @brief Changes the period the PWM peripheral.
391 * @details This function changes the period of a PWM unit that has already
392 * been activated using @p pwmStart().
393 * @pre The PWM unit must have been activated using @p pwmStart().
394 * @post The PWM unit period is changed to the new value.
395 * @note The function has effect at the next cycle start.
396 * @note If a period is specified that is shorter than the pulse width
397 * programmed in one of the channels then the behavior is not
398 * guaranteed.
399 *
400 * @param[in] pwmp pointer to a @p PWMDriver object
401 * @param[in] period new cycle time in ticks
402 *
403 * @notapi
404 */
405#define pwm_lld_change_period(pwmp, period) \
406 ((pwmp)->tim->ARR = ((period) - 1))
407
408/*===========================================================================*/
409/* External declarations. */
410/*===========================================================================*/
411
412#if WB32_PWM_USE_TIM1 && !defined(__DOXYGEN__)
413extern PWMDriver PWMD1;
414#endif
415
416#if WB32_PWM_USE_TIM2 && !defined(__DOXYGEN__)
417extern PWMDriver PWMD2;
418#endif
419
420#if WB32_PWM_USE_TIM3 && !defined(__DOXYGEN__)
421extern PWMDriver PWMD3;
422#endif
423
424#if WB32_PWM_USE_TIM4 && !defined(__DOXYGEN__)
425extern PWMDriver PWMD4;
426#endif
427
428#ifdef __cplusplus
429extern "C" {
430#endif
431 void pwm_lld_init(void);
432 void pwm_lld_start(PWMDriver *pwmp);
433 void pwm_lld_stop(PWMDriver *pwmp);
434 void pwm_lld_enable_channel(PWMDriver *pwmp,
435 pwmchannel_t channel,
436 pwmcnt_t width);
437 void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
438 void pwm_lld_enable_periodic_notification(PWMDriver *pwmp);
439 void pwm_lld_disable_periodic_notification(PWMDriver *pwmp);
440 void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
441 pwmchannel_t channel);
442 void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
443 pwmchannel_t channel);
444 void pwm_lld_serve_interrupt(PWMDriver *pwmp);
445#ifdef __cplusplus
446}
447#endif
448
449#endif /* HAL_USE_PWM */
450
451#endif /* HAL_PWM_LLD_H */
452
453/** @} */
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.c b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.c
new file mode 100644
index 000000000..de765ca7d
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.c
@@ -0,0 +1,270 @@
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 TIMv1/hal_st_lld.c
19 * @brief ST Driver subsystem low level driver code.
20 *
21 * @addtogroup ST
22 * @{
23 */
24
25#include "hal.h"
26
27#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
28
29/*===========================================================================*/
30/* Driver local definitions. */
31/*===========================================================================*/
32
33#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
34
35#if (OSAL_ST_RESOLUTION == 32)
36#define ST_ARR_INIT 0xFFFFFFFFU
37#else
38#define ST_ARR_INIT 0x0000FFFFU
39#endif
40
41#if WB32_ST_USE_TIMER == 2
42
43#if !WB32_HAS_TIM2
44#error "TIM2 not present in the selected device"
45#endif
46
47#if (OSAL_ST_RESOLUTION == 32) && !WB32_TIM2_IS_32BITS
48#error "TIM2 is not a 32bits timer"
49#endif
50
51#define ST_HANDLER WB32_TIM2_IRQ_VECTOR
52#define ST_NUMBER WB32_TIM2_NUMBER
53#define ST_CLOCK_SRC WB32_TIMCLK1
54#define ST_ENABLE_CLOCK() rccEnableTIM2()
55#if defined(WB32F3G71xx)
56#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM2_STOP
57#endif
58
59#elif WB32_ST_USE_TIMER == 3
60
61#if !WB32_HAS_TIM3
62#error "TIM3 not present in the selected device"
63#endif
64
65#if (OSAL_ST_RESOLUTION == 32) && !WB32_TIM3_IS_32BITS
66#error "TIM3 is not a 32bits timer"
67#endif
68
69#define ST_HANDLER WB32_TIM3_IRQ_VECTOR
70#define ST_NUMBER WB32_TIM3_NUMBER
71#define ST_CLOCK_SRC WB32_TIMCLK1
72#define ST_ENABLE_CLOCK() rccEnableTIM3()
73#if defined(WB32F3G71xx)
74#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM3_STOP
75#endif
76
77#elif WB32_ST_USE_TIMER == 4
78
79#if !WB32_HAS_TIM4
80#error "TIM4 not present in the selected device"
81#endif
82
83#if (OSAL_ST_RESOLUTION == 32) && !WB32_TIM4_IS_32BITS
84#error "TIM4 is not a 32bits timer"
85#endif
86
87#define ST_HANDLER WB32_TIM4_IRQ_VECTOR
88#define ST_NUMBER WB32_TIM4_NUMBER
89#define ST_CLOCK_SRC WB32_TIMCLK1
90#define ST_ENABLE_CLOCK() rccEnableTIM4()
91#if defined(WB32F3G71xx)
92#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM4_STOP
93#endif
94
95#else
96#error "WB32_ST_USE_TIMER specifies an unsupported timer"
97#endif
98
99#if ST_CLOCK_SRC % OSAL_ST_FREQUENCY != 0
100#error "the selected ST frequency is not obtainable because integer rounding"
101#endif
102
103#if (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1 > 0xFFFF
104#error "the selected ST frequency is not obtainable because TIM timer prescaler limits"
105#endif
106
107#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
108
109#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
110
111#define ST_HANDLER SysTick_Handler
112
113#if defined(WB32_CORE_CK)
114#define SYSTICK_CK WB32_CORE_CK
115#else
116#define SYSTICK_CK WB32_HCLK
117#endif
118
119#if SYSTICK_CK % OSAL_ST_FREQUENCY != 0
120#error "the selected ST frequency is not obtainable because integer rounding"
121#endif
122
123#if (SYSTICK_CK / OSAL_ST_FREQUENCY) - 1 > 0xFFFFFF
124#error "the selected ST frequency is not obtainable because SysTick timer counter limits"
125#endif
126
127#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
128
129/*===========================================================================*/
130/* Driver exported variables. */
131/*===========================================================================*/
132
133/*===========================================================================*/
134/* Driver local types. */
135/*===========================================================================*/
136
137/*===========================================================================*/
138/* Driver local variables and types. */
139/*===========================================================================*/
140
141/*===========================================================================*/
142/* Driver local functions. */
143/*===========================================================================*/
144
145/*===========================================================================*/
146/* Driver interrupt handlers. */
147/*===========================================================================*/
148
149#if !defined(WB32_SYSTICK_SUPPRESS_ISR)
150/**
151 * @brief Interrupt handler.
152 *
153 * @isr
154 */
155OSAL_IRQ_HANDLER(ST_HANDLER) {
156
157 OSAL_IRQ_PROLOGUE();
158
159 st_lld_serve_interrupt();
160
161 OSAL_IRQ_EPILOGUE();
162}
163#endif
164
165/*===========================================================================*/
166/* Driver exported functions. */
167/*===========================================================================*/
168
169/**
170 * @brief Low level ST driver initialization.
171 *
172 * @notapi
173 */
174void st_lld_init(void) {
175
176#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
177 /* Free running counter mode.*/
178
179 /* Enabling timer clock.*/
180 ST_ENABLE_CLOCK();
181
182 /* Enabling the stop mode during debug for this timer.*/
183 ST_ENABLE_STOP();
184
185 /* Initializing the counter in free running mode.*/
186 WB32_ST_TIM->PSC = (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1;
187 WB32_ST_TIM->ARR = ST_ARR_INIT;
188 WB32_ST_TIM->CCMR1 = 0;
189 WB32_ST_TIM->CCR[0] = 0;
190#if ST_LLD_NUM_ALARMS > 1
191 WB32_ST_TIM->CCR[1] = 0;
192#endif
193#if ST_LLD_NUM_ALARMS > 2
194 WB32_ST_TIM->CCR[2] = 0;
195#endif
196#if ST_LLD_NUM_ALARMS > 3
197 WB32_ST_TIM->CCR[3] = 0;
198#endif
199 WB32_ST_TIM->DIER = 0;
200 WB32_ST_TIM->CR2 = 0;
201 WB32_ST_TIM->EGR = TIM_EGR_UG;
202 WB32_ST_TIM->CR1 = TIM_CR1_CEN;
203
204#if !defined(WB32_SYSTICK_SUPPRESS_ISR)
205 /* IRQ enabled.*/
206 nvicEnableVector(ST_NUMBER, WB32_ST_IRQ_PRIORITY);
207#endif
208#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
209
210#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
211 /* Periodic systick mode, the Cortex-Mx internal systick timer is
212 used in this mode.*/
213 SysTick->LOAD = (SYSTICK_CK / OSAL_ST_FREQUENCY) - 1;
214 SysTick->VAL = 0;
215 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
216 SysTick_CTRL_ENABLE_Msk |
217 SysTick_CTRL_TICKINT_Msk;
218
219 /* IRQ enabled.*/
220 nvicSetSystemHandlerPriority(HANDLER_SYSTICK, WB32_ST_IRQ_PRIORITY);
221#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
222}
223
224/**
225 * @brief IRQ handling code.
226 */
227void st_lld_serve_interrupt(void) {
228#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
229 uint32_t sr;
230 wb32_tim_t *timp = WB32_ST_TIM;
231
232 sr = timp->SR;
233 sr &= timp->DIER & WB32_TIM_DIER_IRQ_MASK;
234 timp->SR = ~sr;
235
236 if ((sr & TIM_SR_CC1IF) != 0U)
237#endif
238 {
239 osalSysLockFromISR();
240 osalOsTimerHandlerI();
241 osalSysUnlockFromISR();
242 }
243#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
244#if ST_LLD_NUM_ALARMS > 1
245 if ((sr & TIM_SR_CC2IF) != 0U) {
246 if (st_callbacks[2] != NULL) {
247 st_callbacks[0](1U);
248 }
249 }
250#endif
251#if ST_LLD_NUM_ALARMS > 2
252 if ((sr & TIM_SR_CC3IF) != 0U) {
253 if (st_callbacks[2] != NULL) {
254 st_callbacks[1](2U);
255 }
256 }
257#endif
258#if ST_LLD_NUM_ALARMS > 3
259 if ((sr & TIM_SR_CC4IF) != 0U) {
260 if (st_callbacks[2] != NULL) {
261 st_callbacks[2](3U);
262 }
263 }
264#endif
265#endif
266}
267
268#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
269
270/** @} */
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.h b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.h
new file mode 100644
index 000000000..6ae1c8770
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.h
@@ -0,0 +1,369 @@
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 TIMv1/hal_st_lld.h
19 * @brief ST Driver subsystem low level driver header.
20 * @details This header is designed to be include-able without having to
21 * include other files from the HAL.
22 *
23 * @addtogroup ST
24 * @{
25 */
26
27#ifndef HAL_ST_LLD_H
28#define HAL_ST_LLD_H
29
30/*===========================================================================*/
31/* Driver constants. */
32/*===========================================================================*/
33
34/* Feature currently disabled.*/
35#define WB32_ST_ENFORCE_ALARMS 1
36
37/*===========================================================================*/
38/* Driver pre-compile time settings. */
39/*===========================================================================*/
40
41/**
42 * @name Configuration options
43 * @{
44 */
45/**
46 * @brief SysTick timer IRQ priority.
47 */
48#if !defined(WB32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__)
49#define WB32_ST_IRQ_PRIORITY 8
50#endif
51
52/**
53 * @brief TIMx unit (by number) to be used for free running operations.
54 * @note You must select a 32 bits timer if a 32 bits @p systick_t type
55 * is required.
56 * @note Timers 2, 3, 4, 5, 21 and 22 are supported.
57 */
58#if !defined(WB32_ST_USE_TIMER) || defined(__DOXYGEN__)
59#define WB32_ST_USE_TIMER 2
60#endif
61/** @} */
62
63/*===========================================================================*/
64/* Derived constants and error checks. */
65/*===========================================================================*/
66
67/* This has to go after transition to shared handlers is complete for all
68 platforms.*/
69#if !defined(WB32_HAS_TIM2)
70#define WB32_HAS_TIM2 FALSE
71#endif
72
73#if !defined(WB32_HAS_TIM3)
74#define WB32_HAS_TIM3 FALSE
75#endif
76
77#if !defined(WB32_HAS_TIM4)
78#define WB32_HAS_TIM4 FALSE
79#endif
80
81/**/
82
83#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
84
85#if WB32_ST_USE_TIMER == 2
86
87#if defined(WB32_TIM2_IS_USED)
88#error "ST requires TIM2 but the timer is already used"
89#else
90#define WB32_TIM2_IS_USED
91#endif
92
93#if defined(WB32_TIM2_SUPPRESS_ISR)
94#define WB32_SYSTICK_SUPPRESS_ISR
95#endif
96
97#define WB32_ST_TIM WB32_TIM2
98#define ST_LLD_NUM_ALARMS WB32_TIM2_CHANNELS
99#define WB32_ST_USE_SYSTICK FALSE
100#define WB32_ST_USE_TIM2 TRUE
101#define WB32_ST_USE_TIM3 FALSE
102#define WB32_ST_USE_TIM4 FALSE
103
104
105#elif WB32_ST_USE_TIMER == 3
106
107#if defined(WB32_TIM3_IS_USED)
108#error "ST requires TIM3 but the timer is already used"
109#else
110#define WB32_TIM3_IS_USED
111#endif
112
113#if defined(WB32_TIM3_SUPPRESS_ISR)
114#define WB32_SYSTICK_SUPPRESS_ISR
115#endif
116
117#define WB32_ST_TIM WB32_TIM3
118#define ST_LLD_NUM_ALARMS WB32_TIM3_CHANNELS
119#define WB32_ST_USE_SYSTICK FALSE
120#define WB32_ST_USE_TIM2 FALSE
121#define WB32_ST_USE_TIM3 TRUE
122#define WB32_ST_USE_TIM4 FALSE
123
124#elif WB32_ST_USE_TIMER == 4
125
126#if defined(WB32_TIM4_IS_USED)
127#error "ST requires TIM4 but the timer is already used"
128#else
129#define WB32_TIM4_IS_USED
130#endif
131
132#if defined(WB32_TIM4_SUPPRESS_ISR)
133#define WB32_SYSTICK_SUPPRESS_ISR
134#endif
135
136#define WB32_ST_TIM WB32_TIM4
137#define ST_LLD_NUM_ALARMS WB32_TIM4_CHANNELS
138#define WB32_ST_USE_SYSTICK FALSE
139#define WB32_ST_USE_TIM2 FALSE
140#define WB32_ST_USE_TIM3 FALSE
141#define WB32_ST_USE_TIM4 TRUE
142
143#else
144#error "WB32_ST_USE_TIMER specifies an unsupported timer"
145#endif
146
147#if defined(WB32_ST_ENFORCE_ALARMS)
148
149#if (WB32_ST_ENFORCE_ALARMS < 1) || (WB32_ST_ENFORCE_ALARMS > ST_LLD_NUM_ALARMS)
150#error "invalid WB32_ST_ENFORCE_ALARMS value"
151#endif
152
153#undef ST_LLD_NUM_ALARMS
154#define ST_LLD_NUM_ALARMS WB32_ST_ENFORCE_ALARMS
155#endif
156
157#elif OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
158
159#define WB32_ST_USE_SYSTICK TRUE
160#define WB32_ST_USE_TIM2 FALSE
161#define WB32_ST_USE_TIM3 FALSE
162#define WB32_ST_USE_TIM4 FALSE
163
164#else
165
166#define WB32_ST_USE_SYSTICK FALSE
167#define WB32_ST_USE_TIM2 FALSE
168#define WB32_ST_USE_TIM3 FALSE
169#define WB32_ST_USE_TIM4 FALSE
170
171#endif
172
173/*===========================================================================*/
174/* Driver data structures and types. */
175/*===========================================================================*/
176
177/*===========================================================================*/
178/* Driver macros. */
179/*===========================================================================*/
180
181/*===========================================================================*/
182/* External declarations. */
183/*===========================================================================*/
184
185#ifdef __cplusplus
186extern "C" {
187#endif
188 void st_lld_init(void);
189 void st_lld_serve_interrupt(void);
190#ifdef __cplusplus
191}
192#endif
193
194/*===========================================================================*/
195/* Driver inline functions. */
196/*===========================================================================*/
197
198
199#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
200
201/**
202 * @brief Returns the time counter value.
203 *
204 * @return The counter value.
205 *
206 * @notapi
207 */
208static inline systime_t st_lld_get_counter(void) {
209
210 return (systime_t)WB32_ST_TIM->CNT;
211}
212
213/**
214 * @brief Starts the alarm.
215 * @note Makes sure that no spurious alarms are triggered after
216 * this call.
217 *
218 * @param[in] abstime the time to be set for the first alarm
219 *
220 * @notapi
221 */
222static inline void st_lld_start_alarm(systime_t abstime) {
223
224 WB32_ST_TIM->CCR[0] = (uint32_t)abstime;
225 WB32_ST_TIM->SR = 0;
226#if ST_LLD_NUM_ALARMS == 1
227 WB32_ST_TIM->DIER = WB32_TIM_DIER_CC1IE;
228#else
229 WB32_ST_TIM->DIER |= WB32_TIM_DIER_CC1IE;
230#endif
231}
232
233/**
234 * @brief Stops the alarm interrupt.
235 *
236 * @notapi
237 */
238static inline void st_lld_stop_alarm(void) {
239
240#if ST_LLD_NUM_ALARMS == 1
241 WB32_ST_TIM->DIER = 0U;
242#else
243 WB32_ST_TIM->DIER &= ~WB32_TIM_DIER_CC1IE;
244#endif
245}
246
247/**
248 * @brief Sets the alarm time.
249 *
250 * @param[in] abstime the time to be set for the next alarm
251 *
252 * @notapi
253 */
254static inline void st_lld_set_alarm(systime_t abstime) {
255
256 WB32_ST_TIM->CCR[0] = (uint32_t)abstime;
257}
258
259/**
260 * @brief Returns the current alarm time.
261 *
262 * @return The currently set alarm time.
263 *
264 * @notapi
265 */
266static inline systime_t st_lld_get_alarm(void) {
267
268 return (systime_t)WB32_ST_TIM->CCR[0];
269}
270
271/**
272 * @brief Determines if the alarm is active.
273 *
274 * @return The alarm status.
275 * @retval false if the alarm is not active.
276 * @retval true is the alarm is active
277 *
278 * @notapi
279 */
280static inline bool st_lld_is_alarm_active(void) {
281
282 return (bool)((WB32_ST_TIM->DIER & WB32_TIM_DIER_CC1IE) != 0);
283}
284
285#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__)
286/**
287 * @brief Starts an alarm.
288 * @note Makes sure that no spurious alarms are triggered after
289 * this call.
290 * @note This functionality is only available in free running mode, the
291 * behavior in periodic mode is undefined.
292 *
293 * @param[in] abstime the time to be set for the first alarm
294 * @param[in] alarm alarm channel number
295 *
296 * @notapi
297 */
298static inline void st_lld_start_alarm_n(unsigned alarm, systime_t abstime) {
299
300 WB32_ST_TIM->CCR[alarm] = (uint32_t)abstime;
301 WB32_ST_TIM->SR = 0;
302 WB32_ST_TIM->DIER |= (WB32_TIM_DIER_CC1IE << alarm);
303}
304
305/**
306 * @brief Stops an alarm interrupt.
307 * @note This functionality is only available in free running mode, the
308 * behavior in periodic mode is undefined.
309 *
310 * @param[in] alarm alarm channel number
311 *
312 * @notapi
313 */
314static inline void st_lld_stop_alarm_n(unsigned alarm) {
315
316 WB32_ST_TIM->DIER &= ~(WB32_TIM_DIER_CC1IE << alarm);
317}
318
319/**
320 * @brief Sets an alarm time.
321 * @note This functionality is only available in free running mode, the
322 * behavior in periodic mode is undefined.
323 *
324 * @param[in] alarm alarm channel number
325 * @param[in] abstime the time to be set for the next alarm
326 *
327 * @notapi
328 */
329static inline void st_lld_set_alarm_n(unsigned alarm, systime_t abstime) {
330
331 WB32_ST_TIM->CCR[alarm] = (uint32_t)abstime;
332}
333
334/**
335 * @brief Returns an alarm current time.
336 * @note This functionality is only available in free running mode, the
337 * behavior in periodic mode is undefined.
338 *
339 * @param[in] alarm alarm channel number
340 * @return The currently set alarm time.
341 *
342 * @notapi
343 */
344static inline systime_t st_lld_get_alarm_n(unsigned alarm) {
345
346 return (systime_t)WB32_ST_TIM->CCR[alarm];
347}
348
349/**
350 * @brief Determines if an alarm is active.
351 *
352 * @param[in] alarm alarm channel number
353 * @return The alarm status.
354 * @retval false if the alarm is not active.
355 * @retval true is the alarm is active
356 *
357 * @notapi
358 */
359static inline bool st_lld_is_alarm_active_n(unsigned alarm) {
360
361 return (bool)((WB32_ST_TIM->DIER & (WB32_TIM_DIER_CC1IE << alarm)) != 0);
362}
363#endif /* ST_LLD_NUM_ALARMS > 1 */
364
365#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
366
367#endif /* HAL_ST_LLD_H */
368
369/** @} */
diff --git a/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/wb32_tim.h b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/wb32_tim.h
new file mode 100644
index 000000000..116f5cb5b
--- /dev/null
+++ b/lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1/wb32_tim.h
@@ -0,0 +1,534 @@
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 TIMv1/wb32_tim.h
19 * @brief WB32 TIM units common header.
20 * @note This file requires definitions from the ST WB32 header file.
21 *
22 * @addtogroup WB32_TIMv1
23 * @{
24 */
25
26#ifndef WB32_TIM_H
27#define WB32_TIM_H
28
29/*===========================================================================*/
30/* Driver constants. */
31/*===========================================================================*/
32
33/**
34 * @name TIM_CR1 register
35 * @{
36 */
37#define WB32_TIM_CR1_CEN (1U << 0)
38#define WB32_TIM_CR1_UDIS (1U << 1)
39#define WB32_TIM_CR1_URS (1U << 2)
40#define WB32_TIM_CR1_OPM (1U << 3)
41#define WB32_TIM_CR1_DIR (1U << 4)
42
43#define WB32_TIM_CR1_CMS_MASK (3U << 5)
44#define WB32_TIM_CR1_CMS(n) ((n) << 5)
45
46#define WB32_TIM_CR1_ARPE (1U << 7)
47
48#define WB32_TIM_CR1_CKD_MASK (3U << 8)
49#define WB32_TIM_CR1_CKD(n) ((n) << 8)
50
51#define WB32_TIM_CR1_UIFREMAP (1U << 11)
52/** @} */
53
54/**
55 * @name TIM_CR2 register
56 * @{
57 */
58#define WB32_TIM_CR2_CCPC (1U << 0)
59#define WB32_TIM_CR2_CCUS (1U << 2)
60#define WB32_TIM_CR2_CCDS (1U << 3)
61
62#define WB32_TIM_CR2_MMS_MASK (7U << 4)
63#define WB32_TIM_CR2_MMS(n) ((n) << 4)
64
65#define WB32_TIM_CR2_TI1S (1U << 7)
66#define WB32_TIM_CR2_OIS1 (1U << 8)
67#define WB32_TIM_CR2_OIS1N (1U << 9)
68#define WB32_TIM_CR2_OIS2 (1U << 10)
69#define WB32_TIM_CR2_OIS2N (1U << 11)
70#define WB32_TIM_CR2_OIS3 (1U << 12)
71#define WB32_TIM_CR2_OIS3N (1U << 13)
72#define WB32_TIM_CR2_OIS4 (1U << 14)
73#define WB32_TIM_CR2_OIS5 (1U << 16)
74#define WB32_TIM_CR2_OIS6 (1U << 18)
75
76#define WB32_TIM_CR2_MMS2_MASK (15U << 20)
77#define WB32_TIM_CR2_MMS2(n) ((n) << 20)
78/** @} */
79
80/**
81 * @name TIM_SMCR register
82 * @{
83 */
84#define WB32_TIM_SMCR_SMS_MASK ((7U << 0) | (1U << 16))
85#define WB32_TIM_SMCR_SMS(n) ((((n) & 7) << 0) | \
86 (((n) >> 3) << 16))
87
88#define WB32_TIM_SMCR_OCCS (1U << 3)
89
90#define WB32_TIM_SMCR_TS_MASK (7U << 4)
91#define WB32_TIM_SMCR_TS(n) ((n) << 4)
92
93#define WB32_TIM_SMCR_MSM (1U << 7)
94
95#define WB32_TIM_SMCR_ETF_MASK (15U << 8)
96#define WB32_TIM_SMCR_ETF(n) ((n) << 8)
97
98#define WB32_TIM_SMCR_ETPS_MASK (3U << 12)
99#define WB32_TIM_SMCR_ETPS(n) ((n) << 12)
100
101#define WB32_TIM_SMCR_ECE (1U << 14)
102#define WB32_TIM_SMCR_ETP (1U << 15)
103/** @} */
104
105/**
106 * @name TIM_DIER register
107 * @{
108 */
109#define WB32_TIM_DIER_UIE (1U << 0)
110#define WB32_TIM_DIER_CC1IE (1U << 1)
111#define WB32_TIM_DIER_CC2IE (1U << 2)
112#define WB32_TIM_DIER_CC3IE (1U << 3)
113#define WB32_TIM_DIER_CC4IE (1U << 4)
114#define WB32_TIM_DIER_COMIE (1U << 5)
115#define WB32_TIM_DIER_TIE (1U << 6)
116#define WB32_TIM_DIER_BIE (1U << 7)
117#define WB32_TIM_DIER_UDE (1U << 8)
118#define WB32_TIM_DIER_CC1DE (1U << 9)
119#define WB32_TIM_DIER_CC2DE (1U << 10)
120#define WB32_TIM_DIER_CC3DE (1U << 11)
121#define WB32_TIM_DIER_CC4DE (1U << 12)
122#define WB32_TIM_DIER_COMDE (1U << 13)
123#define WB32_TIM_DIER_TDE (1U << 14)
124
125#define WB32_TIM_DIER_IRQ_MASK (WB32_TIM_DIER_UIE | \
126 WB32_TIM_DIER_CC1IE | \
127 WB32_TIM_DIER_CC2IE | \
128 WB32_TIM_DIER_CC3IE | \
129 WB32_TIM_DIER_CC4IE | \
130 WB32_TIM_DIER_COMIE | \
131 WB32_TIM_DIER_TIE | \
132 WB32_TIM_DIER_BIE)
133
134/** @} */
135
136/**
137 * @name TIM_SR register
138 * @{
139 */
140#define WB32_TIM_SR_UIF (1U << 0)
141#define WB32_TIM_SR_CC1IF (1U << 1)
142#define WB32_TIM_SR_CC2IF (1U << 2)
143#define WB32_TIM_SR_CC3IF (1U << 3)
144#define WB32_TIM_SR_CC4IF (1U << 4)
145#define WB32_TIM_SR_COMIF (1U << 5)
146#define WB32_TIM_SR_TIF (1U << 6)
147#define WB32_TIM_SR_BIF (1U << 7)
148#define WB32_TIM_SR_B2IF (1U << 8)
149#define WB32_TIM_SR_CC1OF (1U << 9)
150#define WB32_TIM_SR_CC2OF (1U << 10)
151#define WB32_TIM_SR_CC3OF (1U << 11)
152#define WB32_TIM_SR_CC4OF (1U << 12)
153#define WB32_TIM_SR_CC5IF (1U << 16)
154#define WB32_TIM_SR_CC6IF (1U << 17)
155/** @} */
156
157/**
158 * @name TIM_EGR register
159 * @{
160 */
161#define WB32_TIM_EGR_UG (1U << 0)
162#define WB32_TIM_EGR_CC1G (1U << 1)
163#define WB32_TIM_EGR_CC2G (1U << 2)
164#define WB32_TIM_EGR_CC3G (1U << 3)
165#define WB32_TIM_EGR_CC4G (1U << 4)
166#define WB32_TIM_EGR_COMG (1U << 5)
167#define WB32_TIM_EGR_TG (1U << 6)
168#define WB32_TIM_EGR_BG (1U << 7)
169#define WB32_TIM_EGR_B2G (1U << 8)
170/** @} */
171
172/**
173 * @name TIM_CCMR1 register (output)
174 * @{
175 */
176#define WB32_TIM_CCMR1_CC1S_MASK (3U << 0)
177#define WB32_TIM_CCMR1_CC1S(n) ((n) << 0)
178
179#define WB32_TIM_CCMR1_OC1FE (1U << 2)
180#define WB32_TIM_CCMR1_OC1PE (1U << 3)
181
182#define WB32_TIM_CCMR1_OC1M_MASK ((7U << 4) | (1U << 16))
183#define WB32_TIM_CCMR1_OC1M(n) ((((n) & 7) << 4) | \
184 (((n) >> 3) << 16))
185
186#define WB32_TIM_CCMR1_OC1CE (1U << 7)
187
188#define WB32_TIM_CCMR1_CC2S_MASK (3U << 8)
189#define WB32_TIM_CCMR1_CC2S(n) ((n) << 8)
190
191#define WB32_TIM_CCMR1_OC2FE (1U << 10)
192#define WB32_TIM_CCMR1_OC2PE (1U << 11)
193
194#define WB32_TIM_CCMR1_OC2M_MASK ((7U << 12) | (1U << 24))
195#define WB32_TIM_CCMR1_OC2M(n) ((((n) & 7) << 12) | \
196 (((n) >> 3) << 24))
197
198#define WB32_TIM_CCMR1_OC2CE (1U << 15)
199/** @} */
200
201/**
202 * @name CCMR1 register (input)
203 * @{
204 */
205#define WB32_TIM_CCMR1_IC1PSC_MASK (3U << 2)
206#define WB32_TIM_CCMR1_IC1PSC(n) ((n) << 2)
207
208#define WB32_TIM_CCMR1_IC1F_MASK (15U << 4)
209#define WB32_TIM_CCMR1_IC1F(n) ((n) << 4)
210
211#define WB32_TIM_CCMR1_IC2PSC_MASK (3U << 10)
212#define WB32_TIM_CCMR1_IC2PSC(n) ((n) << 10)
213
214#define WB32_TIM_CCMR1_IC2F_MASK (15U << 12)
215#define WB32_TIM_CCMR1_IC2F(n) ((n) << 12)
216/** @} */
217
218/**
219 * @name TIM_CCMR2 register (output)
220 * @{
221 */
222#define WB32_TIM_CCMR2_CC3S_MASK (3U << 0)
223#define WB32_TIM_CCMR2_CC3S(n) ((n) << 0)
224
225#define WB32_TIM_CCMR2_OC3FE (1U << 2)
226#define WB32_TIM_CCMR2_OC3PE (1U << 3)
227
228#define WB32_TIM_CCMR2_OC3M_MASK ((7U << 4) | (1U << 16))
229#define WB32_TIM_CCMR2_OC3M(n) ((((n) & 7) << 4) | \
230 (((n) >> 3) << 16))
231
232#define WB32_TIM_CCMR2_OC3CE (1U << 7)
233
234#define WB32_TIM_CCMR2_CC4S_MASK (3U << 8)
235#define WB32_TIM_CCMR2_CC4S(n) ((n) << 8)
236
237#define WB32_TIM_CCMR2_OC4FE (1U << 10)
238#define WB32_TIM_CCMR2_OC4PE (1U << 11)
239
240#define WB32_TIM_CCMR2_OC4M_MASK ((7U << 12) | (1U << 24))
241#define WB32_TIM_CCMR2_OC4M(n) ((((n) & 7) << 12) | \
242 (((n) >> 3) << 24))
243
244#define WB32_TIM_CCMR2_OC4CE (1U << 15)
245/** @} */
246
247/**
248 * @name TIM_CCMR2 register (input)
249 * @{
250 */
251#define WB32_TIM_CCMR2_IC3PSC_MASK (3U << 2)
252#define WB32_TIM_CCMR2_IC3PSC(n) ((n) << 2)
253
254#define WB32_TIM_CCMR2_IC3F_MASK (15U << 4)
255#define WB32_TIM_CCMR2_IC3F(n) ((n) << 4)
256
257#define WB32_TIM_CCMR2_IC4PSC_MASK (3U << 10)
258#define WB32_TIM_CCMR2_IC4PSC(n) ((n) << 10)
259
260#define WB32_TIM_CCMR2_IC4F_MASK (15U << 12)
261#define WB32_TIM_CCMR2_IC4F(n) ((n) << 12)
262/** @} */
263
264/**
265 * @name TIM_CCER register
266 * @{
267 */
268#define WB32_TIM_CCER_CC1E (1U << 0)
269#define WB32_TIM_CCER_CC1P (1U << 1)
270#define WB32_TIM_CCER_CC1NE (1U << 2)
271#define WB32_TIM_CCER_CC1NP (1U << 3)
272#define WB32_TIM_CCER_CC2E (1U << 4)
273#define WB32_TIM_CCER_CC2P (1U << 5)
274#define WB32_TIM_CCER_CC2NE (1U << 6)
275#define WB32_TIM_CCER_CC2NP (1U << 7)
276#define WB32_TIM_CCER_CC3E (1U << 8)
277#define WB32_TIM_CCER_CC3P (1U << 9)
278#define WB32_TIM_CCER_CC3NE (1U << 10)
279#define WB32_TIM_CCER_CC3NP (1U << 11)
280#define WB32_TIM_CCER_CC4E (1U << 12)
281#define WB32_TIM_CCER_CC4P (1U << 13)
282#define WB32_TIM_CCER_CC4NE (1U << 14)
283#define WB32_TIM_CCER_CC4NP (1U << 15)
284#define WB32_TIM_CCER_CC5E (1U << 16)
285#define WB32_TIM_CCER_CC5P (1U << 17)
286#define WB32_TIM_CCER_CC6E (1U << 20)
287#define WB32_TIM_CCER_CC6P (1U << 21)
288/** @} */
289
290/**
291 * @name TIM_CNT register
292 * @{
293 */
294#define WB32_TIM_CNT_UIFCPY (1U << 31)
295/** @} */
296
297/**
298 * @name TIM_BDTR register
299 * @{
300 */
301#define WB32_TIM_BDTR_DTG_MASK (255U << 0)
302#define WB32_TIM_BDTR_DTG(n) ((n) << 0)
303
304#define WB32_TIM_BDTR_LOCK_MASK (3U << 8)
305#define WB32_TIM_BDTR_LOCK(n) ((n) << 8)
306
307#define WB32_TIM_BDTR_OSSI (1U << 10)
308#define WB32_TIM_BDTR_OSSR (1U << 11)
309#define WB32_TIM_BDTR_BKE (1U << 12)
310#define WB32_TIM_BDTR_BKP (1U << 13)
311#define WB32_TIM_BDTR_AOE (1U << 14)
312#define WB32_TIM_BDTR_MOE (1U << 15)
313
314#define WB32_TIM_BDTR_BKF_MASK (15U << 16)
315#define WB32_TIM_BDTR_BKF(n) ((n) << 16)
316#define WB32_TIM_BDTR_BK2F_MASK (15U << 20)
317#define WB32_TIM_BDTR_BK2F(n) ((n) << 20)
318
319#define WB32_TIM_BDTR_BK2E (1U << 24)
320#define WB32_TIM_BDTR_BK2P (1U << 25)
321/** @} */
322
323/**
324 * @name TIM_DCR register
325 * @{
326 */
327#define WB32_TIM_DCR_DBA_MASK (31U << 0)
328#define WB32_TIM_DCR_DBA(n) ((n) << 0)
329
330#define WB32_TIM_DCR_DBL_MASK (31U << 8)
331#define WB32_TIM_DCR_DBL(n) ((n) << 8)
332/** @} */
333
334/**
335 * @name TIM16_OR register
336 * @{
337 */
338#define WB32_TIM16_OR_TI1_RMP_MASK (3U << 6)
339#define WB32_TIM16_OR_TI1_RMP(n) ((n) << 6)
340/** @} */
341
342/**
343 * @name TIM_OR register
344 * @{
345 */
346#define WB32_TIM_OR_ETR_RMP_MASK (15U << 0)
347#define WB32_TIM_OR_ETR_RMP(n) ((n) << 0)
348/** @} */
349
350/**
351 * @name TIM_CCMR3 register
352 * @{
353 */
354#define WB32_TIM_CCMR3_OC5FE (1U << 2)
355#define WB32_TIM_CCMR3_OC5PE (1U << 3)
356
357#define WB32_TIM_CCMR3_OC5M_MASK ((7U << 4) | (1U << 16))
358#define WB32_TIM_CCMR3_OC5M(n) ((((n) & 7) << 4) | \
359 (((n) >> 2) << 16))
360
361#define WB32_TIM_CCMR3_OC5CE (1U << 7)
362
363#define WB32_TIM_CCMR3_OC6FE (1U << 10)
364#define WB32_TIM_CCMR3_OC6PE (1U << 11)
365
366#define WB32_TIM_CCMR3_OC6M_MASK ((7U << 12) | (1U << 24))
367#define WB32_TIM_CCMR3_OC6M(n) ((((n) & 7) << 12) | \
368 (((n) >> 2) << 24))
369
370#define WB32_TIM_CCMR3_OC6CE (1U << 15)
371/** @} */
372
373/**
374 * @name LPTIM_ISR register
375 * @{
376 */
377#define WB32_LPTIM_ISR_CMPM (1U << 0)
378#define WB32_LPTIM_ISR_ARRM (1U << 1)
379#define WB32_LPTIM_ISR_EXTTRIG (1U << 2)
380#define WB32_LPTIM_ISR_CMPOK (1U << 3)
381#define WB32_LPTIM_ISR_ARROK (1U << 4)
382#define WB32_LPTIM_ISR_UP (1U << 5)
383#define WB32_LPTIM_ISR_DOWN (1U << 6)
384/** @} */
385
386/**
387 * @name LPTIM_ICR register
388 * @{
389 */
390#define WB32_LPTIM_ICR_CMPMCF (1U << 0)
391#define WB32_LPTIM_ICR_ARRMCF (1U << 1)
392#define WB32_LPTIM_ICR_EXTTRIGCF (1U << 2)
393#define WB32_LPTIM_ICR_CMPOKCF (1U << 3)
394#define WB32_LPTIM_ICR_ARROKCF (1U << 4)
395#define WB32_LPTIM_ICR_UPCF (1U << 5)
396#define WB32_LPTIM_ICR_DOWNCF (1U << 6)
397/** @} */
398
399/**
400 * @name LPTIM_IER register
401 * @{
402 */
403#define WB32_LPTIM_IER_CMPMIE (1U << 0)
404#define WB32_LPTIM_IER_ARRMIE (1U << 1)
405#define WB32_LPTIM_IER_EXTTRIGIE (1U << 2)
406#define WB32_LPTIM_IER_CMPOKIE (1U << 3)
407#define WB32_LPTIM_IER_ARROKIE (1U << 4)
408#define WB32_LPTIM_IER_UPIE (1U << 5)
409#define WB32_LPTIM_IER_DOWNIE (1U << 6)
410/** @} */
411
412/**
413 * @name LPTIM_CFGR register
414 * @{
415 */
416#define WB32_LPTIM_CFGR_CKSEL (1U << 0)
417#define WB32_LPTIM_CFGR_CKPOL_MASK (3U << 1)
418#define WB32_LPTIM_CFGR_CKPOL(n) ((n) << 1)
419#define WB32_LPTIM_CFGR_CKFLT_MASK (3U << 3)
420#define WB32_LPTIM_CFGR_CKFLT(n) ((n) << 3)
421#define WB32_LPTIM_CFGR_TRGFLT_MASK (3U << 6)
422#define WB32_LPTIM_CFGR_TRGFLT(n) ((n) << 6)
423#define WB32_LPTIM_CFGR_PRESC_MASK (7U << 9)
424#define WB32_LPTIM_CFGR_PRESC(n) ((n) << 9)
425#define WB32_LPTIM_CFGR_TRIGSEL_MASK (7U << 13)
426#define WB32_LPTIM_CFGR_TRIGSEL(n) ((n) << 13)
427#define WB32_LPTIM_CFGR_TRIGEN_MASK (3U << 17)
428#define WB32_LPTIM_CFGR_TRIGEN(n) ((n) << 17)
429#define WB32_LPTIM_CFGR_TIMOUT (1U << 19)
430#define WB32_LPTIM_CFGR_WAVE (1U << 20)
431#define WB32_LPTIM_CFGR_WAVPOL (1U << 21)
432#define WB32_LPTIM_CFGR_PRELOAD (1U << 22)
433#define WB32_LPTIM_CFGR_COUNTMODE (1U << 23)
434#define WB32_LPTIM_CFGR_ENC (1U << 24)
435/** @} */
436
437/**
438 * @name LPTIM_CR register
439 * @{
440 */
441#define WB32_LPTIM_CR_ENABLE (1U << 0)
442#define WB32_LPTIM_CR_SNGSTRT (1U << 1)
443#define WB32_LPTIM_CR_CNTSTRT (1U << 2)
444/** @} */
445
446/**
447 * @name LPTIM_OR register
448 * @{
449 */
450#define WB32_LPTIM_OR_0 (1U << 0)
451#define WB32_LPTIM_OR_1 (1U << 1)
452/** @} */
453
454/**
455 * @name TIM units references
456 * @{
457 */
458#define WB32_TIM1 ((wb32_tim_t *)TIM1_BASE)
459#define WB32_TIM2 ((wb32_tim_t *)TIM2_BASE)
460#define WB32_TIM3 ((wb32_tim_t *)TIM3_BASE)
461#define WB32_TIM4 ((wb32_tim_t *)TIM4_BASE)
462
463#define WB32_LPTIM1 ((wb32_lptim_t *)LPTIM1_BASE)
464#define WB32_LPTIM2 ((wb32_lptim_t *)LPTIM2_BASE)
465/** @} */
466
467/*===========================================================================*/
468/* Driver pre-compile time settings. */
469/*===========================================================================*/
470
471/*===========================================================================*/
472/* Derived constants and error checks. */
473/*===========================================================================*/
474
475/*===========================================================================*/
476/* Driver data structures and types. */
477/*===========================================================================*/
478
479/**
480 * @brief WB32 TIM registers block.
481 * @note This is the most general known form, not all timers have
482 * necessarily all registers and bits.
483 */
484typedef struct {
485 volatile uint32_t CR1;
486 volatile uint32_t CR2;
487 volatile uint32_t SMCR;
488 volatile uint32_t DIER;
489 volatile uint32_t SR;
490 volatile uint32_t EGR;
491 volatile uint32_t CCMR1;
492 volatile uint32_t CCMR2;
493 volatile uint32_t CCER;
494 volatile uint32_t CNT;
495 volatile uint32_t PSC;
496 volatile uint32_t ARR;
497 volatile uint32_t RCR;
498 volatile uint32_t CCR[4];
499 volatile uint32_t BDTR;
500 volatile uint32_t DCR;
501 volatile uint32_t DMAR;
502 volatile uint32_t OR;
503 volatile uint32_t CCMR3;
504 volatile uint32_t CCXR[2];
505} wb32_tim_t;
506
507/**
508 * @brief WB32 LPTIM registers block.
509 * @note This is the most general known form, not all timers have
510 * necessarily all registers and bits.
511 */
512typedef struct {
513 volatile uint32_t ISR;
514 volatile uint32_t ICR;
515 volatile uint32_t IER;
516 volatile uint32_t CFGR;
517 volatile uint32_t CR;
518 volatile uint32_t CMP;
519 volatile uint32_t ARR;
520 volatile uint32_t CNT;
521 volatile uint32_t OR;
522} wb32_lptim_t;
523
524/*===========================================================================*/
525/* Driver macros. */
526/*===========================================================================*/
527
528/*===========================================================================*/
529/* External declarations. */
530/*===========================================================================*/
531
532#endif /* WB32_TIM_H */
533
534/** @} */