Skip to content

Commit de29569

Browse files
committed
新增多路pwm驱动+配置
1 parent d64c05d commit de29569

29 files changed

Lines changed: 5403 additions & 4930 deletions

libraries/HAL_Drivers/drv_pwm.c

Lines changed: 147 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,66 @@ struct ifx_pwm
2222
{
2323
struct rt_device_pwm pwm_device;
2424
const cy_stc_tcpwm_pwm_config_t *tcpwm_pwm_config;
25-
TCPWM_Type *base;
26-
uint32_t cntNum;
27-
rt_uint8_t channel;
25+
const mtb_hal_pwm_configurator_t *hal_cfg;
2826
const char *name;
29-
uint32_t clk_dst;
30-
cy_en_divider_types_t clk_divType;
31-
uint32_t clk_divNum;
3227
};
3328

3429
static struct ifx_pwm ifx_pwm_obj[] =
3530
{
36-
#ifdef BSP_USING_PWM18
37-
#ifdef TCPWM_0_GRP_1_PWM_9_CONFIG
38-
TCPWM_0_GRP_1_PWM_9_CONFIG,
39-
#endif
40-
#endif
31+
IFX_PWM_DEVICE_LIST
32+
{
33+
.tcpwm_pwm_config = RT_NULL,
34+
.hal_cfg = RT_NULL,
35+
.name = RT_NULL,
36+
}
4137
};
4238

4339

4440
#ifndef IFX_PWM_MAX_TICKS
4541
#define IFX_PWM_MAX_TICKS 65535U
4642
#endif
4743

44+
#ifndef IFX_PWM_DEFAULT_CHANNEL
45+
#define IFX_PWM_DEFAULT_CHANNEL 1U
46+
#endif
47+
48+
static inline TCPWM_Type *ifx_pwm_get_base(struct ifx_pwm *pwm)
49+
{
50+
if ((pwm == RT_NULL) || (pwm->hal_cfg == RT_NULL))
51+
return RT_NULL;
52+
53+
return pwm->hal_cfg->base;
54+
}
55+
56+
static inline uint32_t ifx_pwm_get_cntnum(struct ifx_pwm *pwm)
57+
{
58+
if ((pwm == RT_NULL) || (pwm->hal_cfg == RT_NULL))
59+
return 0U;
60+
61+
return pwm->hal_cfg->cntnum;
62+
}
63+
64+
static inline const mtb_hal_peri_div_t *ifx_pwm_get_clock_ref(struct ifx_pwm *pwm)
65+
{
66+
if ((pwm == RT_NULL) || (pwm->hal_cfg == RT_NULL) ||
67+
(pwm->hal_cfg->clock == RT_NULL) || (pwm->hal_cfg->clock->clock_ref == RT_NULL))
68+
{
69+
return RT_NULL;
70+
}
71+
72+
return (const mtb_hal_peri_div_t *)pwm->hal_cfg->clock->clock_ref;
73+
}
74+
4875
static inline uint32_t ifx_pwm_get_clock(struct ifx_pwm *pwm)
4976
{
50-
return Cy_SysClk_PeriPclkGetFrequency((en_clk_dst_t)pwm->clk_dst,
51-
pwm->clk_divType,
52-
pwm->clk_divNum);
77+
const mtb_hal_peri_div_t *clock_ref = ifx_pwm_get_clock_ref(pwm);
78+
79+
if (clock_ref == RT_NULL)
80+
return 0U;
81+
82+
return Cy_SysClk_PeriPclkGetFrequency((en_clk_dst_t)clock_ref->clk_dst,
83+
clock_ref->div_type,
84+
clock_ref->div_num);
5385
}
5486

5587
static inline int ifx_pwm_check_clk(struct ifx_pwm *pwm, uint32_t *clk)
@@ -63,6 +95,24 @@ static inline int ifx_pwm_check_clk(struct ifx_pwm *pwm, uint32_t *clk)
6395
return RT_EOK;
6496
}
6597

98+
static inline rt_err_t ifx_pwm_check_cfg(struct ifx_pwm *pwm, const struct rt_pwm_configuration *cfg)
99+
{
100+
if (!pwm || ifx_pwm_get_base(pwm) == RT_NULL)
101+
return -RT_ERROR;
102+
103+
if (cfg == RT_NULL)
104+
return -RT_EINVAL;
105+
106+
/* Single-channel PWM devices keep compatibility with channel 0 and default channel(1). */
107+
if ((cfg->channel != 0U) && (cfg->channel != IFX_PWM_DEFAULT_CHANNEL))
108+
{
109+
LOG_E("%s: unsupported channel %u", pwm->name ? pwm->name : "ifx_pwm", cfg->channel);
110+
return -RT_EINVAL;
111+
}
112+
113+
return RT_EOK;
114+
}
115+
66116
static inline uint64_t ns_to_ticks(uint64_t ns, uint32_t clk)
67117
{
68118
if (clk == 0U)
@@ -79,20 +129,25 @@ static inline uint64_t ns_to_ticks(uint64_t ns, uint32_t clk)
79129
static rt_err_t drv_pwm_enable(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration, rt_bool_t enable)
80130
{
81131
struct ifx_pwm *pwm = (struct ifx_pwm *)device->parent.user_data;
132+
rt_err_t ret;
133+
TCPWM_Type *base;
134+
uint32_t cntNum;
82135

83-
(void)configuration;
136+
ret = ifx_pwm_check_cfg(pwm, configuration);
137+
if (ret != RT_EOK)
138+
return ret;
84139

85-
if (!pwm || pwm->base == RT_NULL)
86-
return -RT_ERROR;
140+
base = ifx_pwm_get_base(pwm);
141+
cntNum = ifx_pwm_get_cntnum(pwm);
87142

88143
if (!enable)
89144
{
90-
Cy_TCPWM_PWM_Disable(pwm->base, pwm->cntNum);
145+
Cy_TCPWM_PWM_Disable(base, cntNum);
91146
}
92147
else
93148
{
94-
Cy_TCPWM_PWM_Enable(pwm->base, pwm->cntNum);
95-
Cy_TCPWM_TriggerStart_Single(pwm->base, pwm->cntNum);
149+
Cy_TCPWM_PWM_Enable(base, cntNum);
150+
Cy_TCPWM_TriggerStart_Single(base, cntNum);
96151
}
97152

98153
return RT_EOK;
@@ -101,10 +156,20 @@ static rt_err_t drv_pwm_enable(struct rt_device_pwm *device, struct rt_pwm_confi
101156
static rt_err_t drv_pwm_set_period(struct ifx_pwm *pwm, struct rt_pwm_configuration *configuration)
102157
{
103158
uint32_t clk;
159+
uint32_t cntNum;
160+
TCPWM_Type *base;
161+
rt_err_t ret;
162+
163+
ret = ifx_pwm_check_cfg(pwm, configuration);
164+
if (ret != RT_EOK)
165+
return ret;
104166

105167
if (ifx_pwm_check_clk(pwm, &clk) != RT_EOK)
106168
return -RT_ERROR;
107169

170+
base = ifx_pwm_get_base(pwm);
171+
cntNum = ifx_pwm_get_cntnum(pwm);
172+
108173
uint64_t period_ns = configuration->period;
109174
uint64_t ticks = ns_to_ticks(period_ns, clk);
110175

@@ -120,22 +185,32 @@ static rt_err_t drv_pwm_set_period(struct ifx_pwm *pwm, struct rt_pwm_configurat
120185
if (ticks > IFX_PWM_MAX_TICKS)
121186
ticks = IFX_PWM_MAX_TICKS;
122187

123-
Cy_TCPWM_PWM_SetPeriod0(pwm->base, pwm->cntNum, (uint32_t)ticks);
188+
Cy_TCPWM_PWM_SetPeriod0(base, cntNum, (uint32_t)ticks);
124189

125190
return RT_EOK;
126191
}
127192

128193
static rt_err_t drv_pwm_set_pulse(struct ifx_pwm *pwm, struct rt_pwm_configuration *configuration)
129194
{
130195
uint32_t clk;
196+
uint32_t cntNum;
197+
TCPWM_Type *base;
198+
rt_err_t ret;
199+
200+
ret = ifx_pwm_check_cfg(pwm, configuration);
201+
if (ret != RT_EOK)
202+
return ret;
131203

132204
if (ifx_pwm_check_clk(pwm, &clk) != RT_EOK)
133205
return -RT_ERROR;
134206

207+
base = ifx_pwm_get_base(pwm);
208+
cntNum = ifx_pwm_get_cntnum(pwm);
209+
135210
uint64_t pulse_ns = configuration->pulse;
136211
uint64_t ticks = ns_to_ticks(pulse_ns, clk);
137212

138-
uint32_t period_ticks = Cy_TCPWM_PWM_GetPeriod0(pwm->base, pwm->cntNum);
213+
uint32_t period_ticks = Cy_TCPWM_PWM_GetPeriod0(base, cntNum);
139214

140215
if (period_ticks == 0)
141216
{
@@ -148,7 +223,7 @@ static rt_err_t drv_pwm_set_pulse(struct ifx_pwm *pwm, struct rt_pwm_configurati
148223
ticks = period_ticks;
149224
}
150225

151-
Cy_TCPWM_PWM_SetCompare0Val(pwm->base, pwm->cntNum, (uint32_t)ticks);
226+
Cy_TCPWM_PWM_SetCompare0Val(base, cntNum, (uint32_t)ticks);
152227

153228
return RT_EOK;
154229
}
@@ -157,10 +232,20 @@ static rt_err_t drv_pwm_set(struct rt_device_pwm *device, struct rt_pwm_configur
157232
{
158233
struct ifx_pwm *pwm = (struct ifx_pwm *)device->parent.user_data;
159234
uint32_t clk;
235+
uint32_t cntNum;
236+
TCPWM_Type *base;
237+
rt_err_t ret;
238+
239+
ret = ifx_pwm_check_cfg(pwm, configuration);
240+
if (ret != RT_EOK)
241+
return ret;
160242

161243
if (ifx_pwm_check_clk(pwm, &clk) != RT_EOK)
162244
return -RT_ERROR;
163245

246+
base = ifx_pwm_get_base(pwm);
247+
cntNum = ifx_pwm_get_cntnum(pwm);
248+
164249
uint64_t period_ticks = ns_to_ticks(configuration->period, clk);
165250
uint64_t pulse_ticks = ns_to_ticks(configuration->pulse, clk);
166251

@@ -179,8 +264,8 @@ static rt_err_t drv_pwm_set(struct rt_device_pwm *device, struct rt_pwm_configur
179264
if (period_ticks > IFX_PWM_MAX_TICKS)
180265
period_ticks = IFX_PWM_MAX_TICKS;
181266

182-
Cy_TCPWM_PWM_SetPeriod0(pwm->base, pwm->cntNum, (uint32_t)period_ticks);
183-
Cy_TCPWM_PWM_SetCompare0Val(pwm->base, pwm->cntNum, (uint32_t)pulse_ticks);
267+
Cy_TCPWM_PWM_SetPeriod0(base, cntNum, (uint32_t)period_ticks);
268+
Cy_TCPWM_PWM_SetCompare0Val(base, cntNum, (uint32_t)pulse_ticks);
184269

185270
return RT_EOK;
186271
}
@@ -189,12 +274,22 @@ static rt_err_t drv_pwm_get(struct rt_device_pwm *device, struct rt_pwm_configur
189274
{
190275
struct ifx_pwm *pwm = (struct ifx_pwm *)device->parent.user_data;
191276
uint32_t clk;
277+
uint32_t cntNum;
278+
TCPWM_Type *base;
279+
rt_err_t ret;
280+
281+
ret = ifx_pwm_check_cfg(pwm, configuration);
282+
if (ret != RT_EOK)
283+
return ret;
192284

193285
if (ifx_pwm_check_clk(pwm, &clk) != RT_EOK)
194286
return -RT_ERROR;
195287

196-
uint32_t period_ticks = Cy_TCPWM_PWM_GetPeriod0(pwm->base, pwm->cntNum);
197-
uint32_t cmp_ticks = Cy_TCPWM_PWM_GetCompare0Val(pwm->base, pwm->cntNum);
288+
base = ifx_pwm_get_base(pwm);
289+
cntNum = ifx_pwm_get_cntnum(pwm);
290+
291+
uint32_t period_ticks = Cy_TCPWM_PWM_GetPeriod0(base, cntNum);
292+
uint32_t cmp_ticks = Cy_TCPWM_PWM_GetCompare0Val(base, cntNum);
198293

199294
configuration->period = (uint64_t)period_ticks * 1000000000ULL / (uint64_t)clk;
200295
configuration->pulse = (uint64_t)cmp_ticks * 1000000000ULL / (uint64_t)clk;
@@ -206,6 +301,14 @@ static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg
206301
{
207302
struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
208303

304+
if ((cmd == PWM_CMD_ENABLE) || (cmd == PWM_CMD_DISABLE) ||
305+
(cmd == PWM_CMD_SET) || (cmd == PWM_CMD_GET) ||
306+
(cmd == PWM_CMD_SET_PERIOD) || (cmd == PWM_CMD_SET_PULSE))
307+
{
308+
if (configuration == RT_NULL)
309+
return -RT_EINVAL;
310+
}
311+
209312
switch (cmd)
210313
{
211314
case PWM_CMD_ENABLE:
@@ -236,16 +339,22 @@ static struct rt_pwm_ops drv_ops = { drv_pwm_control };
236339
static rt_err_t ifx_hw_pwm_init(struct ifx_pwm *device)
237340
{
238341
cy_en_tcpwm_status_t tcpwm_status;
342+
TCPWM_Type *base;
343+
uint32_t cntNum;
344+
239345
RT_ASSERT(device != RT_NULL);
240346

241-
if (!device->tcpwm_pwm_config || !device->base)
347+
if (!device->tcpwm_pwm_config || !device->hal_cfg)
242348
{
243349
LOG_W("%s: tcpwm config or base missing", device->name ? device->name : "ifx_pwm");
244350
return -RT_ERROR;
245351
}
246352

247-
tcpwm_status = Cy_TCPWM_PWM_Init(device->base, device->cntNum, device->tcpwm_pwm_config);
248-
if (CY_RSLT_SUCCESS != tcpwm_status)
353+
base = ifx_pwm_get_base(device);
354+
cntNum = ifx_pwm_get_cntnum(device);
355+
356+
tcpwm_status = Cy_TCPWM_PWM_Init(base, cntNum, device->tcpwm_pwm_config);
357+
if (CY_TCPWM_SUCCESS != tcpwm_status)
249358
{
250359
LOG_E("%s: Initialize the TCPWM block failed", device->name ? device->name : "ifx_pwm");
251360
return -RT_ERROR;
@@ -259,20 +368,14 @@ static int rt_hw_pwm_init(void)
259368
int i;
260369
int result = RT_EOK;
261370
int count = sizeof(ifx_pwm_obj) / sizeof(ifx_pwm_obj[0]);
262-
263-
if (count == 0)
264-
{
265-
LOG_W("No PWM instances configured");
266-
return RT_EOK;
267-
}
371+
int registered = 0;
268372

269373
for (i = 0; i < count; i++)
270374
{
271375
struct ifx_pwm *obj = &ifx_pwm_obj[i];
272376

273-
if (obj->tcpwm_pwm_config == RT_NULL || obj->base == RT_NULL)
377+
if (obj->tcpwm_pwm_config == RT_NULL || obj->hal_cfg == RT_NULL)
274378
{
275-
LOG_W("pwm obj %d not configured (skipped)", i);
276379
continue;
277380
}
278381

@@ -288,6 +391,7 @@ static int rt_hw_pwm_init(void)
288391
if (rt_device_pwm_register(&obj->pwm_device, obj->name, &drv_ops, obj) == RT_EOK)
289392
{
290393
LOG_D("%s register success", obj->name ? obj->name : "ifx_pwm");
394+
registered++;
291395
}
292396
else
293397
{
@@ -296,6 +400,11 @@ static int rt_hw_pwm_init(void)
296400
}
297401
}
298402

403+
if (registered == 0)
404+
{
405+
LOG_W("No PWM instances configured");
406+
}
407+
299408
__exit:
300409
return result;
301410
}

0 commit comments

Comments
 (0)