当前位置: 首页 > news >正文

zynq ttc pwm例子

一:ttc pwm

想要使用ttc 产生pwm,需要将ttc使能主控驱动,并自己添加pwm控制驱动,比如想通过呕吐提出产生pwm控制背光

二:设备树修改


&ttc0 {    //主控驱动ttc。此部分是官方内核支持的驱动,drivers\pwm\pwm-cadence.cstatus = "okay";#pwm-cells = <3>;
};usr-backlight {compatible = "pwm-bl-beep";                      //backlight标签,用于设备树匹配pwms = <&ttc0 0 5000000>;                       //背光访问的pwm模块,ttc0,0通道,频率5000000brightness-levels = <0 4 8 16 32 64 128 255>;   //背光等级支持的档位default-brightness-level = <6>;                 //默认背光等级status = "okay";                                //设备节点状态
};

从drivers\pwm\pwm-cadence.c 内核源码知道,ttc设置pwm相关配置,采用static const struct pwm_ops ttc_pwm_ops = {
.apply = ttc_pwm_apply,
.get_state = ttc_pwm_get_state,
};
因此我们可以猜测自己的驱动应该会用到apply 和get_state相关的操作接口。因此可以查看:include\linux\pwm.h,有以下几个接口:

在新版本中需要使用
int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state);
//中断中使用
int pwm_apply_atomic(struct pwm_device *pwm, const struct pwm_state *state);
//一般不用
int pwm_adjust_config(struct pwm_device *pwm);

另外我们可以查看drivers\video\backlight\pwm_bl.c 驱动,可以看到pwm控制部分使用了pwm_apply_might_sleep和pwm_get_state。可以得出我们自己的驱动例子如下:可以根据例子改为beep驱动等

三:驱动例子

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/backlight.h>
#include <linux/pwm.h>
#include <linux/of.h>
#include <linux/of_device.h>// 复用pwm_bl.c中的私有数据结构(定义与通用逻辑一致)
struct pwm_backlight_data {struct pwm_device *pwm;const u32 *levels;          // 亮度等级数组(从设备树获取)unsigned int num_levels;    // 等级数量unsigned int brightness;    // 当前亮度
};// 核心:更新背光亮度(复用pwm_bl的逻辑,适配PWM接口)
static void pwm_backlight_update(struct backlight_device *bl)
{struct pwm_backlight_data *data = bl_get_data(bl);struct pwm_state state;unsigned int brightness = bl->props.brightness;u64 duty_cycle;// 1. 获取当前PWM状态(周期、极性等)pwm_get_state(data->pwm, &state);if (brightness == 0) {// 关闭背光:禁用PWMstate.enabled = false;} else {// 2. 映射亮度等级到占空比(0~255 → 0~period)if (brightness >= data->num_levels)brightness = data->num_levels - 1;u32 level = data->levels[brightness];  // 取当前等级值(如128)// 占空比 = (level / 255) * 周期(保持周期不变)duty_cycle = (u64)state.period * level / 255;state.duty_cycle = clamp_val(duty_cycle, 0, state.period);state.enabled = true;}// 3. 应用PWM状态(根据内核版本选择接口)#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)pwm_apply_might_sleep(data->pwm, &state);  // 新接口#elsepwm_config(data->pwm, state.duty_cycle, state.period);  // 旧接口if (state.enabled)pwm_enable(data->pwm);elsepwm_disable(data->pwm);#endif
}// 背光操作集(绑定到通用框架)
static const struct backlight_ops pwm_bl_ops = {.update_status = pwm_backlight_update,  // 核心更新函数};// 驱动探测函数(解析设备树,初始化资源)
static int pwm_backlight_probe(struct platform_device *pdev)
{struct device *dev = &pdev->dev;struct device_node *np = dev->of_node;struct pwm_backlight_data *data;struct backlight_properties props;struct backlight_device *bl;int ret;// 1. 分配私有数据data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);if (!data)return -ENOMEM;// 2. 解析设备树:亮度等级数组ret = of_property_count_u32_elems(np, "brightness-levels");if (ret <= 0) {dev_err(dev, "missing brightness-levels\n");return -EINVAL;}data->num_levels = ret;data->levels = devm_kcalloc(dev, data->num_levels, sizeof(u32), GFP_KERNEL);if (!data->levels)return -ENOMEM;ret = of_property_read_u32_array(np, "brightness-levels", data->levels, data->num_levels);if (ret) {dev_err(dev, "failed to read brightness-levels\n");return ret;}// 3. 获取PWM设备(从设备树pwms属性)data->pwm = devm_of_pwm_get(dev, np, NULL);if (IS_ERR(data->pwm)) {dev_err(dev, "failed to get PWM: %ld\n", PTR_ERR(data->pwm));return PTR_ERR(data->pwm);}// 4. 初始化背光属性memset(&props, 0, sizeof(props));props.type = BACKLIGHT_RAW;  // 原始亮度(直接映射PWM占空比)props.max_brightness = data->num_levels - 1;  // 最大等级索引// 5. 解析默认亮度等级ret = of_property_read_u32(np, "default-brightness-level", &data->brightness);if (ret)data->brightness = 0;  // 默认关闭data->brightness = clamp_val(data->brightness, 0, props.max_brightness);props.brightness = data->brightness;// 6. 注册背光设备bl = devm_backlight_device_register(dev, dev_name(dev), dev, data, &pwm_bl_ops, &props);if (IS_ERR(bl)) {dev_err(dev, "failed to register backlight\n");return PTR_ERR(bl);}// 7. 初始化亮度(应用默认值)backlight_update_status(bl);platform_set_drvdata(pdev, data);dev_info(dev, "PWM backlight initialized (levels: %u)\n", data->num_levels);return 0;
}// 设备树匹配表(与usr-backlight的compatible匹配)
static const struct of_device_id pwm_bl_of_match[] = {{ .compatible = "pwm-bl-beep" },{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pwm_bl_of_match);// 平台驱动结构体
static struct platform_driver pwm_backlight_driver = {.driver = {.name = "pwm-bl-beep",.of_match_table = pwm_bl_of_match,},.probe = pwm_backlight_probe,
};
module_platform_driver(pwm_backlight_driver);MODULE_AUTHOR("cccc");
MODULE_DESCRIPTION("Zynq TTC PWM Backlight Driver");
MODULE_LICENSE("GPL");

http://www.dtcms.com/a/532627.html

相关文章:

  • 【底层机制】linux IO 为什么要有进程表项、文件表项、v节点表项、i节点表项
  • 怎么用wordpress修改网站源码镇江网站网站建设
  • 设计方案表网站名称汉台网站制作
  • git误合并两分支如何回退
  • 【Linux系统编程】编译器gcc/g++
  • LeetCode 面试经典 150_链表_K 个一组翻转链表(61_25_C++_困难)(四指针法;头插法)
  • 做一个简单网站多少钱建设银行网站买手机
  • Ubuntu 22.04上安装Vivado2023.1(离线方式)
  • 使用 OpenAI SDK 调用阿里云 Qwen 模型:从基础到提示词工程实战
  • HTTPS 高频考点
  • 安徽网站建设 网新线上推广100种方式
  • 东莞专业做网站优化用vs2010做网站登入
  • 若依框架学习第二天:功能改造与问题攻坚实战 (2)
  • 为什么要学深度学习?——从“传统编程”到“数据驱动”的思维跃迁(附AI落地案例)
  • 简述网站建设优坏的评价标准wordpress 手机访问不了
  • 浙江网站改版设计公司网站策划书结尾
  • 网站建设 招标公告域名注册的网站
  • 【OC】UIKit常用组件适配iOS 26
  • 自适应微网站开发舟山网站设计
  • 南京高端网站开发朝城做网站公司
  • 26.UE-游戏逆向-绘制骨骼编号
  • 可做产品预售的网站九江有限公司
  • 设计模式-状态模式(State)
  • 强化学习推荐系统:不同的探索策略——贪心探索策略(4.1)
  • Git学习-1
  • 如何运营一个行业网站dede建设网站
  • 找公司网站建设3网站有哪些后台
  • 15.如何利用ArcGIS提取出线要素数据所经过的格网
  • 数据结构<C++>——数组
  • vidhub v1.3.13 |聚合主流网盘,自动刮削整理影视资源,有网盘会员的可入,或者使用不限速网盘