资讯详情

周期任务框架在裸机、RTOS上的实现

一、任务的类型

操作程序包括响应指令的触发程序、持续操作的保护程序和周期程序。在单片机/嵌入式领域,大多数程序都是定期执行、数据收集、处理、上传等功能。因此,我们需要能够适应各种情况下的周期任务框架。

二、周期、时钟、定时器

先看这篇文章:C/C 使用语言性能分析方法和性能分析工具

我们通常通过高中的周期函数来理解周期的准确性。

以下是关于周期的数学描述:

完成振动所需的时间称为振动周期。

若f(x)作为一个周期函数,它使f(x l)=f(x)最小正数建立在定义域中的任何xl,称为f(x)(基本)周期。

在计算机中完成循环所需的时间;或者访问存储器所需的时间,也称为周期 [4] 。当两个自变量值的整体差等于周期倍数时,两个自变量值的整体函数值相等。f(x 6) =f(x-2)函数周期为T=8。

根据我们的一般理解,周期任务是指每个任务的开始执行时间(或完成任务的时间)是固定时间,还是必须在一段时间内执行一次。

周期任务的第一个表达更接近数学的准确描述。

周期任务的第二种表达更实用。

在行业内,周期任务的表述如下:

周期任务是指计算机系统按一定周期到达并要求运行的任务实例,每个请求称为任务实例,任务实例的任务的开始称为任务实例的到达时间,任务实例务实例的释放时间。

可以看出,该周期任务的描述更准确,并考虑到操作系统对任务的调度。当有一个操作系统时,任务不能直接从创建到执行状态,任务是否执行由操作系统决定。我们能控制的是准备好任务,等待操作系统的分配CPU资源。

因此,我对周期任务的第二种描述应该是行业周期任务表达的白话版。

只要实际的周期任务能够在每段时间内执行一次,即使满足其周期性。


说到周期,我们必须谈论时间和时间,这需要时间基准和时间测量。

因此,我们需要对时钟有一定的了解。我们可以参考这篇文章:了解单片机中的时钟


下面我以VxWorks5.5和RTT以定时器为例。

VxWorks

vxworks定时方法:VxWorks几种常用的延迟方法

image-20220301222742523

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-svUfYOu1-1646148117765)(https://raw.githubusercontent.com/xkyvvv/blogpic2/main/img/20220301222958.png)]

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-vtuTg7Pa-1646148117766)(https://raw.githubusercontent.com/xkyvvv/blogpic2/main/img/20220301223234.png)]

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-iscO42tl-1646148117767)(https://raw.githubusercontent.com/xkyvvv/blogpic2/main/img/20220301223643.png)]

RTT

可参考官方文件:时钟管理

三、周期任务框架

了解上述背景知识后,我们能建立什么样的周期任务框架?

裸机上和在RTOS操作系统上有什么不同。

单片机裸机周期任务框架

分享一篇来自无尽老板的非常非常好的文章。单片机如何制作定时器矩阵,彻底解决各种定时问题?

看完这篇文章,我们知道了单片机裸机编程中的周期任务框架。

RTOS周期任务框架

一般的RTOS创建任务的界面会提供,但创建周期任务的界面可能不会提供。因此,如果你想这样做RTOS在创建周期任务的接口上,我们需要使用定时器和创建任务的接口来生成创建周期任务的接口。当然有的RTOS它提供了一个创建周期任务的界面,比如国内开源RTOS——RT-Thread 。

在RT-Thread 在官方文档提供的示例代码中:

#include <rtthread.h>  /* 定时器控制块 */ static struct rt_timer timer1; static struct rt_timer timer2; static int cnt = 0;  /* 定时器 1 超时函数 */ static void timeout1(void* parameter) { 
             rt_kprintf("periodic timer is timeout\n");     /* 运行 10 次 */     if (cnt >= 9)     { 
                 rt_timer_stop(&timer1);     } }  /* 定时器 2 超时函数 */ static void timeout2(void* parameter)
{ 
        
    rt_kprintf("one shot timer is timeout\n");
}

int timer_static_sample(void)
{ 
        
    /* 初始化定时器 */
    rt_timer_init(&timer1, "timer1",  /* 定时器名字是 timer1 */
                    timeout1, /* 超时时回调的处理函数 */
                    RT_NULL, /* 超时函数的入口参数 */
                    10, /* 定时长度,以 OS Tick 为单位,即 10 个 OS Tick */
                    RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */
    rt_timer_init(&timer2, "timer2",   /* 定时器名字是 timer2 */
                    timeout2, /* 超时时回调的处理函数 */
                      RT_NULL, /* 超时函数的入口参数 */
                      30, /* 定时长度为 30 个 OS Tick */
                    RT_TIMER_FLAG_ONE_SHOT); /* 单次定时器 */

    /* 启动定时器 */
    rt_timer_start(&timer1);
    rt_timer_start(&timer2);
    return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(timer_static_sample, timer_static sample);

仿真运行结果如下:

\ | /
- RT -     Thread Operating System
 / | \     3.1.0 build Aug 24 2018
 2006 - 2018 Copyright by rt-thread team
msh >timer_static_sample
msh >periodic timer is timeout
periodic timer is timeout
one shot timer is timeout
periodic timer is timeout
periodic timer is timeout
periodic timer is timeout
periodic timer is timeout
periodic timer is timeout
periodic timer is timeout
periodic timer is timeout
periodic timer is timeout复制错误复制成功

周期性定时器 1 的超时函数,每 10 个 OS Tick 运行 1 次,共运行 10 次(10 次后调用 rt_timer_stop 使定时器 1 停止运行);单次定时器 2 的超时函数在第 30 个 OS Tick 时运行一次。

对于一些没有提供创建周期任务接口的RTOS,我们就需要自己写了,但是建议在写之前先参考一下成熟的周期任务接口实现,以防写出来的接口有bug。

标签: isco红外线液位传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台