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

Zephyr 的 Counter alarm

Zephyr 的 Counter 驱动支持“相对闹钟”和“绝对闹钟”两种触发语义。区别在于struct counter_alarm_cfg里的flagsticks的含义。

关键结构体:

struct counter_alarm_cfg { counter_alarm_callback_t callback; //回调 uint32_t ticks; //不同模式下含义不同(见下) void *user_data; //给callback做回调参数 uint32_t flags; //标志闹钟模式 };

常用标志位(flags

  • alarm_cfg.flags = COUNTER_ALARM_CFG_ABSOLUTE
    绝对闹钟ticks表示计数器周期空间内的绝对计数值(例如下一次的目标计数点)。需要你自己处理取模(wrap)。
  • 缺省(alarm_cfg.flags = 0
    相对闹钟ticks表示相对当前的延迟,即“从现在开始延迟多少 ticks 后触发”。

设定闹钟函数

intcounter_set_channel_alarm(conststructdevice*dev,uint8_tchannel_id,conststructcounter_alarm_cfg*alarm_cfg);

不同模式下ticks的含义

相对闹钟

相对闹钟alarm_cfg.flags = 0

  • ticks表示从现在起ticks后触发(相对当前计数值),通常允许的最大延迟受计数器的拓展/回卷周期(top)以及驱动“保护期(guard period)”限制。

  • 使用情况:需求是“每隔固定时长触发”(周期性任务),最简单且不需要考虑取模。注意不要累加延迟。

  • 参考代码实现,通过信号量释放while循环阻塞,1s触发一次:

#include<zephyr/drivers/counter.h>staticstructcounter_alarm_cfgalarm_cfg;staticuint32_tperiod_ticks;staticstructk_semsem;staticvoidalarm_cb(conststructdevice*dev,uint8_tchan_id,uint32_tticks,void*user_data){structcounter_alarm_cfg*config=user_data;// 周期性:固定相对延迟为 period_ticks(不要累加)// config.ticks = period_ticks; 这个不用动interr=counter_set_channel_alarm(dev,chan_id,&config);if(err){printk("re-arm failed: %d\n",err);}k_sem_give(&sem);}voidmain(void){conststructdevice*dev=DEVICE_DT_GET(TIMER);// 你的计时器设备if(!device_is_ready(dev)){printk("counter not ready\n");return;}k_sem_init(&sem,0,1);// 计算 1 秒对应的 ticksperiod_ticks=counter_us_to_ticks(dev,1000000U);//(可选)设置保护期,避免过近设置失败//counter_set_guard_period(dev, counter_us_to_ticks(dev, 200U), COUNTER_GUARD_PERIOD_LATE);// 启动计数器counter_start(dev);// 首次设置:相对 1 秒后触发alarm_cfg.flags=0;// 相对模式alarm_cfg.ticks=period_ticks;// 相对延迟alarm_cfg.callback=alarm_cb;alarm_cfg.user_data=&alarm_cfg;// 让回调能访问配置interr=counter_set_channel_alarm(dev,0,&alarm_cfg);if(err){printk("set alarm failed: %d\n",err);}while(1){k_sem_take(&sem,K_FOREVER);// 可在此做一些cycle性质的工作}}

绝对闹钟

绝对闹钟alarm_cfg.flags = COUNTER_ALARM_CFG_ABSOLUTE

  • ticks表示计数器周期空间内的绝对目标值(比如“当计数值到 N 时触发”)。

  • 使用情况:

    需要保证你设置的下一个闹钟值落在[0, top)区间内。所以需要注意自己取模。如果不做取模,传入的绝对值超出范围,驱动一般会返回-EINVAL

    如果计数器是向下计数,你可以用原始硬件计数空间或把它转换成统一的“向上空间”,但要一致

  • 参考代码实现

#include<zephyr/drivers/counter.h>#include<zephyr/kernel.h>#include<zephyr/sys/printk.h>staticstructcounter_alarm_cfgalarm_cfg;staticuint32_tperiod_ticks;staticuint32_ttop;staticstructk_semsem;staticvoidalarm_cb(conststructdevice*dev,uint8_tchan_id,uint32_tfired_ticks,void*user_data){ARG_UNUSED(user_data);// fired_ticks 是这次触发的绝对计数值(在周期空间内)// 下一个绝对触发点 = 本次触发点 + 周期(取模 top)uint64_tnext=(uint64_t)fired_ticks+(uint64_t)period_ticks;uint32_tnext_ticks=(uint32_t)(next%top);printk("Alarm fired (absolute). now=%u next=%u\n",fired_ticks,next_ticks);alarm_cfg.ticks=next_ticks;alarm_cfg.flags=COUNTER_ALARM_CFG_ABSOLUTE;interr=counter_set_channel_alarm(dev,chan_id,&alarm_cfg);if(err){printk("re-arm failed: %d\n",err);}k_sem_give(&sem);}voidmain(void){conststructdevice*dev=DEVICE_DT_GET(TIMER);if(!device_is_ready(dev)){printk("counter not ready\n");return;}k_sem_init(&sem,0,1);period_ticks=counter_us_to_ticks(dev,1000000U);top=counter_get_top_value(dev);counter_start(dev);// 读取当前绝对计数值作为起点uint32_tnow;interr=counter_get_value(dev,&now);if(err){printk("get value failed: %d\n",err);return;}// 第一次触发点 = 当前值 + 周期(取模)uint32_tfirst=(now+period_ticks)%top;alarm_cfg.flags=COUNTER_ALARM_CFG_ABSOLUTE;alarm_cfg.ticks=first;// 绝对目标值alarm_cfg.callback=alarm_cb;alarm_cfg.user_data=&alarm_cfg;err=counter_set_channel_alarm(dev,0,&alarm_cfg);if(err){printk("set alarm failed: %d\n",err);}while(1){k_sem_take(&sem,K_FOREVER);// 与回调同步}}
http://www.cnnetsun.cn/news/7803.html

相关文章:

  • 记录:Spring异步执行的报异常No qualifying bean of type ‘org.springframework.core.task.TaskExecutor‘ available
  • 从零定义Agentic Apps:Docker Compose配置实战(附10个高可用场景案例)
  • 亲测3款降AI率工具!知网AI率从87%降到15%,免费降AI技巧+避坑测评全攻略
  • Kafka 的自动提交机制详解:Spring Boot 中如何正确使用?
  • PAT 1135 Is It A Red-Black Tree
  • YOLOv8-Ultralytics 系列文章目录
  • 自动化运维工程师之ansible启动rpcbind和nfs服务
  • 数字供应链系统哪个好?2025 供应链系统推荐排名来了,八大供应链系统
  • M.I.B.终极指南:解锁汽车娱乐系统的隐藏功能
  • 把 ABAP CDS 讲清楚:从 ABAP 7.40 SP05 的语义建模,到 SP08 的函数、参数化与扩展视图
  • 终极PHP兼容性检查工具:轻松应对版本迁移挑战
  • Kamailio usrloc 细节测试
  • 探索STM32单片机仿真温湿度采集控制系统
  • MediaPipe实时多模态感知:从单点检测到全身协同追踪的技术革命
  • SMDJ33A单向 TVS瞬态抑制二极管 :33V电压000W 浪涌,中压电路防护核心
  • MCP 2025量子编程认证重大升级(新增内容全曝光)
  • Bottles:让Windows软件在Linux上轻松运行的智能解决方案
  • 日志框架问答整理(吊打面试官)
  • 从零到安全工程师:2025年必备技能树详解(附实战学习蓝图)
  • Komikku:免费开源的Android漫画阅读器终极指南
  • 长耗时接口异步改造总结
  • 解码人类智慧密码——贾子五定律(Kucius Five Laws):贾子认知、历史、战略、军事、文明五定律
  • 启点创新智慧景区小程序系统,景区智能化售票系统,景区购票管理系统
  • 3种快速安装readr数据读取工具的方法:从入门到精通
  • 对比实测:传统vs自动化VMware安装,效率提升300%
  • 跨平台字体革命:PingFangSC字体包的终极解决方案
  • 14 类圣诞核心 SVG 交互方案拆解(附案例 + 资源)
  • 7个技巧轻松搞定Node.js版本升级:从16.x到20.x的无痛迁移指南
  • MCP SC-400配置避坑手册(一线专家亲授10大常见错误)
  • Ghost没落、同行消失,深度却靠国产系统翻盘?关键点不止一个!