0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RT-Thread驱动篇:hwtimer重载值算法

RTThread物联网操作系统 来源:RTThread物联网操作系统 作者:RTThread物联网操作 2022-04-01 10:06 次阅读

硬件定时器

区别于 rt-thread 内核实现的两种定时器,这种定时器依赖芯片内置的定时器外设,依靠稳定高速的晶振实现精确定时,可以实现 rt_timer 无法达到的定时精度。硬件定时器最重要的两个参数是定时器时钟和定时器重载值。

定时器时钟越高,定时器精度越高;重载值越大,实现的定时时间越长。

在定时器时钟一定的前提下,重载值就决定了定时器定时时间的准确性。

两种计算重载值算法

hwtimer.c 文件timeout_calc函数实现

 1floatoverflow;
 2floattimeout;
 3rt_uint32_tcounter;
 4inti,index=0;
 5floattv_sec;
 6floatdevi_min=1;
 7floatdevi;
 8
 9/*changedtosecond*/
10overflow=timer->maxcnt/(float)timer->freq;
11tv_sec=tv->sec+tv->usec/(float)1000000;
12
13if(tv_sec< (1/(float)timer->freq))
14{
15/*littletimeout*/
16i=0;
17timeout=1/(float)timer->freq;
18}
19else
20{
21for(i=1;i>0;i++)
22{
23timeout=tv_sec/i;
24
25if(timeout<= overflow)
26{
27counter=timeout*timer->freq;
28devi=tv_sec-(counter/(float)timer->freq)*i;
29/*Minimumcalculationerror*/
30if(devi>devi_min)
31{
32i=index;
33timeout=tv_sec/i;
34break;
35}
36elseif(devi==0)
37{
38break;
39}
40elseif(devi< devi_min)
41{
42devi_min=devi;
43index=i;
44}
45}
46}
47}
48
49timer->cycles=i;
50timer->reload=i;
51timer->period_sec=timeout;
52counter=timeout*timer->freq;
53
54returncounter;

第二种实现,

 1rt_uint32_tcounter,reload;
 2rt_uint32_ttimer_cnt;
 3inti,index=0,n0,n1;
 4floattv_sec;
 5rt_uint32_tdev,dev_min;
 6
 7/*changedtosecond*/
 8tv_sec=tv->sec+tv->usec/(float)1000000.0;
 9timer_cnt=tv_sec*timer->freq;
10
11if(timer_cnt==0){
12timer_cnt=1;
13}
14if(timer_cnt< timer->maxcnt){
15timer->cycles=timer->reload=1;
16timer->period_sec=tv_sec;
17counter=timer_cnt;
18returncounter;
19}
20if(timer_cnt%timer->maxcnt==0){
21timer->cycles=timer->reload=timer_cnt/timer->maxcnt;
22timer->period_sec=tv_sec;
23counter=timer_cnt;
24returncounter;
25}
26n0=timer_cnt/timer->maxcnt+1;
27n1=timer_cnt/2;
28dev_min=n0;
29for(i=n0;i< n1; i++) {
30reload=(rt_uint32_t)(timer_cnt/i);
31dev=timer_cnt-reload*i;
32if(dev==0){
33//end
34index=i;
35break;
36}elseif(dev< dev_min) {
37dev_min=dev;
38index=i;
39}
40}
41timer->cycles=timer->reload=index;
42timer->period_sec=index/timer->freq;
43counter=timer_cnt/index;
44returncounter;

测试环境

定时器频率设定 1M。定时器最大重载值 65535。

系统:win10

IDE:Qt Creator

最大定时范围

两种算法,最主要的差别在于前一种用 float 运算,因为 float 可以表达的值范围更大,定时时间可以更长。

而在 1M 定时器时钟前提下,用 32 位无符号整型 timer_cnt,最大可以处理时间仅有 4294.967295s。

精度 PK

5bb68cf0-b15d-11ec-aa7f-dac502259ad0.jpg

这里不支持嵌入 html 表格,只好贴图了

分别选各个量级的时间,用两种算法计算,第二种算法可以把误差降低到0,但是也暴露出一些问题,在某些时间,例如 3.230970s、12.230970s、14.230970s... 误差是很小,定时器重载值也很小,这是我们不愿意看到的。

第一种算法,在计算大于 1000 的数时,误差也随之增大。比如 1000s 误差为 3.236ms;4293.0s 误差为 64.080ms。

运算速度

测试方法:抽取某几个时间值,循环 1M 次运算,计量 1M 次运算总耗时时间。

5bcaf226-b15d-11ec-aa7f-dac502259ad0.png

从抽取的几个值测试结果看,第一种算法耗时比较稳定,第二种算法对不同值的运算时间差异很大。特别的,3.317s 这个值用第二种算法,1M 次运算总耗时时间可能达到 3000s。

从上一小节的精度比对可以看出,第二种算法对精度要求太高了。下面降低第二种算法的精度,达到和第一种一样的精度再重复一次。修改代码如下

 1if(dev==0){
 2//end
 3index=i;
 4break;
 5}elseif(dev>dev_min){
 6break;
 7}elseif(dev< dev_min) {
 8dev_min=dev;
 9index=i;
10}

再次测试结果:

5bdeafc8-b15d-11ec-aa7f-dac502259ad0.png

我们可以看出来,在相同精度条件下,第二种算法的运算速度比第一种快很多,而且耗时反而变得更集中。

其实,对结束条件再次修正,将dev == 0的严苛误差条件换成dev <= 1也不会出现上面 3000+s 慢速。

 1if(dev<= 1){
 2//end
 3index=i;
 4break;
 5}elseif(dev>dev_min){
 6break;
 7}elseif(dev< dev_min) {
 8dev_min=dev;
 9index=i;
10}

超过 4295s 的超长定时

需要修改rt_uint64_t timer_cnt的定义为 64 位无符号整型rt_uint64_t timer_cnt

又因为定时时间很长很长,对误差要求可以降低一些,对第二种算法做的第二处修改:

1if(dev<= 500){
2//end
3index=i;
4break;
5}elseif(dev< dev_min) {
6dev_min=dev;
7index=i;
8}

5bee09be-b15d-11ec-aa7f-dac502259ad0.png

超长时间,第二种算法的表现也很优秀。第三组数据第一种方法竟然出错了,没算出结果。

下面是 10k 次(没有进行 1W 次是因为有些时间太长了)运算时间统计

5c062dd2-b15d-11ec-aa7f-dac502259ad0.png

返璞归真

以上是对两种算法从不同角度进行的比对测验。看似用 float 可以计算更大的定时数,但是,测试结果并不那么理想。使用 64位整型数计算,可能得到比用 float 更精确的结果。

使用 32 位无符号整型数运算虽然最大定时时间只有 4294.9s 。但是我们也看到了,第一种方法有可能出现计算误差的,当误差超过 1ms 我们用 rt_thread_mdelay 或者 rt-thread 的软/硬定时器,可能结果比硬件定时器更精确了,反而失去了精确定时器的意义。在这个前提下,使用 32 位无符号整型数已经足够了。

算法及测试源码见:

https://gitee.com/thewon/rt_thread_repo/tree/master/user

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 算法
    +关注

    关注

    23

    文章

    4612

    浏览量

    92894
  • 定时器
    +关注

    关注

    23

    文章

    3248

    浏览量

    114809
  • RT-Thread
    +关注

    关注

    31

    文章

    1289

    浏览量

    40132

原文标题:RT-Thread 驱动篇 之 hwtimer 重载值算法

文章出处:【微信号:RTThread,微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【S32K146 RT-Thread】之 使用SFUD组件驱动spi flash

    【S32K146 RT-Thread】之 使用SFUD组件驱动spi flash
    的头像 发表于 11-21 01:05 289次阅读
    【S32K146 <b class='flag-5'>RT-Thread</b>】之 使用SFUD组件<b class='flag-5'>驱动</b>spi flash

    RT-Thread上CAN实践

    开箱测试RT-Thread官方已完成了对英飞凌XMC7200EVK的移植,通过shell可以看到做好了uart3的console。本文将介绍如何进行RT-ThreadCan移植。接下来我们要完成CAN_FD的驱动移植,并正常启动
    的头像 发表于 11-13 01:03 1179次阅读
    <b class='flag-5'>RT-Thread</b>上CAN实践

    【S32K146 RT-thread】之 SPI驱动适配

    概述RT-Thread对SPI总线的驱动,抽象出了spibus的设备驱动,我们基于S32K146的硬件学习spibus设备驱动
    的头像 发表于 11-01 08:11 396次阅读
    【S32K146 <b class='flag-5'>RT-thread</b>】之 SPI<b class='flag-5'>驱动</b>适配

    新书发布——《RT-Thread嵌入式实时操作系统内核、驱动和应用开发技术》

    我们非常高兴地宣布,由郑苗秀、沈鸿飞和廖建尚编著的《RT-Thread嵌入式实时操作系统内核、驱动和应用开发技术》一书正式发布。本书的编写团队由多位在嵌入式和实时操作系统领域有着丰富经验的专家组
    的头像 发表于 09-03 08:06 597次阅读
    新书发布——《<b class='flag-5'>RT-Thread</b>嵌入式实时操作系统内核、<b class='flag-5'>驱动</b>和应用开发技术》

    2024 RT-Thread全球巡回 线下培训火热来袭!

    亲爱的RT-Thread社区成员们:我们非常高兴地宣布,2024年RT-Thread全球开发者线下培训即将拉开帷幕!24年全球巡回培训将覆盖超10座城市及国家,为开发者提供一个深入学习RT-Thread嵌入式开发的绝佳机会。
    的头像 发表于 08-07 08:35 1237次阅读
    2024 <b class='flag-5'>RT-Thread</b>全球巡回 线下培训火热来袭!

    【好书推荐】RT-Thread设备驱动开发指南

    近年来国内芯片产业和物联网产业的快速崛起,行业发展迫切需要更多人才,尤其需要掌握嵌入式操作系统等底层技术的人才。随着RT-Thread被更广泛地应用于行业中,开发者对嵌入式驱动开发的需求越来越
    的头像 发表于 08-01 08:35 642次阅读
    【好书推荐】<b class='flag-5'>RT-Thread</b>设备<b class='flag-5'>驱动</b>开发指南

    RT-Thread 新里程碑达成——GitHub Star 破万!

    RT-Thread实时操作系统开源项目在GitHub上的star数量突破一万!截止发文,RT-Thread作为实时操作系统在业界Star数量排名第一!仓库地址:https://github.com
    的头像 发表于 07-04 08:35 480次阅读
    <b class='flag-5'>RT-Thread</b> 新里程碑达成——GitHub Star 破万!

    6月6日杭州站RT-Thread线下workshop,探索RT-Thread混合部署新模式!

    6月6日下午我们将在杭州举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台上实现同时运行RT-Thread和linux,本次workshop邀请到RT-Thread资深
    的头像 发表于 05-28 08:35 447次阅读
    6月6日杭州站<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!

    4月25日北京站RT-Thread线下workshop,探索RT-Thread混合部署新模式

    4月25日,下午我们将在北京举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台上实现同时运行RT-Thread和linux,本次workshop邀请到RT-Thread资深
    的头像 发表于 04-16 08:35 423次阅读
    4月25日北京站<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式

    4月10日深圳场RT-Thread线下workshop,探索RT-Thread混合部署新模式!

    4月10日我们将在深圳福田举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台上实现同时运行RT-Thread和linux,本次workshop邀请到RT-Thread资深嵌入式软件工程师农晓明老师为您讲
    的头像 发表于 03-27 11:36 825次阅读
    4月10日深圳场<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!

    4月10日深圳场RT-Thread线下workshop,探索RT-Thread混合部署新模式!

    4月10日我们将在深圳福田举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台上实现同时运行RT-Thread和linux,本次workshop邀请到RT-Thread资深
    的头像 发表于 03-27 08:34 537次阅读
    4月10日深圳场<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!

    恩智浦半导体正式加入RT-Thread全球合作伙伴计划!

    前不久,恩智浦半导体正式加入RT-Thread全球合作伙伴计划,成为RT-Thread高级会员合作伙伴。同时,RT-Thread现已成为恩智浦注册合作伙伴(RT-Thread| 简介合
    的头像 发表于 03-14 10:40 624次阅读
    恩智浦半导体正式加入<b class='flag-5'>RT-Thread</b>全球合作伙伴计划!

    RT-Thread驱动开发指南进阶-动手驱动先楫未适配的外设LCD

    经过上一的《《RT-Thread设备驱动开发指南》基础--以先楫bsp的hwtimer设备为例》阐述,可以大致了解到
    的头像 发表于 02-25 11:04 2551次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>驱动</b>开发指南进阶<b class='flag-5'>篇</b>-动手<b class='flag-5'>驱动</b>先楫未适配的外设LCD

    RT-Thread设备驱动开发指南》基础--以先楫bsp的hwtimer设备为例

    一、概述(一)RT-Thread设备驱动RT-Thread设备驱动开发指南》书籍是RT-thread官方出品撰写,系统讲解
    的头像 发表于 02-24 08:16 1663次阅读
    《<b class='flag-5'>RT-Thread</b>设备<b class='flag-5'>驱动</b>开发指南》基础<b class='flag-5'>篇</b>--以先楫bsp的<b class='flag-5'>hwtimer</b>设备为例

    RT-Thread设备驱动开发指南基础—以先楫bsp的hwtimer设备为例

    RT-Thread设备驱动开发指南》书籍是RT-thread官方出品撰写,系统讲解RT-thread IO设备驱动开发方法,从三方面进行讲解
    的头像 发表于 02-20 16:01 1714次阅读
    <b class='flag-5'>RT-Thread</b>设备<b class='flag-5'>驱动</b>开发指南基础<b class='flag-5'>篇</b>—以先楫bsp的<b class='flag-5'>hwtimer</b>设备为例