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(ald_timer_handle_t * timer_initstruct,ald_timer_channel_t ch,uint32_t ns)34 static void pwm_set_duty(ald_timer_handle_t *timer_initstruct, ald_timer_channel_t ch, uint32_t ns)
35 {
36     uint64_t tmp = (uint64_t)ald_cmu_get_pclk_clock() * ns / 1000000000 /
37                    (timer_initstruct->init.prescaler + 1);
38 
39     if (ch == ALD_TIMER_CHANNEL_1)
40         WRITE_REG(timer_initstruct->perh->CCVAL1, (uint32_t)tmp);
41     else if (ch == ALD_TIMER_CHANNEL_2)
42         WRITE_REG(timer_initstruct->perh->CCVAL2, (uint32_t)tmp);
43     else if (ch == ALD_TIMER_CHANNEL_3)
44         WRITE_REG(timer_initstruct->perh->CCVAL3, (uint32_t)tmp);
45     else if (ch == ALD_TIMER_CHANNEL_4)
46         WRITE_REG(timer_initstruct->perh->CCVAL4, (uint32_t)tmp);
47 }
48 
es32f3_pwm_control(struct rt_device_pwm * device,int cmd,void * arg)49 static rt_err_t es32f3_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     ald_timer_channel_t pwm_channel;
55     ald_timer_oc_init_t tim_ocinit;
56     ald_timer_handle_t *timer_initstruct = (ald_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 
62     /* select pwm output channel */
63     if (1 == cfg->channel)
64     {
65         pwm_channel = ALD_TIMER_CHANNEL_1;
66         _ccep_ch_en = timer_initstruct->perh->CCEP & TIMER_CCEP_CC1EN_MSK;
67     }
68     else if (2 == cfg->channel)
69     {
70         pwm_channel = ALD_TIMER_CHANNEL_2;
71         _ccep_ch_en = timer_initstruct->perh->CCEP & TIMER_CCEP_CC2EN_MSK;
72     }
73     else if (3 == cfg->channel)
74     {
75         pwm_channel = ALD_TIMER_CHANNEL_3;
76         _ccep_ch_en = timer_initstruct->perh->CCEP & TIMER_CCEP_CC3EN_MSK;
77     }
78     else if (4 == cfg->channel)
79     {
80         pwm_channel = ALD_TIMER_CHANNEL_4;
81         _ccep_ch_en = timer_initstruct->perh->CCEP & TIMER_CCEP_CC4EN_MSK;
82     }
83     else
84         return RT_EINVAL;
85 
86     switch (cmd)
87     {
88     case PWM_CMD_ENABLE:
89         ald_timer_pwm_start(timer_initstruct, pwm_channel);
90         break;
91 
92     case PWM_CMD_DISABLE:
93         ald_timer_pwm_stop(timer_initstruct, pwm_channel);
94         break;
95 
96     case PWM_CMD_SET:
97 
98           /*当通道没开的时候:关通道,设置输出模式和极性,初始化通道*/
99         if(!_ccep_ch_en)
100         {
101          tim_ocinit.oc_mode      = ES_PWM_OC_MODE;
102          tim_ocinit.oc_polarity  = ES_PWM_OC_POLARITY;
103          tim_ocinit.oc_fast_en   = DISABLE;
104          tim_ocinit.ocn_polarity = ALD_TIMER_OCN_POLARITY_HIGH;
105          tim_ocinit.ocn_idle     = ALD_TIMER_OCN_IDLE_RESET;
106          tim_ocinit.oc_idle      = ALD_TIMER_OC_IDLE_RESET;
107 
108             ald_timer_oc_config_channel(timer_initstruct, &tim_ocinit, pwm_channel);
109         }
110 
111         bus_speed = (uint64_t)ald_cmu_get_pclk_clock();
112 
113         /*判断外设的计数器最大值*/
114 #ifdef ES32F36xx
115         if((timer_initstruct->perh == GP32C4T0)||(timer_initstruct->perh == GP32C4T1))
116         {
117             _maxcnt = 0xFFFFFFFF;
118         }
119         else _maxcnt = 0xFFFF;
120 #else
121         _maxcnt = 0xFFFF;
122 #endif
123 
124         /*当最大分频 <= _maxcnt时:估计大概的分频,加快速度 */
125         tmp = bus_speed * (cfg->period)/1000000000/_maxcnt;
126         timer_initstruct->init.prescaler = (tmp > 2U) ? (tmp - 2U) : 0U ;    /*bus_speed < 500000000*/
127 
128         /* count registers max , auto adjust prescaler */
129         do
130         {
131           _arr = bus_speed * (cfg->period) / 1000000000 /(++timer_initstruct->init.prescaler);
132 
133         }
134         while (_arr > _maxcnt);
135 
136         WRITE_REG(timer_initstruct->perh->AR, (uint32_t)_arr);
137         timer_initstruct->init.period   = (uint32_t)_arr;
138 
139         /* update prescaler */
140         WRITE_REG(timer_initstruct->perh->PRES, --timer_initstruct->init.prescaler);
141 
142         pwm_set_duty(timer_initstruct, pwm_channel, cfg->pulse);
143 
144         break;
145 
146     case PWM_CMD_GET:
147         cfg->pulse = ald_timer_read_capture_value(timer_initstruct, pwm_channel) * 100 /
148                      READ_REG(timer_initstruct->perh->AR);
149         break;
150 
151     default:
152         break;
153     }
154     return ret;
155 }
156 
157 const static struct rt_pwm_ops es32f3_pwm_ops =
158 {
159     es32f3_pwm_control
160 };
161 
rt_hw_pwm_init(void)162 int rt_hw_pwm_init(void)
163 {
164     rt_err_t ret = RT_EOK;
165     ald_gpio_init_t gpio_initstructure;
166 
167     gpio_initstructure.mode = ALD_GPIO_MODE_OUTPUT;
168     gpio_initstructure.od = ALD_GPIO_PUSH_PULL;
169     gpio_initstructure.pupd = ALD_GPIO_PUSH_UP;
170     gpio_initstructure.odrv = ALD_GPIO_OUT_DRIVE_NORMAL;
171     gpio_initstructure.flt  = ALD_GPIO_FILTER_DISABLE;
172     gpio_initstructure.type = ALD_GPIO_TYPE_CMOS;
173 
174 #ifdef BSP_USING_AD16C4T0_PWM /* 4 channels */
175     static struct rt_device_pwm ad16c4t0_pwm_dev;
176     static ald_timer_handle_t ad16c4t0_timer_initstruct;
177 
178     ad16c4t0_timer_initstruct.perh = AD16C4T;
179     ald_timer_pwm_init(&ad16c4t0_timer_initstruct);
180 
181     /* gpio initialization */
182 
183 #if  defined(ES_AD16C4T0_CH1_GPIO_FUNC)&&defined(ES_AD16C4T0_CH1_GPIO_PORT)&&defined(ES_AD16C4T0_CH1_GPIO_PIN)
184     gpio_initstructure.func = ES_AD16C4T0_CH1_GPIO_FUNC;
185     ald_gpio_init(ES_AD16C4T0_CH1_GPIO_PORT, ES_AD16C4T0_CH1_GPIO_PIN, &gpio_initstructure);
186 #endif
187 
188 #if  defined(ES_AD16C4T0_CH2_GPIO_FUNC)&&defined(ES_AD16C4T0_CH2_GPIO_PORT)&&defined(ES_AD16C4T0_CH2_GPIO_PIN)
189     gpio_initstructure.func = ES_AD16C4T0_CH2_GPIO_FUNC;
190     ald_gpio_init(ES_AD16C4T0_CH2_GPIO_PORT, ES_AD16C4T0_CH2_GPIO_PIN, &gpio_initstructure);
191 #endif
192 
193 #if  defined(ES_AD16C4T0_CH3_GPIO_FUNC)&&defined(ES_AD16C4T0_CH3_GPIO_PORT)&&defined(ES_AD16C4T0_CH3_GPIO_FUNC)
194     gpio_initstructure.func = ES_AD16C4T0_CH3_GPIO_FUNC;
195     ald_gpio_init(ES_AD16C4T0_CH3_GPIO_PORT, ES_AD16C4T0_CH3_GPIO_PIN, &gpio_initstructure);
196 #endif
197 
198 #if  defined(ES_AD16C4T0_CH4_GPIO_FUNC)&&defined(ES_AD16C4T0_CH4_GPIO_PORT)&&defined(ES_AD16C4T0_CH4_GPIO_PIN)
199     gpio_initstructure.func = ES_AD16C4T0_CH4_GPIO_FUNC;
200     ald_gpio_init(ES_AD16C4T0_CH4_GPIO_PORT, ES_AD16C4T0_CH4_GPIO_PIN, &gpio_initstructure);
201 #endif
202 
203     ret = rt_device_pwm_register(&ad16c4t0_pwm_dev, ES_DEVICE_NAME_AD16C4T0_PWM, &es32f3_pwm_ops,
204                                  &ad16c4t0_timer_initstruct);
205 #endif
206 
207 #ifdef BSP_USING_GP16C4T0_PWM /* 4 channels */
208     static struct rt_device_pwm gp16c4t0_pwm_dev;
209     static ald_timer_handle_t gp16c4t0_timer_initstruct;
210 
211     gp16c4t0_timer_initstruct.perh = GP16C4T0;
212     ald_timer_pwm_init(&gp16c4t0_timer_initstruct);
213 
214     /* gpio initialization */
215 
216 #if  defined(ES_GP16C4T0_CH1_GPIO_FUNC)&&defined(ES_GP16C4T0_CH1_GPIO_PORT)&&defined(ES_GP16C4T0_CH1_GPIO_PIN)
217     gpio_initstructure.func = ES_GP16C4T0_CH1_GPIO_FUNC;
218     ald_gpio_init(ES_GP16C4T0_CH1_GPIO_PORT, ES_GP16C4T0_CH1_GPIO_PIN, &gpio_initstructure);
219 #endif
220 
221 #if  defined(ES_GP16C4T0_CH2_GPIO_FUNC)&&defined(ES_GP16C4T0_CH2_GPIO_PORT)&&defined(ES_GP16C4T0_CH2_GPIO_PIN)
222     gpio_initstructure.func = ES_GP16C4T0_CH2_GPIO_FUNC;
223     ald_gpio_init(ES_GP16C4T0_CH2_GPIO_PORT, ES_GP16C4T0_CH2_GPIO_PIN, &gpio_initstructure);
224 #endif
225 
226 #if  defined(ES_GP16C4T0_CH3_GPIO_FUNC)&&defined(ES_GP16C4T0_CH3_GPIO_PORT)&&defined(ES_GP16C4T0_CH3_GPIO_PIN)
227     gpio_initstructure.func = ES_GP16C4T0_CH3_GPIO_FUNC;
228     ald_gpio_init(ES_GP16C4T0_CH3_GPIO_PORT, ES_GP16C4T0_CH3_GPIO_PIN, &gpio_initstructure);
229 #endif
230 
231 #if  defined(ES_GP16C4T0_CH4_GPIO_FUNC)&&defined(ES_GP16C4T0_CH4_GPIO_PORT)&&defined(ES_GP16C4T0_CH4_GPIO_PIN)
232     gpio_initstructure.func = ES_GP16C4T0_CH4_GPIO_FUNC;
233     ald_gpio_init(ES_GP16C4T0_CH4_GPIO_PORT, ES_GP16C4T0_CH4_GPIO_PIN, &gpio_initstructure);
234 #endif
235 
236     ret = rt_device_pwm_register(&gp16c4t0_pwm_dev, ES_DEVICE_NAME_GP16C4T0_PWM, &es32f3_pwm_ops,
237                                  &gp16c4t0_timer_initstruct);
238 #endif
239 
240 #ifdef BSP_USING_GP16C4T1_PWM /* 4 channels */
241     static struct rt_device_pwm gp16c4t1_pwm_dev;
242     static ald_timer_handle_t gp16c4t1_timer_initstruct;
243 
244     gp16c4t1_timer_initstruct.perh = GP16C4T1;
245     ald_timer_pwm_init(&gp16c4t1_timer_initstruct);
246 
247     /* gpio initialization */
248 
249 #if  defined(ES_GP16C4T1_CH1_GPIO_FUNC)&&defined(ES_GP16C4T1_CH1_GPIO_PORT)&&defined(ES_GP16C4T1_CH1_GPIO_PIN)
250     gpio_initstructure.func = ES_GP16C4T1_CH1_GPIO_FUNC;
251     ald_gpio_init(ES_GP16C4T1_CH1_GPIO_PORT, ES_GP16C4T1_CH1_GPIO_PIN, &gpio_initstructure);
252 #endif
253 
254 #if  defined(ES_GP16C4T1_CH2_GPIO_FUNC)&&defined(ES_GP16C4T1_CH2_GPIO_PORT)&&defined(ES_GP16C4T1_CH2_GPIO_PIN)
255     gpio_initstructure.func = ES_GP16C4T1_CH2_GPIO_FUNC;
256     ald_gpio_init(ES_GP16C4T1_CH2_GPIO_PORT, ES_GP16C4T1_CH2_GPIO_PIN, &gpio_initstructure);
257 #endif
258 
259 #if  defined(ES_GP16C4T1_CH3_GPIO_FUNC)&&defined(ES_GP16C4T1_CH3_GPIO_PORT)&&defined(ES_GP16C4T1_CH3_GPIO_PIN)
260     gpio_initstructure.func = ES_GP16C4T1_CH3_GPIO_FUNC;
261     ald_gpio_init(ES_GP16C4T1_CH3_GPIO_PORT, ES_GP16C4T1_CH3_GPIO_PIN, &gpio_initstructure);
262 #endif
263 
264 #if  defined(ES_GP16C4T1_CH4_GPIO_FUNC)&&defined(ES_GP16C4T1_CH4_GPIO_PORT)&&defined(ES_GP16C4T1_CH4_GPIO_PIN)
265     gpio_initstructure.func = ES_GP16C4T1_CH4_GPIO_FUNC;
266     ald_gpio_init(ES_GP16C4T1_CH4_GPIO_PORT, ES_GP16C4T1_CH4_GPIO_PIN, &gpio_initstructure);
267 #endif
268 
269     ret = rt_device_pwm_register(&gp16c4t1_pwm_dev, ES_DEVICE_NAME_GP16C4T1_PWM, &es32f3_pwm_ops,
270                                  &gp16c4t1_timer_initstruct);
271 #endif
272 
273 #ifdef BSP_USING_GP16C4T2_PWM /* 4 channels */
274     static struct rt_device_pwm gp16c4t2_pwm_dev;
275     static ald_timer_handle_t gp16c4t2_timer_initstruct;
276 
277     gp16c4t2_timer_initstruct.perh = GP16C4T2;
278     ald_timer_pwm_init(&gp16c4t2_timer_initstruct);
279 
280     /* gpio initialization */
281 
282 #if  defined(ES_GP16C4T2_CH1_GPIO_FUNC)&&defined(ES_GP16C4T2_CH1_GPIO_PORT)&&defined(ES_GP16C4T2_CH1_GPIO_PIN)
283     gpio_initstructure.func = ES_GP16C4T2_CH1_GPIO_FUNC;
284     ald_gpio_init(ES_GP16C4T2_CH1_GPIO_PORT, ES_GP16C4T2_CH1_GPIO_PIN, &gpio_initstructure);
285 #endif
286 
287 #if  defined(ES_GP16C4T2_CH2_GPIO_FUNC)&&defined(ES_GP16C4T2_CH2_GPIO_PORT)&&defined(ES_GP16C4T2_CH2_GPIO_PIN)
288     gpio_initstructure.func = ES_GP16C4T2_CH2_GPIO_FUNC;
289     ald_gpio_init(ES_GP16C4T2_CH2_GPIO_PORT, ES_GP16C4T2_CH2_GPIO_PIN, &gpio_initstructure);
290 #endif
291 
292 #if  defined(ES_GP16C4T2_CH3_GPIO_FUNC)&&defined(ES_GP16C4T2_CH3_GPIO_PORT)&&defined(ES_GP16C4T2_CH3_GPIO_PIN)
293     gpio_initstructure.func = ES_GP16C4T2_CH3_GPIO_FUNC;
294     ald_gpio_init(ES_GP16C4T2_CH3_GPIO_PORT, ES_GP16C4T2_CH3_GPIO_PIN, &gpio_initstructure);
295 #endif
296 
297 #if  defined(ES_GP16C4T2_CH4_GPIO_FUNC)&&defined(ES_GP16C4T2_CH4_GPIO_PORT)&&defined(ES_GP16C4T2_CH4_GPIO_PIN)
298     gpio_initstructure.func = ES_GP16C4T2_CH4_GPIO_FUNC;
299     ald_gpio_init(ES_GP16C4T2_CH4_GPIO_PORT, ES_GP16C4T2_CH4_GPIO_PIN, &gpio_initstructure);
300 #endif
301 
302     ret = rt_device_pwm_register(&gp16c4t2_pwm_dev, ES_DEVICE_NAME_GP16C4T2_PWM, &es32f3_pwm_ops,
303                                  &gp16c4t2_timer_initstruct);
304 #endif
305 
306     return ret;
307 }
308 INIT_DEVICE_EXPORT(rt_hw_pwm_init);
309 
310 #endif
311