1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-11-11 breo.com first version
9 */
10
11 #include <board.h>
12 #include "drv_pwm.h"
13
14 #ifdef RT_USING_PWM
15 #if !defined(BSP_USING_TIM1_CH1) && !defined(BSP_USING_TIM1_CH2) && \
16 !defined(BSP_USING_TIM1_CH3) && !defined(BSP_USING_TIM1_CH4) && \
17 !defined(BSP_USING_TIM2_CH1) && !defined(BSP_USING_TIM2_CH2) && \
18 !defined(BSP_USING_TIM2_CH3) && !defined(BSP_USING_TIM2_CH4) && \
19 !defined(BSP_USING_TIM3_CH1) && !defined(BSP_USING_TIM3_CH2) && \
20 !defined(BSP_USING_TIM3_CH3) && !defined(BSP_USING_TIM3_CH4) && \
21 !defined(BSP_USING_TIM4_CH1) && !defined(BSP_USING_TIM4_CH2) && \
22 !defined(BSP_USING_TIM4_CH3) && !defined(BSP_USING_TIM4_CH4) && \
23 !defined(BSP_USING_TIM5_CH1) && !defined(BSP_USING_TIM5_CH2) && \
24 !defined(BSP_USING_TIM5_CH3) && !defined(BSP_USING_TIM5_CH4) && \
25 !defined(BSP_USING_TIM8_CH1) && !defined(BSP_USING_TIM8_CH2) && \
26 !defined(BSP_USING_TIM8_CH3) && !defined(BSP_USING_TIM8_CH4)
27 #error "Please define at least one BSP_USING_TIMx_CHx"
28 #endif
29 #endif /* RT_USING_PWM */
30
31 #define MAX_PERIOD 65535
32 #define MIN_PERIOD 3
33
34 #ifdef BSP_USING_PWM
35
36 struct n32_pwm
37 {
38 TIM_Module *tim_handle;
39 const char *name;
40 struct rt_device_pwm pwm_device;
41 int8_t tim_en;
42 uint8_t ch_en;
43 uint32_t period;
44 uint32_t psc;
45 };
46
47 static struct n32_pwm n32_pwm_obj[] =
48 {
49 #if defined(BSP_USING_TIM1_CH1) || defined(BSP_USING_TIM1_CH2) || \
50 defined(BSP_USING_TIM1_CH3) || defined(BSP_USING_TIM1_CH4)
51 {
52 .tim_handle = TIM1,
53 .name = "tim1pwm",
54 },
55 #endif
56
57 #if defined(BSP_USING_TIM2_CH1) || defined(BSP_USING_TIM2_CH2) || \
58 defined(BSP_USING_TIM2_CH3) || defined(BSP_USING_TIM2_CH4)
59 {
60 .tim_handle = TIM2,
61 .name = "tim2pwm",
62 },
63 #endif
64
65 #if defined(BSP_USING_TIM3_CH1) || defined(BSP_USING_TIM3_CH2) || \
66 defined(BSP_USING_TIM3_CH3) || defined(BSP_USING_TIM3_CH4)
67 {
68 .tim_handle = TIM3,
69 .name = "tim3pwm",
70 },
71 #endif
72
73 #if defined(BSP_USING_TIM4_CH1) || defined(BSP_USING_TIM4_CH2) || \
74 defined(BSP_USING_TIM4_CH3) || defined(BSP_USING_TIM4_CH4)
75 {
76 .tim_handle = TIM4,
77 .name = "tim4pwm",
78 },
79 #endif
80
81 #if defined(BSP_USING_TIM5_CH1) || defined(BSP_USING_TIM5_CH2) || \
82 defined(BSP_USING_TIM5_CH3) || defined(BSP_USING_TIM5_CH4)
83 {
84 .tim_handle = TIM5,
85 .name = "tim5pwm",
86 },
87 #endif
88
89 #if defined(BSP_USING_TIM8_CH1) || defined(BSP_USING_TIM8_CH2) || \
90 defined(BSP_USING_TIM8_CH3) || defined(BSP_USING_TIM8_CH4)
91 {
92 .tim_handle = TIM8,
93 .name = "tim8pwm",
94 }
95 #endif
96
97 };
98
99 static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg);
100 static struct rt_pwm_ops drv_ops =
101 {
102 drv_pwm_control
103 };
104
drv_pwm_enable(struct n32_pwm * pwm_dev,struct rt_pwm_configuration * configuration,rt_bool_t enable)105 static rt_err_t drv_pwm_enable(struct n32_pwm *pwm_dev, struct rt_pwm_configuration *configuration, rt_bool_t enable)
106 {
107 /* Get the value of channel */
108 rt_uint32_t channel = configuration->channel;
109 TIM_Module *TIMx = pwm_dev->tim_handle;
110
111 if (enable)
112 {
113 pwm_dev->ch_en |= 0x1 << channel;
114 }
115 else
116 {
117 pwm_dev->ch_en &= ~(0x1 << channel);
118 }
119
120 if (enable)
121 {
122 if (channel == 1)
123 {
124 TIM_EnableCapCmpCh(TIMx, TIM_CH_1, TIM_CAP_CMP_ENABLE);
125 }
126 else if (channel == 2)
127 {
128 TIM_EnableCapCmpCh(TIMx, TIM_CH_2, TIM_CAP_CMP_ENABLE);
129 }
130 else if (channel == 3)
131 {
132 TIM_EnableCapCmpCh(TIMx, TIM_CH_3, TIM_CAP_CMP_ENABLE);
133 }
134 else if (channel == 4)
135 {
136 TIM_EnableCapCmpCh(TIMx, TIM_CH_4, TIM_CAP_CMP_ENABLE);
137 }
138 }
139 else
140 {
141 if (channel == 1)
142 {
143 TIM_EnableCapCmpCh(TIMx, TIM_CH_1, TIM_CAP_CMP_DISABLE);
144 }
145 else if (channel == 2)
146 {
147 TIM_EnableCapCmpCh(TIMx, TIM_CH_2, TIM_CAP_CMP_DISABLE);
148 }
149 else if (channel == 3)
150 {
151 TIM_EnableCapCmpCh(TIMx, TIM_CH_3, TIM_CAP_CMP_DISABLE);
152 }
153 else if (channel == 4)
154 {
155 TIM_EnableCapCmpCh(TIMx, TIM_CH_4, TIM_CAP_CMP_DISABLE);
156 }
157 }
158
159 if (pwm_dev->ch_en)
160 {
161 pwm_dev->tim_en = 0x1;
162 TIM_Enable(TIMx, ENABLE);
163 }
164 else
165 {
166 pwm_dev->tim_en = 0x0;
167 TIM_Enable(TIMx, DISABLE);
168 }
169
170 return RT_EOK;
171 }
172
drv_pwm_get(struct n32_pwm * pwm_dev,struct rt_pwm_configuration * configuration)173 static rt_err_t drv_pwm_get(struct n32_pwm *pwm_dev, struct rt_pwm_configuration *configuration)
174 {
175 RCC_ClocksType RCC_Clockstruct;
176 rt_uint32_t ar, div, cc1, cc2, cc3, cc4;
177 rt_uint64_t tim_clock;
178 rt_uint32_t channel = configuration->channel;
179 TIM_Module *TIMx = pwm_dev->tim_handle;
180
181 ar = TIMx->AR;
182 div = TIMx->PSC;
183 cc1 = TIMx->CCDAT1;
184 cc2 = TIMx->CCDAT2;
185 cc3 = TIMx->CCDAT3;
186 cc4 = TIMx->CCDAT4;
187
188 RCC_GetClocksFreqValue(&RCC_Clockstruct);
189
190 tim_clock = RCC_Clockstruct.Pclk2Freq;
191
192 /* Convert nanosecond to frequency and duty cycle. */
193 tim_clock /= 1000000UL;
194 configuration->period = (ar + 1) * (div + 1) * 1000UL / tim_clock;
195 if (channel == 1)
196 configuration->pulse = (cc1 + 1) * (div + 1) * 1000UL / tim_clock;
197 if (channel == 2)
198 configuration->pulse = (cc2 + 1) * (div + 1) * 1000UL / tim_clock;
199 if (channel == 3)
200 configuration->pulse = (cc3 + 1) * (div + 1) * 1000UL / tim_clock;
201 if (channel == 4)
202 configuration->pulse = (cc4 + 1) * (div + 1) * 1000UL / tim_clock;
203
204 return RT_EOK;
205 }
206
drv_pwm_set(struct n32_pwm * pwm_dev,struct rt_pwm_configuration * configuration)207 static rt_err_t drv_pwm_set(struct n32_pwm *pwm_dev, struct rt_pwm_configuration *configuration)
208 {
209 TIM_Module *TIMx = pwm_dev->tim_handle;
210 rt_uint32_t channel = configuration->channel;
211 rt_uint32_t period;
212 rt_uint64_t psc;
213 rt_uint32_t pulse;
214
215 RCC_ClocksType RCC_Clock;
216 RCC_GetClocksFreqValue(&RCC_Clock);
217 rt_uint64_t input_clock;
218 if ((TIM1 == TIMx) || (TIM8 == TIMx))
219 {
220 RCC_ConfigTim18Clk(RCC_TIM18CLK_SRC_SYSCLK);
221 input_clock = RCC_Clock.SysclkFreq;
222 }
223 else
224 {
225 if (1 == (RCC_Clock.HclkFreq / RCC_Clock.Pclk1Freq))
226 input_clock = RCC_Clock.Pclk1Freq;
227 else
228 input_clock = RCC_Clock.Pclk1Freq * 2;
229 }
230
231 input_clock /= 1000000UL;
232 /* Convert nanosecond to frequency and duty cycle. */
233 period = (unsigned long long)configuration->period * input_clock / 1000ULL;
234 psc = period / MAX_PERIOD + 1;
235 period = period / psc;
236 if (period < MIN_PERIOD)
237 {
238 period = MIN_PERIOD;
239 }
240 if ((pwm_dev->period != period) || (pwm_dev->psc != psc))
241 {
242 /* Tim base configuration */
243 TIM_TimeBaseInitType TIM_TIMeBaseStructure;
244 TIM_InitTimBaseStruct(&TIM_TIMeBaseStructure);
245 TIM_TIMeBaseStructure.Period = period - 1;
246 TIM_TIMeBaseStructure.Prescaler = psc - 1;
247 TIM_TIMeBaseStructure.ClkDiv = 0;
248 TIM_TIMeBaseStructure.CntMode = TIM_CNT_MODE_UP;
249 TIM_InitTimeBase(TIMx, &TIM_TIMeBaseStructure);
250 }
251
252 pulse = (unsigned long long)configuration->pulse * input_clock / psc / 1000ULL;
253 if (pulse > period)
254 {
255 pulse = period;
256 }
257
258 /* PWM1 Mode configuration: Channel1 */
259 OCInitType TIM_OCInitStructure;
260 TIM_InitOcStruct(&TIM_OCInitStructure);
261 TIM_OCInitStructure.OcMode = TIM_OCMODE_PWM1;
262 TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
263 TIM_OCInitStructure.Pulse = pulse;
264 TIM_OCInitStructure.OcPolarity = TIM_OC_POLARITY_HIGH;
265
266 if (channel == 1)
267 {
268 TIM_InitOc1(TIMx, &TIM_OCInitStructure);
269 TIM_ConfigOc1Preload(TIMx, TIM_OC_PRE_LOAD_ENABLE);
270 if (!(pwm_dev->ch_en & (0x1 << channel)))
271 TIM_EnableCapCmpCh(TIMx, TIM_CH_1, TIM_CAP_CMP_DISABLE);
272 }
273 else if (channel == 2)
274 {
275 TIM_InitOc2(TIMx, &TIM_OCInitStructure);
276 TIM_ConfigOc2Preload(TIMx, TIM_OC_PRE_LOAD_ENABLE);
277 if (!(pwm_dev->ch_en & (0x1 << channel)))
278 TIM_EnableCapCmpCh(TIMx, TIM_CH_2, TIM_CAP_CMP_DISABLE);
279 }
280 else if (channel == 3)
281 {
282 TIM_InitOc3(TIMx, &TIM_OCInitStructure);
283 TIM_ConfigOc3Preload(TIMx, TIM_OC_PRE_LOAD_ENABLE);
284 if (!(pwm_dev->ch_en & (0x1 << channel)))
285 TIM_EnableCapCmpCh(TIMx, TIM_CH_3, TIM_CAP_CMP_DISABLE);
286 }
287 else if (channel == 4)
288 {
289 TIM_InitOc4(TIMx, &TIM_OCInitStructure);
290 TIM_ConfigOc4Preload(TIMx, TIM_OC_PRE_LOAD_ENABLE);
291 if (!(pwm_dev->ch_en & (0x1 << channel)))
292 TIM_EnableCapCmpCh(TIMx, TIM_CH_4, TIM_CAP_CMP_DISABLE);
293 }
294
295 TIM_ConfigArPreload(TIMx, ENABLE);
296 TIM_EnableCtrlPwmOutputs(TIMx, ENABLE);
297
298 return RT_EOK;
299 }
300
drv_pwm_control(struct rt_device_pwm * device,int cmd,void * arg)301 static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
302 {
303 struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
304 struct n32_pwm *pwm_dev = (struct n32_pwm *)(device->parent.user_data);
305
306 switch (cmd)
307 {
308 case PWM_CMD_ENABLE:
309 return drv_pwm_enable(pwm_dev, configuration, RT_TRUE);
310 case PWM_CMD_DISABLE:
311 return drv_pwm_enable(pwm_dev, configuration, RT_FALSE);
312 case PWM_CMD_SET:
313 return drv_pwm_set(pwm_dev, configuration);
314 case PWM_CMD_GET:
315 return drv_pwm_get(pwm_dev, configuration);
316 default:
317 return -RT_EINVAL;
318 }
319 }
320
rt_hw_pwm_init(void)321 static int rt_hw_pwm_init(void)
322 {
323 int i = 0;
324 int result = RT_EOK;
325
326 for (i = 0; i < sizeof(n32_pwm_obj) / sizeof(n32_pwm_obj[0]); i++)
327 {
328 if (rt_device_pwm_register(&n32_pwm_obj[i].pwm_device,
329 n32_pwm_obj[i].name, &drv_ops, &(n32_pwm_obj[i])) == RT_EOK)
330 {
331 /* Init timer pin and enable clock */
332 void n32_msp_tim_init(void *Instance);
333 n32_msp_tim_init(n32_pwm_obj[i].tim_handle);
334 }
335 else
336 {
337 result = -RT_ERROR;
338 }
339 }
340
341 return result;
342 }
343 INIT_BOARD_EXPORT(rt_hw_pwm_init);
344
345 #endif
346
347