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