1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include <drv/pwm.h>
6 #include <aos/pwm_csi.h>
7 #include "device.h"
8 #include "objects.h"
9 #include "pinmap.h"
10
11 #define BIT_PWM_TIM_IDX_FLAG BIT(7)
12 #define BIT_PWM_TIM_IDX_SHIFT 7
13 #define PWM_TIMER 5
14
15 /* Table elements express the pin to PWM channel number, they are:
16 * {pinName, km0_pin2chan, km4_pin2chan}
17 */
18 const u32 csi_pin2chan[18][2] = {
19 { PA_12, 0 },
20 { PA_13, 1 },
21 { PA_23, 2 },
22 { PA_24, 3 },
23 { PA_25, 4 },
24 { PA_26, 5 },
25 { PA_28, 6 },
26 { PA_30, 7 },
27 { PB_4, 8 },
28 { PB_5, 9 },
29 { PB_18, 10 },
30 { PB_19, 11 },
31 { PB_20, 12 },
32 { PB_21, 13 },
33 { PB_22, 14 },
34 { PB_23, 15 },
35 { PB_24, 16 },
36 { PB_25, 17 } // this channel also can be PB_7
37 };
38
39 RTIM_TypeDef *CSI_PWM_TIM[2] = { TIM5, TIMM05 };
40
41 u8 csi_km4_ch_start[18] = { 0 };
42
csi_pwm_init(csi_pwm_t * pwm,uint32_t idx)43 csi_error_t csi_pwm_init(csi_pwm_t *pwm, uint32_t idx)
44 {
45 if (!pwm)
46 return CSI_ERROR;
47
48 if (idx != 0) {
49 return CSI_ERROR;
50 }
51 pwm->priv = (TIM_CCInitTypeDef *)malloc(sizeof(TIM_CCInitTypeDef));
52 pwm->dev.idx = idx << BIT_PWM_TIM_IDX_SHIFT;
53
54 return CSI_OK;
55 }
56
csi_pwm_uninit(csi_pwm_t * pwm)57 void csi_pwm_uninit(csi_pwm_t *pwm)
58 {
59 uint32_t pwm_chan = pwm->dev.idx & (~BIT_PWM_TIM_IDX_FLAG);
60 uint8_t pwm_tim_idx = pwm->dev.idx >> BIT_PWM_TIM_IDX_SHIFT;
61
62 if (csi_km4_ch_start[pwm_chan]) {
63 csi_km4_ch_start[pwm_chan] = 0;
64 RTIM_CCxCmd(CSI_PWM_TIM[pwm_tim_idx], pwm_chan, TIM_CCx_Disable);
65
66 /* stop timer5 if no pwm channels starts */
67 for (pwm_chan = 0; pwm_chan < 18; pwm_chan++) {
68 if (csi_km4_ch_start[pwm_chan]) {
69 return;
70 }
71 }
72 RTIM_Cmd(CSI_PWM_TIM[pwm_tim_idx], DISABLE);
73 }
74
75 if (pwm && pwm->priv) {
76 free(pwm->priv);
77 pwm->priv = NULL;
78 }
79 }
80
csi_pwm_out_config(csi_pwm_t * pwm,uint32_t channel,uint32_t period_us,uint32_t pulse_width_us,csi_pwm_polarity_t polarity)81 csi_error_t csi_pwm_out_config(csi_pwm_t *pwm, uint32_t channel, uint32_t period_us,
82 uint32_t pulse_width_us, csi_pwm_polarity_t polarity)
83 {
84 uint32_t arr, tmp, ccrx;
85 uint32_t period;
86 float pulse, value, dc;
87 uint8_t pwm_tim_idx = pwm->dev.idx >> BIT_PWM_TIM_IDX_SHIFT;
88 TIM_CCInitTypeDef *TIM_CCInitStruct = (TIM_CCInitTypeDef *)pwm->priv;
89 u32 csi_prescaler = 0;
90
91 if (channel > 18) {
92 return CSI_ERROR;
93 }
94
95 RTIM_CCStructInit(TIM_CCInitStruct);
96 RTIM_CCxInit(CSI_PWM_TIM[pwm_tim_idx], TIM_CCInitStruct, channel);
97 RTIM_CCxCmd(CSI_PWM_TIM[pwm_tim_idx], channel, TIM_CCx_Enable);
98
99 PinName pin = csi_pin2chan[channel][0];
100
101 if (pwm_tim_idx) {
102 Pinmux_Config(pin, PINMUX_FUNCTION_PWM_LP);
103 } else {
104 Pinmux_Config(pin, PINMUX_FUNCTION_PWM_HS);
105 }
106 pwm->dev.idx |= channel;
107 csi_km4_ch_start[channel] = 1;
108
109 tmp = period_us * 40 / (csi_prescaler + 1);
110 /*
111 * psr is 8bits
112 */
113 if (tmp > 0x10000) {
114 csi_prescaler = period_us * 40 / 0x10000;
115 if (csi_prescaler > 0xff) {
116 csi_prescaler = 0xff;
117 }
118 RTIM_PrescalerConfig(CSI_PWM_TIM[pwm_tim_idx], csi_prescaler, TIM_PSCReloadMode_Update);
119 }
120 /*
121 * arr is 16bits
122 */
123
124 /*
125 * 40M oscilator range:2HZ-2KHZ?
126 */
127 arr = period_us * 40 / (csi_prescaler + 1) - 1;
128 if (arr > 0xffff) {
129 arr = 0xffff;
130 }
131 RTIM_ChangePeriod(CSI_PWM_TIM[pwm_tim_idx], arr);
132
133 ccrx = (u32)((period_us - pulse_width_us) * 40 / (csi_prescaler + 1)) & 0x0000ffff;
134 RTIM_CCRxSet(CSI_PWM_TIM[pwm_tim_idx], ccrx, channel);
135
136 if (0 == polarity)
137 RTIM_CCxPolarityConfig(CSI_PWM_TIM[pwm_tim_idx], TIM_CCPolarity_Low, channel);
138 else
139 RTIM_CCxPolarityConfig(CSI_PWM_TIM[pwm_tim_idx], TIM_CCPolarity_High, channel);
140 return CSI_OK;
141 }
142
csi_pwm_out_start(csi_pwm_t * pwm,uint32_t channel)143 csi_error_t csi_pwm_out_start(csi_pwm_t *pwm, uint32_t channel)
144 {
145 uint32_t pwm_chan = channel;
146 uint8_t pwm_tim_idx = pwm->dev.idx >> BIT_PWM_TIM_IDX_SHIFT;
147
148 RTIM_CCxCmd(CSI_PWM_TIM[pwm_tim_idx], pwm_chan, TIM_CCx_Enable);
149 return CSI_OK;
150 }
151
csi_pwm_out_stop(csi_pwm_t * pwm,uint32_t channel)152 void csi_pwm_out_stop(csi_pwm_t *pwm, uint32_t channel)
153 {
154 uint32_t pwm_chan = channel;
155 uint8_t pwm_tim_idx = pwm->dev.idx >> BIT_PWM_TIM_IDX_SHIFT;
156
157 RTIM_CCxCmd(CSI_PWM_TIM[pwm_tim_idx], pwm_chan, TIM_CCx_Disable);
158 }
pwm_csi_init(void)159 static int pwm_csi_init(void)
160 {
161 csi_error_t ret;
162 static aos_pwm_csi_t pwm_csi_dev[CONFIG_PWM_NUM];
163 int idx = 0, i;
164 RTIM_TimeBaseInitTypeDef TIM_InitStruct;
165 RTIM_TimeBaseStructInit(&TIM_InitStruct);
166 TIM_InitStruct.TIM_Idx = PWM_TIMER;
167 RTIM_TimeBaseInit(CSI_PWM_TIM[idx], &TIM_InitStruct, TIMER5_IRQ, NULL, (u32)&TIM_InitStruct);
168 RTIM_Cmd(CSI_PWM_TIM[idx], ENABLE);
169 for (i = 0; i < CONFIG_PWM_NUM; i++) {
170 ret = csi_pwm_init(&(pwm_csi_dev[i].csi_pwm), idx);
171 pwm_csi_dev[i].csi_pwm.dev.idx |= (i) & (~BIT_PWM_TIM_IDX_FLAG);
172 if (ret != CSI_OK) {
173 return ret;
174 }
175 pwm_csi_dev[i].aos_pwm.dev.id = i;
176 ret = aos_pwm_csi_register(&(pwm_csi_dev[i]));
177 if (ret != CSI_OK) {
178 return ret;
179 }
180 }
181 return 0;
182 }
183
184 LEVEL1_DRIVER_ENTRY(pwm_csi_init)
185