1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-03-12 wcx1024979076 first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "drv_pwm.h"
14
15 #ifdef BSP_USING_PWM
16
17 #define DBG_LEVEL DBG_LOG
18 #include <rtdbg.h>
19 #define LOG_TAG "DRV.PWM"
20
_pwm_set(rt_uint8_t channel,struct rt_pwm_configuration * configuration)21 static rt_err_t _pwm_set(rt_uint8_t channel, struct rt_pwm_configuration *configuration)
22 {
23 struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
24
25 uint32_t period_hz = 1000000000 / configuration->period;
26
27 struct bflb_pwm_v2_config_s pwm_config;
28
29 pwm_config.clk_source = BFLB_SYSTEM_XCLK;
30
31 pwm_config.clk_div = 40;
32
33 pwm_config.period = 1000000 / period_hz;
34
35 bflb_pwm_v2_init(pwm, &pwm_config);
36
37 struct bflb_pwm_v2_channel_config_s pwm_ch_config = {
38 .positive_polarity = PWM_POLARITY_ACTIVE_HIGH,
39 .negative_polarity = PWM_POLARITY_ACTIVE_HIGH,
40 .positive_stop_state = PWM_STATE_INACTIVE,
41 .negative_stop_state = PWM_STATE_ACTIVE,
42 .positive_brake_state = PWM_STATE_INACTIVE,
43 .negative_brake_state = PWM_STATE_INACTIVE,
44 .dead_time = 0,
45 };
46
47 bflb_pwm_v2_channel_init(pwm, channel, &pwm_ch_config);
48
49 bflb_pwm_v2_channel_set_threshold(pwm, channel, 0, configuration->pulse);
50
51 bflb_pwm_v2_channel_positive_stop(pwm, channel);
52 bflb_pwm_v2_channel_negative_stop(pwm, channel);
53 bflb_pwm_v2_stop(pwm);
54
55 bflb_pwm_v2_channel_positive_start(pwm, channel);
56 bflb_pwm_v2_channel_negative_start(pwm, channel);
57 bflb_pwm_v2_start(pwm);
58
59 return RT_EOK;
60 }
61
_pwm_get(rt_uint8_t channel,struct rt_pwm_configuration * configuration)62 static rt_err_t _pwm_get(rt_uint8_t channel, struct rt_pwm_configuration *configuration)
63 {
64 uint32_t reg_base, regval, tmp;
65 float period;
66
67 reg_base = bflb_device_get_by_name("pwm_v2_0")->reg_base;
68 regval = getreg32(reg_base + PWM_MC0_PERIOD_OFFSET);
69 tmp = (regval & PWM_PERIOD_MASK) >> PWM_PERIOD_SHIFT;
70 period = (float)tmp;
71
72 uint32_t period_hz = 1000000 / period;
73
74 regval = getreg32(reg_base + PWM_MC0_CH0_THRE_OFFSET + channel * 4);
75 uint16_t high_threhold = regval >> 16;
76 uint16_t low_threhold = regval;
77
78 configuration->period = 1000000000 / period_hz;
79
80 configuration->pulse = high_threhold;
81
82 return RT_EOK;
83 }
84
_pwm_control(struct rt_device_pwm * device,int cmd,void * arg)85 static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
86 {
87 struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
88
89 rt_uint32_t channel = 0;
90
91 channel = configuration->channel;
92
93 if (channel >= 4)
94 return -RT_EINVAL;
95
96 struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
97 switch (cmd)
98 {
99 case PWM_CMD_ENABLE:
100 bflb_pwm_v2_channel_positive_start(pwm, channel);
101 bflb_pwm_v2_channel_negative_start(pwm, channel);
102 return RT_EOK;
103 case PWM_CMD_DISABLE:
104 bflb_pwm_v2_channel_positive_stop(pwm, channel);
105 bflb_pwm_v2_channel_negative_stop(pwm, channel);
106 return RT_EOK;
107 case PWM_CMD_SET:
108 return _pwm_set(channel, configuration);
109 case PWM_CMD_GET:
110 return _pwm_get(channel, configuration);
111 default:
112 return -RT_EINVAL;
113 }
114 }
115
116 static struct rt_pwm_ops _pwm_ops =
117 {
118 _pwm_control
119 };
120 static struct rt_device_pwm pwm_device;
121
rt_hw_pwm_init(void)122 int rt_hw_pwm_init(void)
123 {
124 int result = RT_EOK;
125
126 struct bflb_device_s* gpio = bflb_device_get_by_name("gpio");
127 bflb_gpio_init(gpio, GPIO_PIN_8, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_1);
128 struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
129 bflb_pwm_v2_start(pwm);
130
131 result = rt_device_pwm_register(&pwm_device, "pwm", &_pwm_ops, 0);
132 if(result != RT_EOK)
133 {
134 LOG_E("pwm device register fail.");
135 }
136 return result;
137 }
138 INIT_DEVICE_EXPORT(rt_hw_pwm_init);
139
140 #endif /* BSP_USING_PWM */
141