diff options
Diffstat (limited to 'lib/chibios-contrib/os/hal/ports/WB32/LLD/TIMv1')
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 @@ | |||
1 | PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_st_lld.c | ||
2 | |||
3 | ifeq ($(USE_SMART_BUILD),yes) | ||
4 | ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),) | ||
5 | PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.c | ||
6 | endif | ||
7 | ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),) | ||
8 | PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.c | ||
9 | endif | ||
10 | ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),) | ||
11 | PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.c | ||
12 | endif | ||
13 | else | ||
14 | PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_gpt_lld.c | ||
15 | PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_icu_lld.c | ||
16 | PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/hal_pwm_lld.c | ||
17 | endif | ||
18 | |||
19 | PLATFORMINC_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__) | ||
42 | GPTDriver 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__) | ||
50 | GPTDriver 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__) | ||
58 | GPTDriver 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__) | ||
66 | GPTDriver 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 | */ | ||
91 | OSAL_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 | */ | ||
112 | OSAL_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 | */ | ||
133 | OSAL_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 | */ | ||
154 | OSAL_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 | */ | ||
174 | void 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 | */ | ||
208 | void 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 | */ | ||
298 | void 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 | */ | ||
354 | void 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 | */ | ||
382 | void 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 | */ | ||
404 | void 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 | */ | ||
426 | void 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 | */ | ||
212 | typedef uint32_t gptfreq_t; | ||
213 | |||
214 | /** | ||
215 | * @brief GPT counter type. | ||
216 | */ | ||
217 | typedef uint32_t gptcnt_t; | ||
218 | |||
219 | /** | ||
220 | * @brief Driver configuration structure. | ||
221 | * @note It could be empty on some architectures. | ||
222 | */ | ||
223 | typedef 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 | */ | ||
254 | struct 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__) | ||
325 | extern GPTDriver GPTD1; | ||
326 | #endif | ||
327 | |||
328 | #if WB32_GPT_USE_TIM2 && !defined(__DOXYGEN__) | ||
329 | extern GPTDriver GPTD2; | ||
330 | #endif | ||
331 | |||
332 | #if WB32_GPT_USE_TIM3 && !defined(__DOXYGEN__) | ||
333 | extern GPTDriver GPTD3; | ||
334 | #endif | ||
335 | |||
336 | #if WB32_GPT_USE_TIM4 && !defined(__DOXYGEN__) | ||
337 | extern GPTDriver GPTD4; | ||
338 | #endif | ||
339 | |||
340 | #ifdef __cplusplus | ||
341 | extern "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__) | ||
46 | ICUDriver 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__) | ||
54 | ICUDriver 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__) | ||
62 | ICUDriver 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__) | ||
70 | ICUDriver ICUD4; | ||
71 | #endif | ||
72 | |||
73 | /*===========================================================================*/ | ||
74 | /* Driver local variables and types. */ | ||
75 | /*===========================================================================*/ | ||
76 | |||
77 | /*===========================================================================*/ | ||
78 | /* Driver local functions. */ | ||
79 | /*===========================================================================*/ | ||
80 | |||
81 | static 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 | */ | ||
127 | OSAL_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 | */ | ||
144 | OSAL_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 | */ | ||
165 | OSAL_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 | */ | ||
186 | OSAL_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 | */ | ||
207 | OSAL_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 | */ | ||
227 | void 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 | */ | ||
261 | void 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 | */ | ||
421 | void 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 | */ | ||
478 | void 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 | */ | ||
500 | bool 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 | */ | ||
519 | void 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 | */ | ||
538 | void 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 | */ | ||
585 | void 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 | */ | ||
598 | void 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 | */ | ||
211 | typedef 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 | */ | ||
219 | typedef uint32_t icufreq_t; | ||
220 | |||
221 | /** | ||
222 | * @brief ICU channel type. | ||
223 | */ | ||
224 | typedef 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 | */ | ||
232 | typedef uint32_t icucnt_t; | ||
233 | |||
234 | /** | ||
235 | * @brief Driver configuration structure. | ||
236 | * @note It could be empty on some architectures. | ||
237 | */ | ||
238 | typedef 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 | */ | ||
283 | struct 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__) | ||
360 | extern ICUDriver ICUD1; | ||
361 | #endif | ||
362 | |||
363 | #if WB32_ICU_USE_TIM2 && !defined(__DOXYGEN__) | ||
364 | extern ICUDriver ICUD2; | ||
365 | #endif | ||
366 | |||
367 | #if WB32_ICU_USE_TIM3 && !defined(__DOXYGEN__) | ||
368 | extern ICUDriver ICUD3; | ||
369 | #endif | ||
370 | |||
371 | #if WB32_ICU_USE_TIM4 && !defined(__DOXYGEN__) | ||
372 | extern ICUDriver ICUD4; | ||
373 | #endif | ||
374 | |||
375 | #ifdef __cplusplus | ||
376 | extern "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__) | ||
42 | PWMDriver 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__) | ||
50 | PWMDriver 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__) | ||
58 | PWMDriver 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__) | ||
66 | PWMDriver 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 | */ | ||
94 | OSAL_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 | */ | ||
114 | OSAL_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 | */ | ||
135 | OSAL_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 | */ | ||
156 | OSAL_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 | */ | ||
177 | OSAL_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 | */ | ||
197 | void 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 | */ | ||
237 | void 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 | */ | ||
453 | void 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 | */ | ||
519 | void 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 | */ | ||
546 | void 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 | */ | ||
570 | void 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 | */ | ||
590 | void 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 | */ | ||
606 | void 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 | */ | ||
634 | void 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 | */ | ||
650 | void 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 | */ | ||
266 | typedef uint32_t pwmmode_t; | ||
267 | |||
268 | /** | ||
269 | * @brief Type of a PWM channel. | ||
270 | */ | ||
271 | typedef uint8_t pwmchannel_t; | ||
272 | |||
273 | /** | ||
274 | * @brief Type of a channels mask. | ||
275 | */ | ||
276 | typedef uint32_t pwmchnmsk_t; | ||
277 | |||
278 | /** | ||
279 | * @brief Type of a PWM counter. | ||
280 | */ | ||
281 | typedef uint32_t pwmcnt_t; | ||
282 | |||
283 | /** | ||
284 | * @brief Type of a PWM driver channel configuration structure. | ||
285 | */ | ||
286 | typedef 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 | */ | ||
303 | typedef 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 | */ | ||
350 | struct 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__) | ||
413 | extern PWMDriver PWMD1; | ||
414 | #endif | ||
415 | |||
416 | #if WB32_PWM_USE_TIM2 && !defined(__DOXYGEN__) | ||
417 | extern PWMDriver PWMD2; | ||
418 | #endif | ||
419 | |||
420 | #if WB32_PWM_USE_TIM3 && !defined(__DOXYGEN__) | ||
421 | extern PWMDriver PWMD3; | ||
422 | #endif | ||
423 | |||
424 | #if WB32_PWM_USE_TIM4 && !defined(__DOXYGEN__) | ||
425 | extern PWMDriver PWMD4; | ||
426 | #endif | ||
427 | |||
428 | #ifdef __cplusplus | ||
429 | extern "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 | */ | ||
155 | OSAL_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 | */ | ||
174 | void 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 | */ | ||
227 | void 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 | ||
186 | extern "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 | */ | ||
208 | static 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 | */ | ||
222 | static 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 | */ | ||
238 | static 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 | */ | ||
254 | static 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 | */ | ||
266 | static 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 | */ | ||
280 | static 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 | */ | ||
298 | static 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 | */ | ||
314 | static 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 | */ | ||
329 | static 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 | */ | ||
344 | static 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 | */ | ||
359 | static 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 | */ | ||
484 | typedef 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 | */ | ||
512 | typedef 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 | /** @} */ | ||