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 iot_pwm driver source \n
16 *
17 * History: \n
18 * 2023-10-18, Create file. \n
19 */
20 #include "common_def.h"
21 #include "iot_errno.h"
22 #include "pwm.h"
23 #include "iot_pwm.h"
24
25 #define IOT_PWM_MIN_DUTY 0
26 #define IOT_PWM_MAX_DUTY 100
27 #define IOT_PWM_DUTY_PART 10
28 #define IOT_PWM_FREQ_PART 2
29 #define IOT_PWM_MAX_DIV_NUM_MAX 8
30 #define IOT_PWM_CFG_OFFEST_TIME 0
31 #define IOT_PWM_CFG_REPEAT_CYCLE 100
32 #define IOT_PWM_CFG_REPEAT_STATE true
33
34 static bool g_iot_pwm_inited = false;
35
IoTPwmInit(unsigned int port)36 unsigned int IoTPwmInit(unsigned int port)
37 {
38 unused(port);
39 if (!g_iot_pwm_inited) {
40 uapi_pwm_init();
41 }
42 g_iot_pwm_inited = true;
43 return IOT_SUCCESS;
44 }
45
IoTPwmDeinit(unsigned int port)46 unsigned int IoTPwmDeinit(unsigned int port)
47 {
48 unused(port);
49 if (g_iot_pwm_inited) {
50 uapi_pwm_deinit();
51 }
52 g_iot_pwm_inited = false;
53 return IOT_SUCCESS;
54 }
55
IoTPwmStart(unsigned int port,unsigned short duty,unsigned int freq)56 unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq)
57 {
58 if ((duty >= IOT_PWM_MAX_DUTY) || (duty == IOT_PWM_MIN_DUTY)) {
59 return IOT_FAILURE;
60 }
61
62 uint32_t clk_freq = uapi_pwm_get_frequency((uint8_t)port);
63 uint32_t div_num = (clk_freq + freq / IOT_PWM_FREQ_PART) / freq; // 计算分频数
64 if (div_num < IOT_PWM_MAX_DIV_NUM_MAX) {
65 return IOT_FAILURE;
66 }
67 uint32_t high_time = div_num * duty / IOT_PWM_MAX_DUTY; // 计算高电平时钟个数(向下取整)
68 if (high_time * IOT_PWM_MAX_DUTY / div_num >= (uint32_t)(duty - duty * IOT_PWM_DUTY_PART / IOT_PWM_MAX_DUTY)) {
69 } else if ((high_time + 1) * IOT_PWM_MAX_DUTY / div_num <=
70 (uint32_t)(duty + duty * IOT_PWM_DUTY_PART / IOT_PWM_MAX_DUTY)) {
71 high_time++;
72 } else {
73 return IOT_FAILURE;
74 }
75 uint32_t low_time = div_num - high_time;
76 pwm_config_t cfg = {
77 .low_time = low_time,
78 .high_time = high_time,
79 .offset_time = IOT_PWM_CFG_OFFEST_TIME,
80 .cycles = IOT_PWM_CFG_REPEAT_CYCLE,
81 .repeat = IOT_PWM_CFG_REPEAT_STATE
82 };
83 if (uapi_pwm_open((uint8_t)port, &cfg) != ERRCODE_SUCC) {
84 return IOT_FAILURE;
85 }
86
87 if (uapi_pwm_start((uint8_t)port) != ERRCODE_SUCC) {
88 return IOT_FAILURE;
89 }
90 return IOT_SUCCESS;
91 }
92
IoTPwmStop(unsigned int port)93 unsigned int IoTPwmStop(unsigned int port)
94 {
95 if (uapi_pwm_close((uint8_t)port) != ERRCODE_SUCC) {
96 return IOT_FAILURE;
97 }
98 return IOT_SUCCESS;
99 }