Linux内核PWM

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/25000ns,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

注:转载请注明作者。

{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/4702401/blog/5607369
PWM