若该文为原创文章,转载请注明原文出处。
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_COMPILECURRENT_PATH := $(shell pwd)
obj-m := pwm_drv.obuild: kernel_moduleskernel_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。
如有侵权,或需要完整代码,请及时联系博主。