若该文为原创文章,转载请注明原文出处。
pwm 子系统功能单一,很少单独使用,一般用于控制显示屏的背光、控制无源蜂鸣器、伺服电机、电压调节等等。
一、PWM介绍
PWM(Pulse width modulation),脉冲宽度调制。在内核中 PWM 驱动较简单,但是麻雀虽小,五脏 俱全,基本的框架是完整的。
pwm 控制器驱动 soc 厂商已经写好,我们要做的是在设备树 (或者是设备树插件) 中开启控制器 节点,描述 pwm 设备节点,然后驱动中调用内核 PWM 提供的接口,来实现 pwm 驱动控制。
二、硬件原理图
PWM 通道与引脚
这里使用GPIO0_C7引脚,复用为pwm功能。
三、设备树修改
修改/home/alientek/rk3568_linux_sdk/kernel/arch/arm64/boot/dts/rockchip/rk3568-atk-evb1-ddr4- v10.dtsi 文件
&pwm0 {
status = "okay";
pinctrl-names = "active";
pinctrl-0 = <&pwm0m1_pins>;
};
&{/} {
pwm_demo: pwm_demo {
status = "okay";
compatible = "pwm_demo";
back {
pwm-names = "pwm-demo";
pwms = <&pwm0 0 10000 1>;
duty_ns = <5000>;
};
};
};
重新编译内核,烧写boot.img文件。
四、驱动
pwm_drv.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/leds.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/leds_pwm.h>
#include <linux/slab.h>
struct pwm_device *pwm_demo; //定义pwm设备结构体
/*简单驱动*/
static int pwm_demo_probe(struct platform_device *pdev)
{
int ret = 0;
struct device *dev = &pdev->dev;
struct device_node *child; // 保存子节点
printk("match success \n");
child = of_get_next_child(dev->of_node, NULL);
if (child)
{
pwm_demo = devm_of_pwm_get(dev, child, NULL);
if (IS_ERR(pwm_demo))
{
printk(KERN_ERR" pwm_demo,get pwm error!!\n");
return -1;
}
}
else
{
printk(KERN_ERR" pwm_demoof_get_next_child error!!\n");
return -1;
}
/*配置频率100KHz 占空比80%*/
pwm_config(pwm_demo, 1000, 5000);
/*反相 频率100KHz 占空比20%*/
pwm_set_polarity(pwm_demo, PWM_POLARITY_INVERSED);
pwm_enable(pwm_demo);
return ret;
}
static int pwm_demo_remove(struct platform_device *pdev)
{
pwm_config(pwm_demo, 0, 5000);
pwm_free(pwm_demo);
return 0;
}
static const struct of_device_id of_pwm_leds_match[] = {
{.compatible = "rockchip,rk3568-pwm",},
{},
};
static struct platform_driver pwm_demo_driver = {
.probe = pwm_demo_probe,
.remove = pwm_demo_remove,
.driver = {
.name = "rockchip,rk3568-pwm",
.of_match_table = of_pwm_leds_match,
},
};
module_platform_driver(pwm_demo_driver);
MODULE_AUTHOR("yifeng");
MODULE_DESCRIPTION("PWM DEMO driver");
MODULE_LICENSE("GPL v2");
makefile
KERNELDIR := /home/alientek/rk3568_linux_sdk/kernel
ARCH=arm64
CROSS_COMPILE=/opt/atk-dlrk356x-toolchain/usr/bin/aarch64-buildroot-linux-gnu-
export ARCH CROSS_COMPILE
CURRENT_PATH := $(shell pwd)
obj-m := pwm_drv.o
build: kernel_modules
kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
五、测试
insmod命令加载驱动
insmod pwm_drv.ko
查看系统当前的PWM状态:
cat /sys/kernel/debug/pwm
我的目的是想改成GPIO3_C5。
如有侵权,或需要完整代码,请及时联系博主。