设计说明
源码说明
源代码位于 bsp/artinchip/
:
-
bsp/artinchip/drv/pwm/drv_pwm.c,PWM Driver 层实现
-
bsp/artinchip/hal/pwm/hal_pwm.c,PWM HAL 层实现
-
bsp/artinchip/include/hal/hal_pwm.h,PWM HAL 层接口头文件
-
bsp/artinchip/drv/epwm/drv_epwm.c,EPWM Driver 层实现
-
bsp/artinchip/hal/pwmcs/hal_epwm.c,EPWM HAL 层实现
-
bsp/artinchip/include/hal/hal_epwm.h,EPWM HAL 层接口头文件
模块架构
PWM/ EPWM 驱动 Driver 层采用 RT-Thread 的 PWM 设备驱动框架。HAL 层也可以支持 Baremetal 方式或配合自定义的设备驱动框架进行使用。(下文仅以 PWM 作为说明,EPWM 同理)

关键流程设计
PWM 驱动的初始化接口通过 INIT_DEVICE_EXPORT(drv_pwm_init)
完成,主要是通过调用 PWM
子系统的接口 rt_device_pwm_register() 注册一个 PWM 设备。
PWM 控制器的初始化过程,主要步骤有:
-
初始化模块的 clk
-
初始化模块的默认参数
-
向设备框架中注册 PWM 设备
数据结构设计
struct aic_pwm_arg { u16 available; u16 id; enum aic_pwm_mode mode; u32 tb_clk_rate; u32 freq; struct aic_pwm_action action0; struct aic_pwm_action action1; u32 period; u32 duty; s32 def_level; enum pwm_polarity polarity; };
struct aic_pwm_action { enum aic_pwm_action_type CBD; enum aic_pwm_action_type CBU; enum aic_pwm_action_type CAD; enum aic_pwm_action_type CAU; enum aic_pwm_action_type PRD; enum aic_pwm_action_type ZRO; };
Driver 层接口设计
struct rt_pwm_ops { rt_err_t (*control)(struct rt_device_pwm *device, int cmd, void *arg); };
函数原型 |
rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg) |
---|---|
功能说明 |
(类似 ioctl 的接口方式)配置一个 PWM 通道 |
参数定义 |
device - 指向 PWM 设备的指针
cmd - ioctl 命令码
arg - 命令参数,指向 struct rt_pwm_configuration 结构的指针
|
返回值 |
0,成功; < 0,失败 |
注意事项 |
- |
HAL 层接口设计
void hal_pwm_ch_init(u32 ch, enum aic_pwm_mode mode, u32 default_level, struct aic_pwm_action *a0, struct aic_pwm_action *a1); int hal_pwm_set(u32 ch, u32 duty_ns, u32 period_ns); int hal_pwm_get(u32 ch, u32 *duty_ns, u32 *period_ns); int hal_pwm_set_polarity(u32 ch, enum pwm_polarity polarity); int hal_pwm_enable(u32 ch); int hal_pwm_disable(u32 ch); int hal_pwm_init(void); int hal_pwm_deinit(void); void hal_pwm_status_show(void);
Demo
void turn_on_lcd_backlight(void) { struct rt_device_pwm *pwm_dev; /* turn on the LCD backlight */ pwm_dev = (struct rt_device_pwm *)rt_device_find("pwm"); /* pwm frequency:100K = 10000ns */ rt_pwm_set(pwm_dev, LCD_PWM_DEV_CHANNEL, 10000, 10000); rt_pwm_enable(pwm_dev, LCD_PWM_DEV_CHANNEL); }