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

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

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

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

  • 16
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值