1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-05-16     shelton      first version
9  * 2024-09-24     shelton      update driver
10  */
11 
12 #include "drv_common.h"
13 
14 #ifdef RT_USING_PWM
15 #include "drv_pwm.h"
16 #include <drivers/dev_pwm.h>
17 
18 //#define DRV_DEBUG
19 #define LOG_TAG                         "drv.pwm"
20 #include <drv_log.h>
21 
22 #define MAX_PERIOD                      65535
23 #define MIN_PERIOD                      3
24 #define MIN_PULSE                       2
25 
26 struct at32_pwm
27 {
28     struct rt_device_pwm pwm_device;
29     tmr_type* tmr_x;
30     rt_uint8_t channel;
31     char *name;
32 };
33 
34 enum
35 {
36 #ifdef BSP_USING_PWM1
37     PWM1_INDEX,
38 #endif
39 #ifdef BSP_USING_PWM2
40     PWM2_INDEX,
41 #endif
42 #ifdef BSP_USING_PWM3
43     PWM3_INDEX,
44 #endif
45 #ifdef BSP_USING_PWM4
46     PWM4_INDEX,
47 #endif
48 #ifdef BSP_USING_PWM5
49     PWM5_INDEX,
50 #endif
51 #ifdef BSP_USING_PWM6
52     PWM6_INDEX,
53 #endif
54 #ifdef BSP_USING_PWM7
55     PWM7_INDEX,
56 #endif
57 #ifdef BSP_USING_PWM8
58     PWM8_INDEX,
59 #endif
60 #ifdef BSP_USING_PWM9
61     PWM9_INDEX,
62 #endif
63 #ifdef BSP_USING_PWM10
64     PWM10_INDEX,
65 #endif
66 #ifdef BSP_USING_PWM11
67     PWM11_INDEX,
68 #endif
69 #ifdef BSP_USING_PWM12
70     PWM12_INDEX,
71 #endif
72 #ifdef BSP_USING_PWM13
73     PWM13_INDEX,
74 #endif
75 };
76 
77 static struct at32_pwm at32_pwm_obj[] =
78 {
79 #ifdef BSP_USING_PWM1
80     PWM1_CONFIG,
81 #endif
82 
83 #ifdef BSP_USING_PWM2
84     PWM2_CONFIG,
85 #endif
86 
87 #ifdef BSP_USING_PWM3
88     PWM3_CONFIG,
89 #endif
90 
91 #ifdef BSP_USING_PWM4
92     PWM4_CONFIG,
93 #endif
94 
95 #ifdef BSP_USING_PWM5
96     PWM5_CONFIG,
97 #endif
98 
99 #ifdef BSP_USING_PWM6
100     PWM6_CONFIG,
101 #endif
102 
103 #ifdef BSP_USING_PWM7
104     PWM7_CONFIG,
105 #endif
106 
107 #ifdef BSP_USING_PWM8
108     PWM8_CONFIG,
109 #endif
110 
111 #ifdef BSP_USING_PWM9
112     PWM9_CONFIG,
113 #endif
114 
115 #ifdef BSP_USING_PWM10
116     PWM10_CONFIG,
117 #endif
118 
119 #ifdef BSP_USING_PWM11
120     PWM11_CONFIG,
121 #endif
122 
123 #ifdef BSP_USING_PWM12
124     PWM12_CONFIG,
125 #endif
126 
127 #ifdef BSP_USING_PWM13
128     PWM13_CONFIG,
129 #endif
130 };
131 
132 static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg);
133 static struct rt_pwm_ops drv_ops =
134 {
135     drv_pwm_control
136 };
137 
tmr_pclk_get(rt_uint32_t * pclk1_doubler,rt_uint32_t * pclk2_doubler)138 static void tmr_pclk_get(rt_uint32_t *pclk1_doubler, rt_uint32_t *pclk2_doubler)
139 {
140     crm_clocks_freq_type  clocks_struct;
141 
142     *pclk1_doubler = 1;
143     *pclk2_doubler = 1;
144 
145     crm_clocks_freq_get(&clocks_struct);
146 
147     if(clocks_struct.ahb_freq != clocks_struct.apb1_freq)
148     {
149         *pclk1_doubler = 2;
150     }
151 
152     if(clocks_struct.ahb_freq != clocks_struct.apb2_freq)
153     {
154         *pclk2_doubler = 2;
155     }
156 }
157 
at32_hw_pwm_init(struct at32_pwm * instance)158 static rt_err_t at32_hw_pwm_init(struct at32_pwm *instance)
159 {
160     tmr_output_config_type tmr_oc_config_struct;
161     tmr_type *tmr_x = instance->tmr_x;
162 
163     at32_msp_tmr_init(tmr_x);
164 
165     tmr_base_init(tmr_x, 0, 0);
166     tmr_clock_source_div_set(tmr_x, TMR_CLOCK_DIV1);
167 
168     /* pwm mode configuration */
169     tmr_output_default_para_init(&tmr_oc_config_struct);
170     /* config pwm mode */
171     tmr_oc_config_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
172 
173     /* config tmr pwm output */
174     if(instance->channel & 0x01)
175     {
176         tmr_output_channel_config(tmr_x, TMR_SELECT_CHANNEL_1, &tmr_oc_config_struct);
177         tmr_output_channel_buffer_enable(tmr_x, TMR_SELECT_CHANNEL_1, TRUE);
178     }
179 
180     if(instance->channel & 0x02)
181     {
182         tmr_output_channel_config(tmr_x, TMR_SELECT_CHANNEL_2, &tmr_oc_config_struct);
183         tmr_output_channel_buffer_enable(tmr_x, TMR_SELECT_CHANNEL_2, TRUE);
184     }
185 
186     if(instance->channel & 0x04)
187     {
188         tmr_output_channel_config(tmr_x, TMR_SELECT_CHANNEL_3, &tmr_oc_config_struct);
189         tmr_output_channel_buffer_enable(tmr_x, TMR_SELECT_CHANNEL_3, TRUE);
190     }
191 
192     if(instance->channel & 0x08)
193     {
194         tmr_output_channel_config(tmr_x, TMR_SELECT_CHANNEL_4, &tmr_oc_config_struct);
195         tmr_output_channel_buffer_enable(tmr_x, TMR_SELECT_CHANNEL_4, TRUE);
196     }
197 
198     /* enable output */
199     tmr_output_enable(tmr_x, TRUE);
200     /* enable overflow request */
201     tmr_overflow_request_source_set(tmr_x, TRUE);
202 
203     return RT_EOK;
204 }
205 
drv_pwm_enable(tmr_type * tmr_x,struct rt_pwm_configuration * configuration,rt_bool_t enable)206 static rt_err_t drv_pwm_enable(tmr_type* tmr_x, struct rt_pwm_configuration *configuration, rt_bool_t enable)
207 {
208     /* get the value of channel */
209     rt_uint32_t channel = configuration->channel;
210 
211     if (!configuration->complementary)
212     {
213         if (!enable)
214         {
215             if(channel == 1)
216             {
217                tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_1, FALSE);
218             }
219             else if(channel == 2)
220             {
221               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_2, FALSE);
222             }
223             else if(channel == 3)
224             {
225               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_3, FALSE);
226             }
227             else if(channel == 4)
228             {
229               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_4, FALSE);
230             }
231         }
232         else
233         {
234             if(channel == 1)
235             {
236               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_1, TRUE);
237             }
238             else if(channel == 2)
239             {
240               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_2, TRUE);
241             }
242             else if(channel == 3)
243             {
244               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_3, TRUE);
245             }
246             else if(channel == 4)
247             {
248               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_4, TRUE);
249             }
250         }
251     }
252     else
253     {
254         if (!enable)
255         {
256             if(channel == 1)
257             {
258                tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_1C, FALSE);
259             }
260             else if(channel == 2)
261             {
262               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_2C, FALSE);
263             }
264             else if(channel == 3)
265             {
266               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_3C, FALSE);
267             }
268         }
269         else
270         {
271             if(channel == 1)
272             {
273               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_1C, TRUE);
274             }
275             else if(channel == 2)
276             {
277               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_2C, TRUE);
278             }
279             else if(channel == 3)
280             {
281               tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_3C, TRUE);
282             }
283         }
284     }
285 
286     /* tmr_x enable counter */
287     tmr_counter_enable(tmr_x, TRUE);
288 
289     return RT_EOK;
290 }
291 
drv_pwm_get(tmr_type * tmr_x,struct rt_pwm_configuration * configuration)292 static rt_err_t drv_pwm_get(tmr_type* tmr_x, struct rt_pwm_configuration *configuration)
293 {
294     crm_clocks_freq_type clocks_struct;
295     rt_uint32_t pr, div, c1dt, c2dt, c3dt, c4dt, tmr_clock;
296     rt_uint32_t pclk1_doubler = 0, pclk2_doubler = 0;
297     rt_uint32_t channel = configuration->channel;
298 
299     pr = tmr_x->pr;
300     div = tmr_x->div;
301     c1dt = tmr_x->c1dt;
302     c2dt = tmr_x->c2dt;
303     c3dt = tmr_x->c3dt;
304     c4dt = tmr_x->c4dt;
305 
306     tmr_pclk_get(&pclk1_doubler, &pclk2_doubler);
307     crm_clocks_freq_get(&clocks_struct);
308 
309     if(
310 #if defined (TMR1)
311     (tmr_x == TMR1)
312 #endif
313 #if defined (TMR8)
314     || (tmr_x == TMR8)
315 #endif
316 #if defined (TMR9)
317     || (tmr_x == TMR9)
318 #endif
319 #if defined (TMR10)
320     || (tmr_x == TMR10)
321 #endif
322 #if defined (TMR11)
323     || (tmr_x == TMR11)
324 #endif
325     )
326     {
327         tmr_clock = clocks_struct.apb2_freq * pclk2_doubler;
328     }
329     else
330     {
331         tmr_clock = clocks_struct.apb1_freq * pclk1_doubler;
332     }
333 
334     /* convert nanosecond to frequency and duty cycle. */
335     tmr_clock /= 1000000UL;
336     configuration->period = (pr + 1) * (div + 1) * 1000UL / tmr_clock;
337 
338     if(channel == 1)
339         configuration->pulse = (c1dt) * (div + 1) * 1000UL / tmr_clock;
340     if(channel == 2)
341         configuration->pulse = (c2dt) * (div + 1) * 1000UL / tmr_clock;
342     if(channel == 3)
343         configuration->pulse = (c3dt) * (div + 1) * 1000UL / tmr_clock;
344     if(channel == 4)
345         configuration->pulse = (c4dt) * (div + 1) * 1000UL / tmr_clock;
346 
347     return RT_EOK;
348 }
349 
drv_pwm_set(tmr_type * tmr_x,struct rt_pwm_configuration * configuration)350 static rt_err_t drv_pwm_set(tmr_type* tmr_x, struct rt_pwm_configuration *configuration)
351 {
352     crm_clocks_freq_type clocks_struct;
353     tmr_channel_select_type channel_select;
354     rt_uint32_t period, pulse, channel, psc, tmr_clock;
355     rt_uint32_t pclk1_doubler = 0, pclk2_doubler = 0;
356 
357     tmr_pclk_get(&pclk1_doubler, &pclk2_doubler);
358     crm_clocks_freq_get(&clocks_struct);
359 
360     if(
361 #if defined (TMR1)
362     (tmr_x == TMR1)
363 #endif
364 #if defined (TMR8)
365     || (tmr_x == TMR8)
366 #endif
367 #if defined (TMR9)
368     || (tmr_x == TMR9)
369 #endif
370 #if defined (TMR10)
371     || (tmr_x == TMR10)
372 #endif
373 #if defined (TMR11)
374     || (tmr_x == TMR11)
375 #endif
376     )
377     {
378         tmr_clock = clocks_struct.apb2_freq * pclk2_doubler;
379     }
380     else
381     {
382         tmr_clock = clocks_struct.apb1_freq * pclk1_doubler;
383     }
384 
385     /* convert nanosecond to frequency and duty cycle. */
386     tmr_clock /= 1000000UL;
387     /* calculate pwm period */
388     period = (unsigned long long)configuration->period * tmr_clock / 1000ULL;;
389     psc = period / MAX_PERIOD + 1;
390     period = period / psc;
391     tmr_div_value_set(tmr_x, psc - 1);
392 
393     if(period < MIN_PERIOD)
394     {
395         period = MIN_PERIOD;
396     }
397 
398     tmr_period_value_set(tmr_x, period - 1);
399 
400     /* calculate pulse width */
401     pulse = (unsigned long long)configuration->pulse * tmr_clock / psc / 1000ULL;
402     if(pulse < MIN_PULSE)
403     {
404         pulse = MIN_PULSE;
405     }
406     else if(pulse >= period)
407     {
408         pulse = period + 1;
409     }
410 
411     /* get channel parameter */
412     channel = configuration->channel;
413     if(channel == 1)
414     {
415         channel_select = TMR_SELECT_CHANNEL_1;
416     }
417     else if(channel == 2)
418     {
419         channel_select = TMR_SELECT_CHANNEL_2;
420     }
421     else if(channel == 3)
422     {
423         channel_select = TMR_SELECT_CHANNEL_3;
424     }
425     else if(channel == 4)
426     {
427         channel_select = TMR_SELECT_CHANNEL_4;
428     }
429 
430     tmr_channel_value_set(tmr_x, channel_select, pulse);
431 
432     /* if you want the pwm setting to take effect immediately,
433     please uncommon the following code, but it will cause the last pwm cycle not complete. */
434     //tmr_counter_value_set(tmr_x, 0);
435     //tmr_x->swevt_bit.ovfswtr = TRUE;
436 
437     return RT_EOK;
438 }
439 
drv_pwm_set_period(tmr_type * tmr_x,struct rt_pwm_configuration * configuration)440 static rt_err_t drv_pwm_set_period(tmr_type* tmr_x, struct rt_pwm_configuration *configuration)
441 {
442     crm_clocks_freq_type clocks_struct;
443     rt_uint32_t period, psc, tmr_clock;
444     rt_uint32_t pclk1_doubler = 0, pclk2_doubler = 0;
445 
446     tmr_pclk_get(&pclk1_doubler, &pclk2_doubler);
447     crm_clocks_freq_get(&clocks_struct);
448 
449     if(
450 #if defined (TMR1)
451     (tmr_x == TMR1)
452 #endif
453 #if defined (TMR8)
454     || (tmr_x == TMR8)
455 #endif
456 #if defined (TMR9)
457     || (tmr_x == TMR9)
458 #endif
459 #if defined (TMR10)
460     || (tmr_x == TMR10)
461 #endif
462 #if defined (TMR11)
463     || (tmr_x == TMR11)
464 #endif
465     )
466     {
467         tmr_clock = clocks_struct.apb2_freq * pclk2_doubler;
468     }
469     else
470     {
471         tmr_clock = clocks_struct.apb1_freq * pclk1_doubler;
472     }
473 
474     /* convert nanosecond to frequency and duty cycle. */
475     tmr_clock /= 1000000UL;
476     /* calculate pwm period */
477     period = (unsigned long long)configuration->period * tmr_clock / 1000ULL;;
478     psc = period / MAX_PERIOD + 1;
479     period = period / psc;
480     tmr_div_value_set(tmr_x, psc - 1);
481 
482     if(period < MIN_PERIOD)
483     {
484         period = MIN_PERIOD;
485     }
486 
487     tmr_period_value_set(tmr_x, period - 1);
488 
489     return RT_EOK;
490 }
491 
drv_pwm_set_pulse(tmr_type * tmr_x,struct rt_pwm_configuration * configuration)492 static rt_err_t drv_pwm_set_pulse(tmr_type* tmr_x, struct rt_pwm_configuration *configuration)
493 {
494     crm_clocks_freq_type clocks_struct;
495     tmr_channel_select_type channel_select;
496     rt_uint32_t period, pulse, channel, psc, tmr_clock;
497     rt_uint32_t pclk1_doubler = 0, pclk2_doubler = 0;
498 
499     tmr_pclk_get(&pclk1_doubler, &pclk2_doubler);
500     crm_clocks_freq_get(&clocks_struct);
501 
502     if(
503 #if defined (TMR1)
504     (tmr_x == TMR1)
505 #endif
506 #if defined (TMR8)
507     || (tmr_x == TMR8)
508 #endif
509 #if defined (TMR9)
510     || (tmr_x == TMR9)
511 #endif
512 #if defined (TMR10)
513     || (tmr_x == TMR10)
514 #endif
515 #if defined (TMR11)
516     || (tmr_x == TMR11)
517 #endif
518     )
519     {
520         tmr_clock = clocks_struct.apb2_freq * pclk2_doubler;
521     }
522     else
523     {
524         tmr_clock = clocks_struct.apb1_freq * pclk1_doubler;
525     }
526 
527     /* convert nanosecond to frequency and duty cycle. */
528     tmr_clock /= 1000000UL;
529     /* calculate pwm period */
530     period = (unsigned long long)configuration->period * tmr_clock / 1000ULL;;
531     psc = period / MAX_PERIOD + 1;
532 
533     /* calculate pulse width */
534     pulse = (unsigned long long)configuration->pulse * tmr_clock / psc / 1000ULL;
535     if(pulse < MIN_PULSE)
536     {
537         pulse = MIN_PULSE;
538     }
539     else if(pulse >= period)
540     {
541         pulse = period + 1;
542     }
543 
544     /* get channel parameter */
545     channel = configuration->channel;
546     if(channel == 1)
547     {
548         channel_select = TMR_SELECT_CHANNEL_1;
549     }
550     else if(channel == 2)
551     {
552         channel_select = TMR_SELECT_CHANNEL_2;
553     }
554     else if(channel == 3)
555     {
556         channel_select = TMR_SELECT_CHANNEL_3;
557     }
558     else if(channel == 4)
559     {
560         channel_select = TMR_SELECT_CHANNEL_4;
561     }
562 
563     tmr_channel_value_set(tmr_x, channel_select, pulse);
564 
565     return RT_EOK;
566 }
567 
drv_pwm_control(struct rt_device_pwm * device,int cmd,void * arg)568 static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
569 {
570     struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
571     tmr_type *tmr_x = (tmr_type *)device->parent.user_data;
572 
573     switch (cmd)
574     {
575     case PWM_CMD_ENABLE:
576         return drv_pwm_enable(tmr_x, configuration, RT_TRUE);
577     case PWM_CMD_DISABLE:
578         return drv_pwm_enable(tmr_x, configuration, RT_FALSE);
579     case PWM_CMD_SET:
580         return drv_pwm_set(tmr_x, configuration);
581     case PWM_CMD_SET_PERIOD:
582         return drv_pwm_set_period(tmr_x, configuration);
583     case PWM_CMD_SET_PULSE:
584         return drv_pwm_set_pulse(tmr_x, configuration);
585     case PWM_CMD_GET:
586         return drv_pwm_get(tmr_x, configuration);
587     default:
588         return -RT_EINVAL;
589     }
590 }
591 
pwm_get_channel(void)592 static void pwm_get_channel(void)
593 {
594 #ifdef BSP_USING_PWM1_CH1
595     at32_pwm_obj[PWM1_INDEX].channel |= 1 << 0;
596 #endif
597 #ifdef BSP_USING_PWM1_CH2
598     at32_pwm_obj[PWM1_INDEX].channel |= 1 << 1;
599 #endif
600 #ifdef BSP_USING_PWM1_CH3
601     at32_pwm_obj[PWM1_INDEX].channel |= 1 << 2;
602 #endif
603 #ifdef BSP_USING_PWM1_CH4
604     at32_pwm_obj[PWM1_INDEX].channel |= 1 << 3;
605 #endif
606 #ifdef BSP_USING_PWM2_CH1
607     at32_pwm_obj[PWM2_INDEX].channel |= 1 << 0;
608 #endif
609 #ifdef BSP_USING_PWM2_CH2
610     at32_pwm_obj[PWM2_INDEX].channel |= 1 << 1;
611 #endif
612 #ifdef BSP_USING_PWM2_CH3
613     at32_pwm_obj[PWM2_INDEX].channel |= 1 << 2;
614 #endif
615 #ifdef BSP_USING_PWM2_CH4
616     at32_pwm_obj[PWM2_INDEX].channel |= 1 << 3;
617 #endif
618 #ifdef BSP_USING_PWM3_CH1
619     at32_pwm_obj[PWM3_INDEX].channel |= 1 << 0;
620 #endif
621 #ifdef BSP_USING_PWM3_CH2
622     at32_pwm_obj[PWM3_INDEX].channel |= 1 << 1;
623 #endif
624 #ifdef BSP_USING_PWM3_CH3
625     at32_pwm_obj[PWM3_INDEX].channel |= 1 << 2;
626 #endif
627 #ifdef BSP_USING_PWM3_CH4
628     at32_pwm_obj[PWM3_INDEX].channel |= 1 << 3;
629 #endif
630 #ifdef BSP_USING_PWM4_CH1
631     at32_pwm_obj[PWM4_INDEX].channel |= 1 << 0;
632 #endif
633 #ifdef BSP_USING_PWM4_CH2
634     at32_pwm_obj[PWM4_INDEX].channel |= 1 << 1;
635 #endif
636 #ifdef BSP_USING_PWM4_CH3
637     at32_pwm_obj[PWM4_INDEX].channel |= 1 << 2;
638 #endif
639 #ifdef BSP_USING_PWM4_CH4
640     at32_pwm_obj[PWM4_INDEX].channel |= 1 << 3;
641 #endif
642 #ifdef BSP_USING_PWM5_CH1
643     at32_pwm_obj[PWM5_INDEX].channel |= 1 << 0;
644 #endif
645 #ifdef BSP_USING_PWM5_CH2
646     at32_pwm_obj[PWM5_INDEX].channel |= 1 << 1;
647 #endif
648 #ifdef BSP_USING_PWM5_CH3
649     at32_pwm_obj[PWM5_INDEX].channel |= 1 << 2;
650 #endif
651 #ifdef BSP_USING_PWM5_CH4
652     at32_pwm_obj[PWM5_INDEX].channel |= 1 << 3;
653 #endif
654 #ifdef BSP_USING_PWM6_CH1
655     at32_pwm_obj[PWM6_INDEX].channel |= 1 << 0;
656 #endif
657 #ifdef BSP_USING_PWM6_CH2
658     at32_pwm_obj[PWM6_INDEX].channel |= 1 << 1;
659 #endif
660 #ifdef BSP_USING_PWM6_CH3
661     at32_pwm_obj[PWM6_INDEX].channel |= 1 << 2;
662 #endif
663 #ifdef BSP_USING_PWM6_CH4
664     at32_pwm_obj[PWM6_INDEX].channel |= 1 << 3;
665 #endif
666 #ifdef BSP_USING_PWM7_CH1
667     at32_pwm_obj[PWM7_INDEX].channel |= 1 << 0;
668 #endif
669 #ifdef BSP_USING_PWM7_CH2
670     at32_pwm_obj[PWM7_INDEX].channel |= 1 << 1;
671 #endif
672 #ifdef BSP_USING_PWM7_CH3
673     at32_pwm_obj[PWM7_INDEX].channel |= 1 << 2;
674 #endif
675 #ifdef BSP_USING_PWM7_CH4
676     at32_pwm_obj[PWM7_INDEX].channel |= 1 << 3;
677 #endif
678 #ifdef BSP_USING_PWM8_CH1
679     at32_pwm_obj[PWM8_INDEX].channel |= 1 << 0;
680 #endif
681 #ifdef BSP_USING_PWM8_CH2
682     at32_pwm_obj[PWM8_INDEX].channel |= 1 << 1;
683 #endif
684 #ifdef BSP_USING_PWM8_CH3
685     at32_pwm_obj[PWM8_INDEX].channel |= 1 << 2;
686 #endif
687 #ifdef BSP_USING_PWM8_CH4
688     at32_pwm_obj[PWM8_INDEX].channel |= 1 << 3;
689 #endif
690 #ifdef BSP_USING_PWM9_CH1
691     at32_pwm_obj[PWM9_INDEX].channel |= 1 << 0;
692 #endif
693 #ifdef BSP_USING_PWM9_CH2
694     at32_pwm_obj[PWM9_INDEX].channel |= 1 << 1;
695 #endif
696 #ifdef BSP_USING_PWM9_CH3
697     at32_pwm_obj[PWM9_INDEX].channel |= 1 << 2;
698 #endif
699 #ifdef BSP_USING_PWM9_CH4
700     at32_pwm_obj[PWM9_INDEX].channel |= 1 << 3;
701 #endif
702 #ifdef BSP_USING_PWM12_CH1
703     at32_pwm_obj[PWM12_INDEX].channel |= 1 << 0;
704 #endif
705 #ifdef BSP_USING_PWM12_CH2
706     at32_pwm_obj[PWM12_INDEX].channel |= 1 << 1;
707 #endif
708 }
709 
rt_hw_pwm_init(void)710 static int rt_hw_pwm_init(void)
711 {
712     int i = 0;
713     int result = RT_EOK;
714 
715     pwm_get_channel();
716 
717     for(i = 0; i < sizeof(at32_pwm_obj) / sizeof(at32_pwm_obj[0]); i++)
718     {
719         if(at32_hw_pwm_init(&at32_pwm_obj[i]) != RT_EOK)
720         {
721             LOG_E("%s init failed", at32_pwm_obj[i].name);
722             result = -RT_ERROR;
723             goto __exit;
724         }
725         else
726         {
727             if(rt_device_pwm_register(&at32_pwm_obj[i].pwm_device, at32_pwm_obj[i].name, &drv_ops, at32_pwm_obj[i].tmr_x) == RT_EOK)
728             {
729                 LOG_D("%s register success", at32_pwm_obj[i].name);
730             }
731             else
732             {
733                 LOG_D("%s register failed", at32_pwm_obj[i].name);
734                 result = -RT_ERROR;
735             }
736         }
737     }
738 __exit:
739     return result;
740 }
741 
742 INIT_BOARD_EXPORT(rt_hw_pwm_init);
743 
744 #endif /* RT_USING_PWM */
745