1 /*
2 * Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Change Logs:
19 * Date Author Notes
20 * 2019-03-11 wangyq the first version
21 * 2019-11-01 wangyq update libraries
22 * 2021-04-20 liuhy the second version
23 */
24
25 #include <rthw.h>
26 #include <rtthread.h>
27 #include <rtdevice.h>
28 #include <board.h>
29 #include "es_conf_info_pwm.h"
30
31
32 #ifdef RT_USING_PWM
33
pwm_set_duty(timer_handle_t * timer_initstruct,timer_channel_t ch,uint32_t ns)34 static void pwm_set_duty(timer_handle_t *timer_initstruct, timer_channel_t ch, uint32_t ns)
35 {
36 uint64_t tmp = (uint64_t)ald_cmu_get_pclk1_clock() * ns / 1000000000 /
37 (timer_initstruct->init.prescaler + 1);
38
39 if (ch == TIMER_CHANNEL_1)
40 WRITE_REG(timer_initstruct->perh->CCVAL1, (uint32_t)tmp);
41 else if (ch == TIMER_CHANNEL_2)
42 WRITE_REG(timer_initstruct->perh->CCVAL2, (uint32_t)tmp);
43 else if (ch == TIMER_CHANNEL_3)
44 WRITE_REG(timer_initstruct->perh->CCVAL3, (uint32_t)tmp);
45 else if (ch == TIMER_CHANNEL_4)
46 WRITE_REG(timer_initstruct->perh->CCVAL4, (uint32_t)tmp);
47 }
48
es32f0_pwm_control(struct rt_device_pwm * device,int cmd,void * arg)49 static rt_err_t es32f0_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
50 {
51 rt_err_t ret = RT_EOK;
52 uint64_t _arr,bus_speed,tmp;
53 uint32_t _maxcnt,_ccep_ch_en = 0U;
54 timer_channel_t pwm_channel;
55 timer_oc_init_t tim_ocinit;
56 timer_handle_t *timer_initstruct = (timer_handle_t *)device->parent.user_data;
57 struct rt_pwm_configuration *cfg = (struct rt_pwm_configuration *)arg;
58
59 RT_ASSERT(timer_initstruct != RT_NULL);
60
61 /* select pwm output channel */
62 if (1 == cfg->channel)
63 {
64 pwm_channel = TIMER_CHANNEL_1;
65 _ccep_ch_en = timer_initstruct->perh->CCEP & TIMER_CCEP_CC1EN_MSK;
66 }
67 else if (2 == cfg->channel)
68 {
69 pwm_channel = TIMER_CHANNEL_2;
70 _ccep_ch_en = timer_initstruct->perh->CCEP & TIMER_CCEP_CC2EN_MSK;
71 }
72 else if (3 == cfg->channel)
73 {
74 pwm_channel = TIMER_CHANNEL_3;
75 _ccep_ch_en = timer_initstruct->perh->CCEP & TIMER_CCEP_CC3EN_MSK;
76 }
77 else if (4 == cfg->channel)
78 {
79 pwm_channel = TIMER_CHANNEL_4;
80 _ccep_ch_en = timer_initstruct->perh->CCEP & TIMER_CCEP_CC4EN_MSK;
81 }
82 else
83 return -RT_EINVAL;
84
85 switch (cmd)
86 {
87 case PWM_CMD_ENABLE:
88 ald_timer_pwm_start(timer_initstruct, pwm_channel);
89 break;
90
91 case PWM_CMD_DISABLE:
92 ald_timer_pwm_stop(timer_initstruct, pwm_channel);
93 break;
94
95 case PWM_CMD_SET:
96
97 /*当通道没开的时候:关通道,设置输出模式和极性,初始化通道*/
98 if(!_ccep_ch_en)
99 {
100 tim_ocinit.oc_mode = ES_PWM_OC_MODE;
101 tim_ocinit.oc_polarity = ES_PWM_OC_POLARITY;
102 tim_ocinit.oc_fast_en = DISABLE;
103 tim_ocinit.ocn_polarity = TIMER_OCN_POLARITY_HIGH;
104 tim_ocinit.ocn_idle = TIMER_OCN_IDLE_RESET;
105 tim_ocinit.oc_idle = TIMER_OC_IDLE_RESET;
106 ald_timer_oc_config_channel(timer_initstruct, &tim_ocinit, pwm_channel);
107 }
108
109 bus_speed = (uint64_t)ald_cmu_get_pclk1_clock();
110
111 /*外设的计数器最大值*/
112 _maxcnt = 0xFFFF;
113
114 /*当最大分频 <= _maxcnt时:估计大概的分频,加快速度 */
115 tmp = bus_speed * (cfg->period)/1000000000/_maxcnt;
116 timer_initstruct->init.prescaler = (tmp > 2U) ? (tmp - 2U) : 0U ; /*bus_speed < 500000000*/
117
118 /* count registers max , auto adjust prescaler */
119 do
120 {
121 _arr = bus_speed * (cfg->period) / 1000000000 /(++timer_initstruct->init.prescaler);
122
123 }
124 while (_arr > _maxcnt);
125
126 WRITE_REG(timer_initstruct->perh->AR, (uint32_t)_arr);
127 timer_initstruct->init.period = (uint32_t)_arr;
128
129 /* update prescaler */
130 WRITE_REG(timer_initstruct->perh->PRES, --timer_initstruct->init.prescaler);
131
132 pwm_set_duty(timer_initstruct, pwm_channel, cfg->pulse);
133
134 break;
135
136 case PWM_CMD_GET:
137 cfg->pulse = ald_timer_read_capture_value(timer_initstruct, pwm_channel) * 100 /
138 READ_REG(timer_initstruct->perh->AR);
139 break;
140
141 default:
142 break;
143 }
144 return ret;
145 }
146
147 const static struct rt_pwm_ops es32f0_pwm_ops =
148 {
149 es32f0_pwm_control
150 };
151
rt_hw_pwm_init(void)152 int rt_hw_pwm_init(void)
153 {
154 rt_err_t ret = RT_EOK;
155 gpio_init_t gpio_initstructure;
156
157 gpio_initstructure.mode = GPIO_MODE_OUTPUT;
158 gpio_initstructure.odos = GPIO_PUSH_PULL;
159 gpio_initstructure.pupd = GPIO_PUSH_UP;
160 gpio_initstructure.odrv = GPIO_OUT_DRIVE_NORMAL;
161 gpio_initstructure.flt = GPIO_FILTER_DISABLE;
162 gpio_initstructure.type = GPIO_TYPE_TTL;
163
164 #ifdef BSP_USING_AD16C4T0_PWM /* 4 channels */
165 static struct rt_device_pwm ad16c4t0_pwm_dev;
166 static timer_handle_t ad16c4t0_timer_initstruct;
167
168 ad16c4t0_timer_initstruct.perh = AD16C4T0;
169 ald_timer_pwm_init(&ad16c4t0_timer_initstruct);
170
171 /* gpio initialization */
172
173 #if defined(ES_AD16C4T0_CH1_GPIO_FUNC)&&defined(ES_AD16C4T0_CH1_GPIO_PORT)&&defined(ES_AD16C4T0_CH1_GPIO_PIN)
174 gpio_initstructure.func = ES_AD16C4T0_CH1_GPIO_FUNC;
175 ald_gpio_init(ES_AD16C4T0_CH1_GPIO_PORT, ES_AD16C4T0_CH1_GPIO_PIN, &gpio_initstructure);
176 #endif
177
178 #if defined(ES_AD16C4T0_CH2_GPIO_FUNC)&&defined(ES_AD16C4T0_CH2_GPIO_PORT)&&defined(ES_AD16C4T0_CH2_GPIO_PIN)
179 gpio_initstructure.func = ES_AD16C4T0_CH2_GPIO_FUNC;
180 ald_gpio_init(ES_AD16C4T0_CH2_GPIO_PORT, ES_AD16C4T0_CH2_GPIO_PIN, &gpio_initstructure);
181 #endif
182
183 #if defined(ES_AD16C4T0_CH3_GPIO_FUNC)&&defined(ES_AD16C4T0_CH3_GPIO_PORT)&&defined(ES_AD16C4T0_CH3_GPIO_FUNC)
184 gpio_initstructure.func = ES_AD16C4T0_CH3_GPIO_FUNC;
185 ald_gpio_init(ES_AD16C4T0_CH3_GPIO_PORT, ES_AD16C4T0_CH3_GPIO_PIN, &gpio_initstructure);
186 #endif
187
188 #if defined(ES_AD16C4T0_CH4_GPIO_FUNC)&&defined(ES_AD16C4T0_CH4_GPIO_PORT)&&defined(ES_AD16C4T0_CH4_GPIO_PIN)
189 gpio_initstructure.func = ES_AD16C4T0_CH4_GPIO_FUNC;
190 ald_gpio_init(ES_AD16C4T0_CH4_GPIO_PORT, ES_AD16C4T0_CH4_GPIO_PIN, &gpio_initstructure);
191 #endif
192
193 ret = rt_device_pwm_register(&ad16c4t0_pwm_dev, ES_DEVICE_NAME_AD16C4T0_PWM, &es32f0_pwm_ops,
194 &ad16c4t0_timer_initstruct);
195 #endif
196
197 #ifdef BSP_USING_GP16C4T0_PWM /* 4 channels */
198 static struct rt_device_pwm gp16c4t0_pwm_dev;
199 static timer_handle_t gp16c4t0_timer_initstruct;
200
201 gp16c4t0_timer_initstruct.perh = GP16C4T0;
202 ald_timer_pwm_init(&gp16c4t0_timer_initstruct);
203
204 /* gpio initialization */
205
206 #if defined(ES_GP16C4T0_CH1_GPIO_FUNC)&&defined(ES_GP16C4T0_CH1_GPIO_PORT)&&defined(ES_GP16C4T0_CH1_GPIO_PIN)
207 gpio_initstructure.func = ES_GP16C4T0_CH1_GPIO_FUNC;
208 ald_gpio_init(ES_GP16C4T0_CH1_GPIO_PORT, ES_GP16C4T0_CH1_GPIO_PIN, &gpio_initstructure);
209 #endif
210
211 #if defined(ES_GP16C4T0_CH2_GPIO_FUNC)&&defined(ES_GP16C4T0_CH2_GPIO_PORT)&&defined(ES_GP16C4T0_CH2_GPIO_PIN)
212 gpio_initstructure.func = ES_GP16C4T0_CH2_GPIO_FUNC;
213 ald_gpio_init(ES_GP16C4T0_CH2_GPIO_PORT, ES_GP16C4T0_CH2_GPIO_PIN, &gpio_initstructure);
214 #endif
215
216 #if defined(ES_GP16C4T0_CH3_GPIO_FUNC)&&defined(ES_GP16C4T0_CH3_GPIO_PORT)&&defined(ES_GP16C4T0_CH3_GPIO_PIN)
217 gpio_initstructure.func = ES_GP16C4T0_CH3_GPIO_FUNC;
218 ald_gpio_init(ES_GP16C4T0_CH3_GPIO_PORT, ES_GP16C4T0_CH3_GPIO_PIN, &gpio_initstructure);
219 #endif
220
221 #if defined(ES_GP16C4T0_CH4_GPIO_FUNC)&&defined(ES_GP16C4T0_CH4_GPIO_PORT)&&defined(ES_GP16C4T0_CH4_GPIO_PIN)
222 gpio_initstructure.func = ES_GP16C4T0_CH4_GPIO_FUNC;
223 ald_gpio_init(ES_GP16C4T0_CH4_GPIO_PORT, ES_GP16C4T0_CH4_GPIO_PIN, &gpio_initstructure);
224 #endif
225
226 ret = rt_device_pwm_register(&gp16c4t0_pwm_dev, ES_DEVICE_NAME_GP16C4T0_PWM, &es32f0_pwm_ops,
227 &gp16c4t0_timer_initstruct);
228 #endif
229
230
231 #ifdef BSP_USING_GP16C2T0_PWM /* 2 channels */
232 static struct rt_device_pwm gp16c2t0_pwm_dev;
233 static timer_handle_t gp16c2t0_timer_initstruct;
234
235 gp16c2t0_timer_initstruct.perh = GP16C2T0;
236 ald_timer_pwm_init(&gp16c2t0_timer_initstruct);
237
238 /* gpio initialization */
239
240 #if defined(ES_GP16C2T0_CH1_GPIO_FUNC)&&defined(ES_GP16C2T0_CH1_GPIO_PORT)&&defined(ES_GP16C2T0_CH1_GPIO_PIN)
241 gpio_initstructure.func = ES_GP16C2T0_CH1_GPIO_FUNC;
242 ald_gpio_init(ES_GP16C2T0_CH1_GPIO_PORT, ES_GP16C2T0_CH1_GPIO_PIN, &gpio_initstructure);
243 #endif
244
245 #if defined(ES_GP16C2T0_CH2_GPIO_FUNC)&&defined(ES_GP16C2T0_CH2_GPIO_PORT)&&defined(ES_GP16C2T0_CH2_GPIO_PIN)
246 gpio_initstructure.func = ES_GP16C2T0_CH2_GPIO_FUNC;
247 ald_gpio_init(ES_GP16C2T0_CH2_GPIO_PORT, ES_GP16C2T0_CH2_GPIO_PIN, &gpio_initstructure);
248 #endif
249
250 ret = rt_device_pwm_register(&gp16c2t0_pwm_dev, ES_DEVICE_NAME_GP16C2T0_PWM, &es32f0_pwm_ops,
251 &gp16c2t0_timer_initstruct);
252 #endif
253
254
255 #ifdef BSP_USING_GP16C2T1_PWM /* 2 channels */
256 static struct rt_device_pwm gp16c2t1_pwm_dev;
257 static timer_handle_t gp16c2t1_timer_initstruct;
258
259 gp16c2t1_timer_initstruct.perh = GP16C2T1;
260 ald_timer_pwm_init(&gp16c2t1_timer_initstruct);
261
262 /* gpio initialization */
263
264 #if defined(ES_GP16C2T1_CH1_GPIO_FUNC)&&defined(ES_GP16C2T1_CH1_GPIO_PORT)&&defined(ES_GP16C2T1_CH1_GPIO_PIN)
265 gpio_initstructure.func = ES_GP16C2T1_CH1_GPIO_FUNC;
266 ald_gpio_init(ES_GP16C2T1_CH1_GPIO_PORT, ES_GP16C2T1_CH1_GPIO_PIN, &gpio_initstructure);
267 #endif
268
269 #if defined(ES_GP16C2T1_CH2_GPIO_FUNC)&&defined(ES_GP16C2T1_CH2_GPIO_PORT)&&defined(ES_GP16C2T1_CH2_GPIO_PIN)
270 gpio_initstructure.func = ES_GP16C2T1_CH2_GPIO_FUNC;
271 ald_gpio_init(ES_GP16C2T1_CH2_GPIO_PORT, ES_GP16C2T1_CH2_GPIO_PIN, &gpio_initstructure);
272 #endif
273
274 ret = rt_device_pwm_register(&gp16c2t1_pwm_dev, ES_DEVICE_NAME_GP16C2T1_PWM, &es32f0_pwm_ops,
275 &gp16c2t1_timer_initstruct);
276 #endif
277
278
279
280 return ret;
281 }
282 INIT_DEVICE_EXPORT(rt_hw_pwm_init);
283
284 #endif
285