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 属性文件,编写应用层代码控制这些属性文件即可;

相关推荐
落笔太慌张~2 分钟前
Linux系统(Ubuntu和树莓派)的远程操作练习
linux·运维·ubuntu
CZIDC15 分钟前
Linux系统安全-开发中注意哪些操作系统安全
linux·安全·系统安全
czhc114007566318 分钟前
LINUX 5 vim cat zip unzip
linux·编辑器·vim
明灯L1 小时前
《深度剖析 Linux 权限管理:从基础到进阶,解锁系统安全密钥》
linux·运维·全网最全权限管理·小白0基础
是覆盖对于变化2 小时前
ubuntu22.04 进入不了系统设置
linux·ubuntu
应以大橘为重2 小时前
interrupt子系统中的数据结构
linux·数据结构·驱动开发
kfepiza2 小时前
硬盘分区格式方案之 MBR(Master Boot Record)主引导记录详解 笔记250407
linux·windows·笔记
mzak2 小时前
已经安装了pip,出现pip command not found【解决方法】
linux·pip·python3
南风与鱼2 小时前
Linux 线程池
linux·线程池
Mazy.v3 小时前
Linux图形化界面
linux·运维·数据库