FreeRTOS系列第9篇---FreeRTOS任务概述

1. 任务和协程(Co-routines)

应用程序可以使用任务也可以使用协程,或者两者混合使用,但是任务和协程使用不同的API函数,因此在任务和协程之间不能使用同一个队列或信号量传递数据。

通常情况下,协程仅用在资源非常少的微处理器中,特别是RAM非常稀缺的情况下。目前协程很少被使用到,因此对于协程FreeRTOS作者既没有把它删除也没有进一步开发。

所以本系列文章以后不会对协程过多描述,包括其API函数。

1.1任务的特性

简而言之:使用RTOS的实时应用程序可认为是一系列独立任务的集合。每个任务在自己的环境中运行,不依赖于系统中的其它任务或者RTOS调度器。在任何时刻,只有一个任务得到运行,RTOS调度器决定运行哪个任务。调度器会不断的启动、停止每一个任务,宏观看上去就像整个应用程序都在执行。作为任务,不需要对调度器的活动有所了解,在任务切入切出时保存上下文环境(寄存器值、堆栈内容)是调度器主要的职责。为了实现这点,每个任务都需要有自己的堆栈。当任务切出时,它的执行环境会被保存在该任务的堆栈中,这样当再次运行时,就能从堆栈中正确的恢复上次的运行环境。

1.2任务概要

  • 简单
  • 没有使用限制
  • 支持完全抢占
  • 支持优先级
  • 每个任务都有自己的堆栈,消耗RAM较多
  • 如果使用抢占,必须小心的考虑可重入问题

2. 任务状态

一个任务可为下面中的一个:

  1. 运行:如果一个任务正在执行,那么说这个任务处于运行状态。此时它占用处理器。
  2. 就绪:就绪的任务已经具备执行的能力(不同于阻塞和挂起),但是因为有一个同优先级或者更高优先级的任务处于运行状态而还没有真正执行。
  3. 阻塞:如果任务当前正在等待某个时序或外部中断,我们就说这个任务处于阻塞状态。比如一个任务调用vTaskDelay()后会阻塞到延时周期到为止。任务也可能阻塞在队列或信号量事件上。进入阻塞状态的任务通常有一个“超时”周期,当事件超时后解除阻塞。
  4. 挂起:处于挂起状态的任务同样对调度器无效。仅当明确的分别调用vTaskSuspend() 和xTaskResume() API函数后,任务才会进入或退出挂起状态。不可以指定超时周期事件(不可以通过设定超时事件而退出挂起状态)

3.任务优先级

每个任务都要被指定一个优先级,从0~configMAX_PRIORITIES,configMAX_PRIORITIES定义在FreeRTOSConfig.h中。

如果某架构硬件支持CLZ(或类似)指令(计算前导零的数目,Cortex-M3是支持该指令的,从ARMv6T2才支持这个指令),并且打算在移植层使用这个特性来优化任务调度机制,需要有一些步骤,首先将FreeRTOSConfig.h中configUSE_PORT_OPTIMISED_TASK_SELECTION设置为1,并且最大优先级数目configMAX_PRIORITIES不能大于32。除此之外,configMAX_PRIORITIES可以设置为任意值,但是考虑到configMAX_PRIORITIES设置越大,RAM消耗也越大,一般设置为满足使用的最小值。

低优先级数值代表低优先级。空闲任务(idle task)的优先级为0(tskIDLE_PRIORITY)。

FreeRTOS调度器确保处于最高优先级的就绪或运行态任务获取处理器,换句话说,处于运行状态的任务,只有其中的最高优先级任务才会运行。

任何数量的任务可以共享同一个优先级。如果宏configUSE_TIME_SLICING未定义或着宏configUSE_TIME_SLICING定义为1,处于就绪态的多个相同优先级任务将会以时间片切换的方式共享处理器。

4.实现一个任务

一个任务具有以下结构:

void vATaskFunction( void *pvParameters )
{
    for( ;; )
    {
        /*-- 应用程序代码放在这里. --*/
    }

    /* 任务不可以从这个函数返回或退出。在较新的FreeRTOS移植包中,如果
    试图从一个任务中返回,将会调用configASSERT()(如果定义的话)。
    如果一个任务确实要退出函数,那么这个任务应调用vTaskDelete(NULL)
    函数,以便处理一些清理工作。*/
    vTaskDelete( NULL );
}

任务函数返回为void,参数只有一个void类型指针。所有的任务函数都应该是这样。void类型指针可以向任务传递任意类型信息。

任务函数决不应该返回,因此通常任务函数都是一个死循环。

任务由xTaskCreate()函数创建,由vTaskDelete()函数删除。

5.空闲任务和空闲任务钩子(idle task和Idle Task hook)

5.1空闲任务

空闲任务是启动RTOS调度器时由内核自动创建的任务,这样可以确保至少有一个任务在运行。空闲任务具有最低任务优先级,这样如果有其它更高优先级的任务进入就绪态就可以立刻让出CPU。

删除任务后,空闲任务用来释放RTOS分配给被删除任务的内存。因此,在应用中使用vTaskDelete()函数后确保空闲任务能获得处理器时间就很重要了。除此之外,空闲任务没有其它有效功能,所以可以被合理的剥夺处理器时间,并且它的优先级也是最低的。

应用程序任务共享空闲任务优先级(tskIDLE_PRIORITY)也是可能的。这种情况如何配置可以参考configIDLE_SHOULE_YIELD配置参数类获取更多信息。

5.2空闲任务钩子

空闲任务钩子是一个函数,每一个空闲任务周期被调用一次。如果你想将任务程序功能运行在空闲优先级上,可以有两种选择:

  1. 在一个空闲任务钩子中实现这个功能:因为FreeRTOS必须至少有一个任务处于就绪或运行状态,因此钩子函数不可以调用可能引起空闲任务阻塞的API函数(比如vTaskDelay()或者带有超时事件的队列或信号量函数)。
  2. 创建一个具有空闲优先级的任务去实现这个功能:这是个更灵活的解决方案,但是会带来更多RAM开销。

创建一个空闲钩子步骤如下:

  • 在FreeRTOSConfig.h头文件中设置configUSE_IDLE_HOOK为1;
  • 定义一个函数,名字和参数原型如下所示:
        void vApplicationIdleHook( void );

通常,使用这个空闲钩子函数设置CPU进入低功耗模式

时间: 2024-09-30 00:27:41

FreeRTOS系列第9篇---FreeRTOS任务概述的相关文章

FreeRTOS系列第2篇---FreeRTOS入门指南【转】

转自:http://blog.csdn.net/zhzht19861011/article/details/49819309 版权声明:本文为博主原创文章,未经博主允许不得转载.联系邮箱:[email protected] 目录(?)[-] 查找相关文档页 获取RTOS源代码 FreeRTOS源码目录结构 编译工程 运行演示例程 FreeRTOS可以被移植到很多不同架构的处理器和编译器.每一个RTOS移植都附带一个已经配置好的演示例程,可以方便快速启动开发.更好的是,每个演示例程都附带一个说明网

FreeRTOS系列第20篇---FreeRTOS信号量API函数

FreeRTOS的信号量包括二进制信号量.计数信号量.互斥信号量(以后简称互斥量)和递归互斥信号量(以后简称递归互斥量).我们可以把互斥量和递归互斥量看成特殊的信号量. 信号量API函数实际上都是宏,它使用现有的队列机制.这些宏定义在semphr.h文件中.如果使用信号量或者互斥量,需要包含semphr.h头文件. 二进制信号量.计数信号量和互斥量信号量的创建API函数是独立的,但是获取和释放API函数都是相同的:递归互斥信号量的创建.获取和释放API函数都是独立的. 1创建二进制信号量 1.1

FreeRTOS系列第10篇---FreeRTOS任务创建和删除

在FreeRTOS移植到Cortex-M3硬件平台的文章中,我们已经见过任务创建API,但那篇文章的重点在于如何移植FreeRTOS,本文将重点放在任务的创建和删除API函数上面. 任务创建和删除API函数位于文件task.c中,需要包含task.h头文件. 1.任务创建 1.1函数描述 BaseType_txTaskCreate( TaskFunction_tpvTaskCode, const char * constpcName, unsigned shortusStackDepth, vo

FreeRTOS系列第8篇---FreeRTOS内存管理

FreeRTOS提供了几个内存堆管理方案,有复杂的也有简单的.其中最简单的管理策略也能满足很多应用的要求,比如对安全要求高的应用,这些应用根本不允许动态内存分配的. FreeRTOS也允许你自己实现内存堆管理,甚至允许你同时使用两种内存堆管理方案.同时实现两种内存堆允许任务堆栈和其它RTOS对象放置到快速的内部RAM,应用数据放置到低速的外部RAM. 每当创建任务.队列.互斥量.软件定时器.信号量或事件组时,RTOS内核会为它们分配RAM.标准函数库中的malloc()和free()函数有些时候

FreeRTOS系列第18篇---FreeRTOS队列API函数

FreeRTOS为操作队列提供了非常丰富的API函数,包括队列的创建.删除,灵活的入队和出队方式.带中断保护的入队和出队等等.下面就来详细讲述这些API函数. 1.获取队列入队信息数目 1.1函数描述 UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue ); 返回队列中存储的信息数目.具有中断保护的版本为uxQueueMessagesWaitingFromISR(),原型为:UBaseType_t uxQueueMessagesWai

FreeRTOS系列第13篇---FreeRTOS内核控制

内核控制的一些功能需要移植层提供,为了方便移植,这些API函数用宏来实现,比如上下文切换.进入和退出临界区.禁止和使能可屏蔽中断.内核控制函数还包括启动和停止调度器.挂起和恢复调度器以及用于低功耗模式的调整系统节拍函数. 1.强制上下文切换宏 taskYIELD:用于强制上下文切换的宏.在中断服务程序中的等价版本为portYIELD_FROM_ISR,这也是个宏,其实现取决于移植层. 用于上下文切换的实际代码由移植层提供.对于Cortex-M3硬件,这个宏会引起PendSV中断. 2.进入临界区

FreeRTOS系列第11篇---FreeRTOS任务控制

FreeRTOS任务控制API函数主要实现任务延时.任务挂起.解除任务挂起.任务优先级获取和设置等功能. 1.相对延时 1.1函数描述 void vTaskDelay( portTickTypexTicksToDelay ) 调用vTaskDelay()函数后,任务会进入阻塞状态,持续时间由vTaskDelay()函数的参数xTicksToDelay指定,单位是系统节拍时钟周期.常量portTICK_RATE_MS 用来辅助计算真实时间,此值是系统节拍时钟中断的周期,单位是毫秒.在文件FreeR

FreeRTOS系列第16篇---可视化追踪调试

使用RTOS编程,为每个任务分配多大的堆栈空间就成了一项技术活:分配多了浪费系统资源,分配少了又恐怕会发生堆栈溢出.由于中断和抢占式调度器的存在,我们要估算出一个任务需要多少堆栈是非常困难的,今天我们就介绍一种方法,来获取每个任务的剩余堆栈空间.本文以NXP LPC177x_8x系列微控制器为例. 我们将这个功能做成一个命令,添加到<FreeRTOS系列第15篇---使用任务通知实现命令行解释器>一文介绍的命令解释列表中.当程序运行一段时间后,我们在SecureCRT软件中输入命令"

解剖SQLSERVER 第七篇 OrcaMDF 特性概述(译)

原文:解剖SQLSERVER 第七篇 OrcaMDF 特性概述(译) 解剖SQLSERVER 第七篇  OrcaMDF 特性概述(译) http://improve.dk/orcamdf-feature-recap/ 时间过得真快,这已经过了大概四个月了自从我最初介绍我的宠物项目OrcaMDF. 自从项目开始到现在,OrcaMDF发生了很多变化,功能更强了,因此我想提供一个概述对目前OrcaMDF的功能的概述以及我对OrcaMDF未来的计划 页面类型 OrcaMDF 当前支持以下页面的数据完整解