• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * Description: Provides pwm driver source \n
16  *
17  * History: \n
18  * 2022-09-16, Create file. \n
19  */
20 
21 #include "common_def.h"
22 #include "osal_interrupt.h"
23 #include "hal_pwm.h"
24 #include "pwm.h"
25 
26 #define PWM_CYCLES_MAX_NUMBER      32767  /* Max number of PWM cycles */
27 
28 static bool g_pwm_inited = false;
29 static bool g_pwm_opened[CONFIG_PWM_CHANNEL_NUM] = { false };
30 #if defined(CONFIG_PWM_USING_V151)
31 static uint16_t g_pwm_group[CONFIG_PWM_GROUP_NUM] = { 0 };
32 #endif /* CONFIG_PWM_USING_v151 */
33 static hal_pwm_funcs_t *g_hal_funcs = NULL;
34 
uapi_pwm_check(uint8_t channel)35 static errcode_t uapi_pwm_check(uint8_t channel)
36 {
37     if (unlikely(channel >= CONFIG_PWM_CHANNEL_NUM)) {
38         return ERRCODE_PWM_INVALID_PARAMETER;
39     }
40 
41     if (unlikely(!g_pwm_inited)) {
42         return ERRCODE_PWM_NOT_INIT;
43     }
44 
45     if (unlikely(!g_pwm_opened[channel])) {
46         return ERRCODE_PWM_NOT_OPEN;
47     }
48 
49     return ERRCODE_SUCC;
50 }
51 
52 #if defined(CONFIG_PWM_USING_V151)
uapi_pwm_group_check(uint8_t group)53 static errcode_t uapi_pwm_group_check(uint8_t group)
54 {
55     if (unlikely(group >= CONFIG_PWM_GROUP_NUM)) {
56         return ERRCODE_PWM_INVALID_PARAMETER;
57     }
58 
59     return ERRCODE_SUCC;
60 }
61 
uapi_pwm_get_group(uint8_t * group,uint8_t channel)62 static errcode_t uapi_pwm_get_group(uint8_t* group, uint8_t channel)
63 {
64     uint8_t index;
65     for (index = 0; index < CONFIG_PWM_GROUP_NUM; index++) {
66         if ((g_pwm_group[index] & (uint16_t)(1 << channel)) > 0) {
67             *group = index;
68             break;
69         }
70     }
71 
72     if (index == CONFIG_PWM_GROUP_NUM) {
73         return ERRCODE_PWM_INVALID_PARAMETER;
74     }
75     return ERRCODE_SUCC;
76 }
77 #endif /* CONFIG_PWM_USING_v151 */
78 
uapi_pwm_init(void)79 errcode_t uapi_pwm_init(void)
80 {
81     if (g_pwm_inited) {
82         return ERRCODE_SUCC;
83     }
84 
85     pwm_port_clock_enable(true);
86 
87     pwm_port_register_hal_funcs();
88     g_hal_funcs = hal_pwm_get_funcs();
89     errcode_t ret = g_hal_funcs->init();
90     if (ret != ERRCODE_SUCC) {
91         return ret;
92     }
93 
94     g_pwm_inited = true;
95 
96     return ret;
97 }
98 
uapi_pwm_deinit(void)99 void uapi_pwm_deinit(void)
100 {
101     if (!g_pwm_inited) {
102         return;
103     }
104 
105     for (uint8_t channel_i = (uint8_t)PWM_0; channel_i < (uint8_t)CONFIG_PWM_CHANNEL_NUM; channel_i++) {
106         if (g_pwm_opened[channel_i]) {
107             (void)uapi_pwm_close(channel_i);
108         }
109     }
110 
111     g_hal_funcs->deinit();
112 
113     pwm_port_unregister_hal_funcs();
114 
115     pwm_port_clock_enable(false);
116 
117     g_pwm_inited = false;
118 }
119 
uapi_pwm_open(uint8_t channel,const pwm_config_t * cfg)120 errcode_t uapi_pwm_open(uint8_t channel, const pwm_config_t *cfg)
121 {
122     if (unlikely(channel >= CONFIG_PWM_CHANNEL_NUM)) {
123         return ERRCODE_PWM_INVALID_PARAMETER;
124     }
125 
126     if (unlikely(!g_pwm_inited)) {
127         return ERRCODE_PWM_NOT_INIT;
128     }
129     if (unlikely(g_pwm_opened[channel])) {
130         (void)uapi_pwm_close(channel);
131     }
132 
133     if (unlikely(cfg->cycles > PWM_CYCLES_MAX_NUMBER)) {
134         return ERRCODE_PWM_INVALID_PARAMETER;
135     }
136 #if defined(CONFIG_PWM_USING_V151)
137     if (pwm_port_param_check(cfg) != ERRCODE_SUCC) {
138         return ERRCODE_PWM_INVALID_PARAMETER;
139     }
140 #endif
141     uint32_t id = osal_irq_lock();
142     g_hal_funcs->registerfunc((pwm_channel_t)channel, (hal_pwm_callback_t)uapi_pwm_isr);
143 
144     g_hal_funcs->set_time(PWM_SET_LOW_TIME, (pwm_channel_t)channel, cfg->low_time);
145     g_hal_funcs->set_time(PWM_SET_HIGH_TIME, (pwm_channel_t)channel, cfg->high_time);
146 
147 #if defined(CONFIG_PWM_USING_V151)
148     g_hal_funcs->set_time(PWM_SET_OFFSET_TIME, (pwm_channel_t)channel, cfg->offset_time);
149 #endif /* CONFIG_PWM_USING_V151 */
150 
151     g_hal_funcs->set_cycles((pwm_channel_t)channel, cfg->cycles);
152 
153     if (cfg->repeat) {
154         g_hal_funcs->set_action(channel, PWM_ACTION_CONTINUE_SET);
155     }
156     osal_irq_restore(id);
157 
158     g_pwm_opened[channel] = true;
159     return ERRCODE_SUCC;
160 }
161 
162 
uapi_pwm_close(uint8_t channel)163 errcode_t uapi_pwm_close(uint8_t channel)
164 {
165     errcode_t ret;
166     ret = uapi_pwm_check(channel);
167     if (ret != ERRCODE_SUCC) {
168         return ret;
169     }
170 #if defined(CONFIG_PWM_USING_V151)
171     uint8_t close_group = 0;
172     ret = uapi_pwm_get_group(&close_group, channel);
173     if (ret != ERRCODE_SUCC) {
174         return ret;
175     }
176 #endif /* CONFIG_PWM_USING_V151 */
177 
178     uint32_t id = osal_irq_lock();
179 #if defined(CONFIG_PWM_USING_V150)
180     g_hal_funcs->set_action(channel, PWM_ACTION_STOP);
181     g_hal_funcs->set_action(channel, PWM_ACTION_CONTINUE_CLR);
182 #else
183     uint16_t pre_channel_id = (uint16_t)(1 << channel);
184     uint16_t post_channel_id = g_pwm_group[close_group];
185     g_hal_funcs->set_group((pwm_v151_group_t)close_group, pre_channel_id);
186     g_hal_funcs->set_action(close_group, PWM_ACTION_STOP);
187     g_hal_funcs->set_group((pwm_v151_group_t)close_group, post_channel_id);
188     g_pwm_group[close_group] = post_channel_id;
189 #endif /* CONFIG_PWM_USING_V150 */
190     osal_irq_restore(id);
191 
192     uapi_pwm_unregister_interrupt((pwm_channel_t)channel);
193 
194     g_pwm_opened[channel] = false;
195 
196     return ret;
197 }
198 
uapi_pwm_start(uint8_t channel)199 errcode_t uapi_pwm_start(uint8_t channel)
200 {
201     errcode_t ret = ERRCODE_SUCC;
202     ret = uapi_pwm_check(channel);
203     if (ret != ERRCODE_SUCC) {
204         return ret;
205     }
206 #if defined(CONFIG_PWM_USING_V151)
207     uint8_t start_group = 0;
208     ret = uapi_pwm_get_group(&start_group, channel);
209     if (ret != ERRCODE_SUCC) {
210         return ret;
211     }
212 #endif /* CONFIG_PWM_USING_V151 */
213 
214     uint32_t id = osal_irq_lock();
215 #if defined(CONFIG_PWM_USING_V150)
216     g_hal_funcs->set_action(channel, PWM_ACTION_START);
217 #else
218     uint16_t pre_channel_id = (uint16_t)(1 << channel);
219     uint16_t post_channel_id = g_pwm_group[start_group];
220     g_hal_funcs->set_group((pwm_v151_group_t)start_group, pre_channel_id);
221     g_hal_funcs->set_action(start_group, PWM_ACTION_START);
222     g_hal_funcs->set_group((pwm_v151_group_t)start_group, post_channel_id);
223     g_pwm_group[start_group] = post_channel_id;
224 #endif /* CONFIG_PWM_USING_V150 */
225     osal_irq_restore(id);
226 
227     return ret;
228 }
229 
uapi_pwm_get_frequency(uint8_t channel)230 uint32_t uapi_pwm_get_frequency(uint8_t channel)
231 {
232     return pwm_port_get_clock_value((pwm_channel_t)channel);
233 }
234 
235 #if defined(CONFIG_PWM_USING_V150)
uapi_pwm_stop(uint8_t channel)236 errcode_t uapi_pwm_stop(uint8_t channel)
237 {
238     errcode_t ret = uapi_pwm_check(channel);
239     if (ret != ERRCODE_SUCC) {
240         return ret;
241     }
242 
243     uint32_t id = osal_irq_lock();
244     g_hal_funcs->set_action(channel, PWM_ACTION_STOP);
245     osal_irq_restore(id);
246 
247     return ret;
248 }
249 
uapi_pwm_update_duty_ratio(uint8_t channel,uint32_t low_time,uint32_t high_time)250 errcode_t uapi_pwm_update_duty_ratio(uint8_t channel, uint32_t low_time, uint32_t high_time)
251 {
252     errcode_t ret = uapi_pwm_check(channel);
253     if (ret != ERRCODE_SUCC) {
254         return ret;
255     }
256 
257     uint32_t id = osal_irq_lock();
258     g_hal_funcs->set_time(PWM_SET_LOW_TIME, (pwm_channel_t)channel, low_time);
259     g_hal_funcs->set_time(PWM_SET_HIGH_TIME, (pwm_channel_t)channel, high_time);
260     g_hal_funcs->set_action(channel, PWM_ACTION_REFRESH);
261     osal_irq_restore(id);
262 
263     return ret;
264 }
265 #endif /* CONFIG_PWM_USING_V150 */
266 
uapi_pwm_isr(uint8_t channel)267 errcode_t uapi_pwm_isr(uint8_t channel)
268 {
269     if (unlikely(channel >= CONFIG_PWM_CHANNEL_NUM)) {
270         return ERRCODE_PWM_INVALID_PARAMETER;
271     }
272 
273     uint32_t id = osal_irq_lock();
274     g_hal_funcs->isrclear((pwm_channel_t)channel);
275     osal_irq_restore(id);
276 
277     return ERRCODE_SUCC;
278 }
279 
uapi_pwm_register_interrupt(uint8_t channel,pwm_callback_t callback)280 errcode_t uapi_pwm_register_interrupt(uint8_t channel, pwm_callback_t callback)
281 {
282     errcode_t ret = uapi_pwm_check(channel);
283     if (ret != ERRCODE_SUCC) {
284         return ret;
285     }
286     pwm_port_register_irq((pwm_channel_t)channel);
287 
288     g_hal_funcs->registerfunc((pwm_channel_t)channel, (hal_pwm_callback_t)callback);
289 
290     return ret;
291 }
292 
uapi_pwm_unregister_interrupt(uint8_t channel)293 errcode_t uapi_pwm_unregister_interrupt(uint8_t channel)
294 {
295     errcode_t ret = uapi_pwm_check(channel);
296     if (ret != ERRCODE_SUCC) {
297         return ret;
298     }
299     pwm_port_unregister_irq((pwm_channel_t)channel);
300 
301     g_hal_funcs->unregisterfunc((pwm_channel_t)channel);
302 
303     return ret;
304 }
305 
306 #if defined(CONFIG_PWM_USING_V151)
uapi_pwm_set_group(uint8_t group,const uint8_t * channel_set,uint32_t channel_set_len)307 errcode_t uapi_pwm_set_group(uint8_t group, const uint8_t *channel_set, uint32_t channel_set_len)
308 {
309     uint16_t channel_id = 0;
310     if ((group >= CONFIG_PWM_GROUP_NUM) || (channel_set == NULL) || (channel_set_len == 0)) {
311         return ERRCODE_PWM_INVALID_PARAMETER;
312     }
313 
314     for (uint32_t i = 0; i < channel_set_len; i++) {
315         channel_id |= (1 << channel_set[i]);
316     }
317 
318     for (uint32_t i = 0; i < CONFIG_PWM_GROUP_NUM; i++) {
319         if ((g_pwm_group[i] & channel_id) > 0) {
320             return ERRCODE_PWM_INVALID_PARAMETER;
321         }
322     }
323 
324     uint32_t id = osal_irq_lock();
325     g_hal_funcs->set_group((pwm_v151_group_t)group, channel_id);
326     g_pwm_group[group] = channel_id;
327     osal_irq_restore(id);
328 
329     return ERRCODE_SUCC;
330 }
331 
uapi_pwm_clear_group(uint8_t group)332 errcode_t uapi_pwm_clear_group(uint8_t group)
333 {
334     if (group >= CONFIG_PWM_GROUP_NUM) {
335         return ERRCODE_PWM_INVALID_PARAMETER;
336     }
337 
338     uint32_t id = osal_irq_lock();
339     g_hal_funcs->set_group((pwm_v151_group_t)group, 0);
340     g_pwm_group[group] = 0;
341     osal_irq_restore(id);
342 
343     return ERRCODE_SUCC;
344 }
345 
uapi_pwm_start_group(uint8_t group)346 errcode_t uapi_pwm_start_group(uint8_t group)
347 {
348     errcode_t ret = uapi_pwm_group_check(group);
349     if (ret != ERRCODE_SUCC) {
350         return ret;
351     }
352 
353     uint32_t id = osal_irq_lock();
354     g_hal_funcs->set_action(group, PWM_ACTION_START);
355     osal_irq_restore(id);
356 
357     return ret;
358 }
359 
uapi_pwm_stop_group(uint8_t group)360 errcode_t uapi_pwm_stop_group(uint8_t group)
361 {
362     errcode_t ret = uapi_pwm_group_check(group);
363     if (ret != ERRCODE_SUCC) {
364         return ret;
365     }
366 
367     uint32_t id = osal_irq_lock();
368     g_hal_funcs->set_action(group, PWM_ACTION_STOP);
369     osal_irq_restore(id);
370 
371     return ret;
372 }
373 
374 #if defined(CONFIG_PWM_PRELOAD)
uapi_pwm_config_preload(uint8_t group,uint8_t channel,const pwm_config_t * cfg)375 errcode_t uapi_pwm_config_preload(uint8_t group, uint8_t channel, const pwm_config_t *cfg)
376 {
377     if ((channel >= CONFIG_PWM_CHANNEL_NUM) || (group >= CONFIG_PWM_GROUP_NUM) || (cfg == NULL)) {
378         return ERRCODE_PWM_INVALID_PARAMETER;
379     }
380 
381     if (unlikely(!g_pwm_inited)) {
382         return ERRCODE_PWM_NOT_INIT;
383     }
384 
385     if (unlikely(cfg->cycles > PWM_CYCLES_MAX_NUMBER)) {
386         return ERRCODE_PWM_INVALID_PARAMETER;
387     }
388 
389     uint32_t id = osal_irq_lock();
390     g_hal_funcs->set_time(PWM_SET_LOW_TIME, (pwm_channel_t)channel, cfg->low_time);
391     g_hal_funcs->set_time(PWM_SET_HIGH_TIME, (pwm_channel_t)channel, cfg->high_time);
392 
393     g_hal_funcs->set_time(PWM_SET_OFFSET_TIME, (pwm_channel_t)channel, cfg->offset_time);
394 
395     g_hal_funcs->set_cycles((pwm_channel_t)channel, cfg->cycles);
396     g_hal_funcs->config_preload(group);
397     osal_irq_restore(id);
398 
399     return ERRCODE_SUCC;
400 }
401 #endif /* CONFIG_PWM_PRELOAD */
402 #endif /* CONFIG_PWM_USING_V151 */