PWM(Pulse Width Modulation)
是脉冲宽度调制的缩写,在嵌入式系统中非常常见。它提供了一种脉冲周期波形的方法,一般用于控制马达、LED
、背光灯等。
本文介绍RK3399 PWM
控制器驱动和调试方法。
一、PWM驱动
1、PWM控制器
RK3399 PWM
控制器框图如下:
RK3399 PWM
控制器特性如下:
1)、4个内置PWM
通道。
2)、可配置为捕获模式(输入)。
3)、可配置为连续模式或单次模式(输出)。
4)、在通道为非激活状态时,处于低功耗模式。
2、PWM配置
RK3399 PWM
配置文件:
1)arch/arm64/boot/dts/rockchip/rk3399.dtsi
PWM
属性配置如下:
pwm0: pwm@ff420000 {
compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
reg = <0x0 0xff420000 0x0 0x10>; ## PWM0寄存器基地址和映射大小
#pwm-cells = <3>;
pinctrl-names = "active";
pinctrl-0 = <&pwm0_pin>; ## PWM0引脚配置
clocks = <&pmucru PCLK_RKPWM_PMU>; ## PWM0时钟源
clock-names = "pwm"; ## PWM0时钟名称
status = "disabled";
};
...
pwm2: pwm@ff420020 {
compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
reg = <0x0 0xff420020 0x0 0x10>;
#pwm-cells = <3>;
pinctrl-names = "active";
pinctrl-0 = <&pwm2_pin>;
clocks = <&pmucru PCLK_RKPWM_PMU>;
clock-names = "pwm";
status = "disabled";
};
PWM
引脚配置如下:
pwm0 {
pwm0_pin: pwm0-pin {
rockchip,pins =
<4 18 RK_FUNC_1 &pcfg_pull_none>; ## 将GPIO4_C2引脚配置为PWM0功能
};
pwm0_pin_pull_down: pwm0-pin-pull-down {
rockchip,pins =
<4 18 RK_FUNC_1 &pcfg_pull_down>;
};
...
};
pwm2 {
pwm2_pin: pwm2-pin {
rockchip,pins =
<1 19 RK_FUNC_1 &pcfg_pull_none>; ## 将GPIO1_C3引脚配置为PWM2功能
};
pwm2_pin_pull_down: pwm2-pin-pull-down {
rockchip,pins =
<1 19 RK_FUNC_1 &pcfg_pull_down>;
};
};
2)arch/arm64/boot/dts/rockchip/rockpi-4-linux.dtsi
使能PWM
配置如下:
&pwm0 {
status = "okay"; ## 使能pwm0
};
vdd_log: vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
regulator-name = "vdd_log";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1400000>;
regulator-always-on;
regulator-boot-on;
/* for rockchip boot on */
rockchip,pwm_id= <2>;
rockchip,pwm_voltage = <900000>;
vin-supply = <&vcc_sys>;
};
&pwm2 {
status = "okay"; ## 使能pwm2
};
其中:
1)、pwms = <&pwm2 0 25000 1>;
`&pwm2`:表示选择`pwm2`通道;
0:`PWM`的设备号;
25000:`PWM`的周期为`40KHZ`,即:1000000000/25000`ns`,25000单位是`ns`。
1:反转极性(`PWM_POLARITY_INVERTED`);0:正常极性(`PWM_POLARITY_NORMAL`)。
2)、PWM0
只打开使能,未被其他模块使用,在系统启动后,可通过sysfs
配置pwmchip0
的相关属性。
3)、PWM2
已经分配给其它模块,在系统启动后,无法通过sysfs
配置pwmchip2
的相关属性。硬上会提示write error: Device or resource busy
。
3、PWM驱动
RK3399 PWM
驱动文件:drivers/pwm/pwm-rockchip.c
,主要关注:
static const struct pwm_ops rockchip_pwm_ops = {
.get_state = rockchip_pwm_get_state,
.apply = rockchip_pwm_apply,
.owner = THIS_MODULE,
};
RK3399 PWM
通道配置调用流程如下:
rockchip_pwm_apply()->
rockchip_pwm_config()
rockchip_pwm_enable()
rockchip_pwm_get_state()
二、PWM调试
下面基于RockPI 4A
单板调试,该单板运行的是Debian
系统。
在系统启动时,会加载hw_intfc.conf
文件,该文件里配置了PWM/UART
等通信接口的使能。如果不打开,即使在rockpi-4-linux.dtsi
里配置PWM status=okay
,在系统启动后,也看不到pwm0/pwm1
通道。
Retrieving file: /hw_intfc.conf
reading /hw_intfc.conf
1718 bytes read in 4 ms (418.9 KiB/s)
dtoverlay number: 0, name:/overlays/console-on-ttyS2.dtbo
dtoverlay number: 1, name:/overlays/spi1-flash.dtbo
hw_conf.valid = 1
hw_conf.pwm0 = 1 ## 使能pwm0通道
hw_conf.pwm1 = 1 ## 使能pwm1通道
hw_conf.uart2 = 0 ## 关闭使能UART2接口
hw_conf.uart4 = 0
hw_conf.spi1 = 1
hw_conf.spi2 = 0
hw_conf.i2c2 = 0
hw_conf.i2c6 = 0
hw_conf.i2c7 = 0
hw_conf.dts_overlay_count = 2
hw_conf.dts_overlay[0] = /overlays/console-on-ttyS2.dtbo
hw_conf.dts_overlay[1] = /overlays/spi1-flash.dtbo
PWM
通道调试命令如下:
0、查看PWM设备
目前每个PWM
控制器下只有1路PWM
设备,方法如下:
root@linaro-alip:/sys/kernel/debug# cat pwm
platform/ff420020.pwm, 1 PWM device
pwm-0 (vdd-log ): requested enabled period: 24997 ns duty: 0 ns polarity: inverse
platform/ff420000.pwm, 1 PWM device
pwm-0 ((null) ): period: 0 ns duty: 0 ns polarity: inverse
1、查看PWM总线设备
root@xiaotianbsp:~# cd /sys/class/pwm/
root@xiaotianbsp:/sys/class/pwm# ls
pwmchip0 pwmchip1 pwmchip2
2、导出PWM
在配置pwmchip0
前,需要将pwmchip0
中的pwm0
导出,方法如下:
root@xiaotianbsp:/sys/class/pwm# cd pwmchip0
root@xiaotianbsp:/sys/class/pwm/pwmchip0# ls
device export npwm power subsystem uevent unexport
root@xiaotianbsp:/sys/class/pwm/pwmchip0# echo 0 > export
## 此时导出pwm0
root@xiaotianbsp:/sys/class/pwm/pwmchip0# ls
device export npwm power pwm0 subsystem uevent unexport
3、配置PWM周期
PWM
周期的单位是ns
,通过配置period
实现,方法如下:
root@xiaotianbsp:/sys/class/pwm/pwmchip0# cd pwm0/
root@xiaotianbsp:/sys/class/pwm/pwmchip0/pwm0# ls
capture duty_cycle enable period polarity power uevent
## 周期1KHZ
root@xiaotianbsp:/sys/class/pwm/pwmchip0/pwm0# echo 1000000 > period
[ 116.102019] ---- rockchip_pwm_apply
[ 116.102348] ---- rockchip_pwm_config
[ 116.102929] ---- rockchip_pwm_get_state
4、配置PWM占空比
duty_cycle
是一个周期中on
的时间,单位是ns
,方法如下:
## 占空比50%,即duty_cycle/period
root@xiaotianbsp:/sys/class/pwm/pwmchip0/pwm0# echo 500000 > duty_cycle
[ 148.418151] ---- rockchip_pwm_apply
[ 148.418472] ---- rockchip_pwm_config
[ 148.418993] ---- rockchip_pwm_get_state
5、配置PWM极性
PWM
极性包括:正常(normal
)和反转(inversed
),通过配置polarity
实现,方法如下:
root@xiaotianbsp:/sys/class/pwm/pwmchip0/pwm0# cat polarity
inversed
root@xiaotianbsp:/sys/class/pwm/pwmchip0/pwm0# echo normal > polarity
[ 193.456890] ---- rockchip_pwm_apply
[ 193.457211] ---- rockchip_pwm_config
[ 193.457541] ---- rockchip_pwm_get_state
6、打开/关闭PWM
配置完成后,可以打开PWM
,此时可以用示波器测量到输出的PWM
波形,方法如下:
## 打开PWM
root@xiaotianbsp:/sys/class/pwm/pwmchip0/pwm0# echo 1 > enable
[ 202.627679] ---- rockchip_pwm_apply
[ 202.628009] ---- rockchip_pwm_config
[ 202.628341] ---- rockchip_pwm_enable
[ 202.628668] ---- rockchip_pwm_get_state
## 关闭PWM
root@xiaotianbsp:/sys/class/pwm/pwmchip0/pwm0# echo 0 > enable
[ 211.909522] ---- rockchip_pwm_apply
[ 211.909851] ---- rockchip_pwm_config
[ 211.910183] ---- rockchip_pwm_enable
[ 211.910510] ---- rockchip_pwm_get_state
7、删除导出PWM
PWM
使用完成后,可以将导出的PWM
删除,方法如下:
root@xiaotianbsp:/sys/class/pwm/pwmchip0/pwm0# cd ..
root@xiaotianbsp:/sys/class/pwm/pwmchip0# ls
device export npwm power pwm0 subsystem uevent unexport
root@xiaotianbsp:/sys/class/pwm/pwmchip0# echo 0 > unexport
## 此时没有pwm0
root@xiaotianbsp:/sys/class/pwm/pwmchip0# ls
device export npwm power subsystem uevent unexport
8、测试已使用PWM
PWM2
已经被使用,此时通过sysfs
访问,会提示Device or resource busy
,操作如下:
root@xiaotianbsp:/sys/class/pwm# cd pwmchip2
root@xiaotianbsp:/sys/class/pwm/pwmchip2# ls
device export npwm power subsystem uevent unexport
root@xiaotianbsp:/sys/class/pwm/pwmchip2# echo 0 > export
-bash: echo: write error: Device or resource busy
注:转载请注明作者。