设为首页 加入收藏

TOP

微控制器实时操作系统实践2了解RTOS任务(一)
2023-07-23 13:25:37 】 浏览:64
Tags:时操作 了解 RTOS 任务

2了解RTOS任务

超级循环编程范式通常是嵌入式系统工程师最先接触到的编程方法之一。用超级循环实现的程序有一个单一的顶层循环,在系统需要执行的各种功能之间循环。这些简单的while循环很容易创建和理解(当它们很小的时候)。在FreeRTOS中,任务与超级循环非常相似--主要区别在于,系统可以有一个以上的任务,但只有一个超级循环。

在本章中,我们将仔细研究超级循环和用它们实现一定程度的并行性的不同方法。之后,将对超级循环和任务进行比较,并从理论上介绍任务执行的思维方式。最后,我们将看看任务是如何通过RTOS内核实际执行的,并比较两种基本的调度算法。

超级循环编程介绍

所有的嵌入式系统都有一个共同的特性--它们没有退出点。由于其性质,嵌入式代码通常被期望总是可用的--静静地在后台运行,处理内务工作,并随时准备接受用户的输入。与旨在启动和停止程序的桌面环境不同,如果微控制器退出main()函数,它就没有任何事情可做。如果发生这种情况,很可能是整个设备已经停止运作。由于这个原因,嵌入式系统中的main()函数从不返回。与应用程序不同的是,应用程序是由其主机操作系统启动和停止的,大多数基于嵌入式MCU的应用程序在上电时开始,在系统断电时突然结束。由于这种突然的关闭,嵌入式应用程序通常没有任何通常与应用程序相关的关闭任务,如释放内存和资源。

下面的代码代表了超级循环的基本思想:

void main ( void )
{
    while(1)
    {
        func1();
        func2();
        func3();
        //do useful stuff, but don't return
        //(otherwise, where would we go. . what would we do. . .?!)
    }
}

虽然非常简单,但前面的代码有许多值得指出的特点。while循环从不返回--它一直在执行同样的三个函数(这是故意的)。这三个看似无害的函数调用可以在实时系统中隐藏一些令人讨厌的惊喜。

基本的超级循环

这个从不返回的主循环一般被称为超级循环。超级循环总是很有趣,因为它可以控制系统中的大多数事情--除非超级循环使之发生,否则下图中的任何事情都无法完成。这种类型的设置非常适合于非常简单的系统,只需要执行一些不需要花费大量时间的任务。基本的超级循环结构非常容易编写和理解;如果你想解决的问题可以用一个简单的超级循环来完成,那么就使用一个简单的超级循环。下面是前面介绍的代码的执行流程--每个函数都是按顺序调用的,而且循环永不退出:

实时系统中的超级环路

当简单的超级循环快速运行时(通常是因为它们的功能/责任有限),它们的响应速度相当快。然而,超级循环的简单性可能是一种祝福,也是一种诅咒。由于每个函数总是跟在前面的函数后面,它们总是以相同的顺序被调用,并且完全相互依赖。一个函数引入的任何延迟都会传播到下一个函数,从而导致执行该循环迭代的总时间增加(如下图所示)。如果func1在循环中执行一次需要10毫秒,而下一次需要100毫秒,那么func2在循环中第二次被调用的时间就不会像第一次那样快:

让我们更深入地看一下这个问题。在上图中,func3负责检查一个代表外部事件的标志的状态(这个事件是一个信号的上升沿)。func3检查标志的频率取决于func1和func2执行的时间。一个设计良好、反应灵敏的超级循环通常会执行得非常快,检查事件的频率要比事件发生的频率高(呼出B)。当外部事件确实发生时,该循环直到func3的下一次执行才检测到该事件(呼出A、C和D)。注意,在事件产生和func3检测到它之间有一个延迟。还要注意的是,这个延迟并不总是一致的:这种时间上的差异被称为抖动。

在许多基于超级循环的系统中,与被轮询的缓慢发生的事件相比,超级循环的执行速度非常高。我们在页面上没有足够的空间来显示循环在检测到事件之间执行数百次(或数千次)的迭代!这就是所谓的抖动!

如果系统在响应事件时有一个已知的最大抖动量,它被认为是确定性的。也就是说,它将在事件发生后的指定时间内对事件作出可靠的反应。高水平的确定性对于实时系统中的时间关键型组件是至关重要的,因为如果没有它,系统可能无法及时响应重要的事件。

考虑到循环反复检查硬件标志的事件(这被称为轮询)。循环越紧密,标志被检查的速度就越快--当标志经常被检查时,代码将对感兴趣的事件做出更多的反应。如果我们有需要及时采取行动的事件,我们可以只写非常紧密的循环,等待重要事件的发生。这种方法是有效的--但前提是该事件是系统唯一感兴趣的事情。如果整个系统唯一的责任就是观察该事件(没有后台I/O、通信等),那么这是一个有效的方法。这种类型的情况在今天复杂的现实世界的系统中很少发生。响应性差是单纯基于轮询的系统的局限性。接下来,我们将看看如何在我们的超级循环中获得更多的并行性。

参考资料

用超级循环实现并行操作

尽管基本的超级循环只能按顺序通过函数,但仍有办法实现并行化。单片机有一些不同类型的专用硬件,它们被设计用来减轻CPU的一些负担,同时还能实现高度响应的系统。本节将介绍这些系统以及如何在超级循环风格的程序中使用它们。

中断

对单一事件进行轮询不仅在CPU周期和功率方面是浪费的--它还会导致系统对其他事物没有反应,这通常是应该避免的。那么,我们怎样才能让单核处理器并行地做事情呢?嗯,我们不能--毕竟只有一个处理器。...但由于我们的处理器很可能每秒运行数百万条指令,所以有可能让它执行足够接近于并行的事情。MCU还包括用于生成中断的专用硬件。中断向MCU提供信号,使其在事件发生时直接跳到中断服务程序(ISR interrupt service routine )。这是一个非常关键的功能,ARM Cortex-M内核为其提供了一个标准化的外设,称为嵌套向量中断控制器(NVIC nested vector interrupt controller。NVIC提供了一种处理中断的通用方法。这个术语的嵌套部分标志着即使是中断也可以被其他具有更高优先级的中断打断。这相当方便,因为它允许我们将系统中时间最关键的部分的延迟和抖动量降到最低。

那么,中断如何融入超级循环,以更好地实现并行活动的假象?ISR内部的代码通常被保持得尽可能短,以尽量减少在中断中花费的时间。这一点很重要,有几个原因。如果中断发生得很频繁,而且ISR包含很多指令,那么ISR就有可能在被再次调用之前不返回。对于UART(universal asynchronous receiver / transmitter)或SPI(serial peripheral interface)等通信外设来说,这将意味着数据丢失(这显然是不可取的)。保持代

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇微控制器实时操作系统实践1实时系.. 下一篇【原创】浅谈EtherCAT主站EOE(上)..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目