linux内核PWM子系统笔记

目录

一、概念

脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。广泛应用在从测量、通信到功率控制与变换的许多领域中。

嵌入式开发中应用较多的场景为通过pwm控制电机驱动芯片实现pwm调压实现对电机的调速;

pwm主要包括周期 占空比 极性,在cpu中会有相应的寄存器支持对它们的配置,方便开发;

二、硬件设计

硬件连接示意图如图

三、pwm子系统概览

结构框图

驱动文件

linux-5.10/linux-5.10.XXX/drivers/pwm/core.c : pwm的核心层,对外提供pwm控制器的注册、请求、查询等接口;

linux-5.10/linux-5.10.XXX/drivers/pwm/sysfs.c : 用户sysfs文件系统中关于pwm子系统的设备属性文件的支持由此部分代码实现;

linux-5.10/linux-5.10.XXX/drivers/pwm/pwm-XXX.c : 某个芯片平台的具体外设驱动文件,如三星 nxp rockchip等;

linux-5.10/linux-5.10.XXX/include/linux/pwm.h: 主要数据结构的定义和对外函数接口;

编译控制

linux-5.10/linux-5.10.165/drivers/pwm/Makefile 中

obj-$ (CONFIG_PWM) += core.o

obj-$ (CONFIG_PWM_SYSFS) += sysfs.o

obj-$ (CONFIG_PWM_XXXX) += pwm-xxxx.o ,具体芯片厂商的编译配置

内核配置文件中将以上配置使能

四、主要数据结构和API

struct pwm_chip

c 复制代码
struct pwm_chip {
	struct device *dev;
	const struct pwm_ops *ops;
	int base;
	unsigned int npwm; //控制器下有多少使用此控制器的设备默认配置为1

	struct pwm_device * (*of_xlate)(struct pwm_chip *pc,
					const struct of_phandle_args *args);
	unsigned int of_pwm_n_cells;

	/* only used internally by the PWM framework */
	struct list_head list;
	struct pwm_device *pwms; //根据npwm个数分配n个并指向第一个
};

表示一个pwm外设控制器,一个cpu芯片可能有多个pwm控制器,core.c中通过pwm_chips链表管理;

struct pwm_device

c 复制代码
struct pwm_device {
	const char *label;
	unsigned long flags;
	unsigned int hwpwm;
	unsigned int pwm;
	struct pwm_chip *chip; //指向所属的pwm控制器
	void *chip_data;

	struct pwm_args args;
	struct pwm_state state;
	struct pwm_state last;
};

表示一个pwm设备,每个pwm_chip可以控制多个pwm_device;

struct pwm_ops

c 复制代码
struct pwm_ops {
	int (*request)(struct pwm_chip *chip, struct pwm_device *pwm);
	void (*free)(struct pwm_chip *chip, struct pwm_device *pwm);
	int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm,
		       struct pwm_capture *result, unsigned long timeout);
	int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
		     const struct pwm_state *state);
	void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
			  struct pwm_state *state);
	struct module *owner;

	/* Only used by legacy drivers */
	int (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
		      int duty_ns, int period_ns);
	int (*set_polarity)(struct pwm_chip *chip, struct pwm_device *pwm,
			    enum pwm_polarity polarity);
	int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm);
	void (*disable)(struct pwm_chip *chip, struct pwm_device *pwm);
};

内核定义钩子函数模板,需要具体芯片根据外设的设计情况去实现,

pwm-芯片平台中.c的多个文件中都有实现具体实现,并通过指针赋值给pwm_chip的指针成员ops;

static RADIX_TREE(pwm_tree, GFP_KERNEL)

位于core.c 中,使用基数对pwm_device进行快速的插入、删除、查找操作;

五、驱动初始化流程

内核启动后加载、解析设备树文件,通过内核的设备、总线、驱动模型将device的兼容属性和驱动的设备支持表兼容字段匹配后,外设的xxxx_prob函数执行,解析设备树中对pwm控制器的时钟、寄存器等的解析,注册pwm_chip结构;

六、开发步骤

驱动部分

1、芯片驱动文件pwm-xxxx.c 实现

外设寄存器的定义;

实现自定义设备结构体;

实现pwm_chip结构中的ops函数,关注周期 占空比 极性的封装配置;

实现xxx_prob函数;

可以参考各个平台的实现大同小异,这部分主要是芯片原厂开发

2、设备树

根据驱动文件编写设备树中pwm节点,主要包括pwm的时钟、寄存器基地址等;
应用部分

驱动正常加载后会在设备中生成/sys/class/pwm/pwmchipX文件夹,通过export可以向export导出控制的通道,如 echo 0 > export ,生成pwm0目录,目录中有 polarity,period,duty_cycle 和 enable 属性文件,编写应用层代码控制这些属性文件即可;

相关推荐
逻各斯6 分钟前
Ubuntu挂载Windows 磁盘,双系统
linux·运维·ubuntu
ITKEY_9 分钟前
Ubuntu 24.04.1 LTS nginx配置maccms
linux·nginx·ubuntu
猫咪-952732 分钟前
touch详讲
linux·指令
帅大大的架构之路43 分钟前
Could not resolve host: mirrorlist.centos.org
linux·运维·centos
xuehaowang44 分钟前
Ubuntu20.04中EasyConnect启动报错
linux·运维·服务器
凉秋girl1 小时前
JVM vs JDK vs JRE
linux·运维·服务器
pumpkin845142 小时前
Windows上使用VSCode开发linux C++程序
linux·windows·vscode
Dusk_橙子2 小时前
在Linux中,zabbix如何监控脑裂?
linux·运维·zabbix
小林熬夜学编程2 小时前
【Linux网络编程】第二十一弹---深入解析I/O多路转接技术之poll函数:优势、缺陷与实战代码
linux·运维·服务器·开发语言·网络·c++
vvw&3 小时前
如何在 Ubuntu 22.04 上安装和配置邮件服务器教程
linux·运维·服务器·数据库·mysql·ubuntu·邮件服务器