一、任务基础知识

在STM32F4中以前的单片机裸机(未使用系统)的时候一般都是在mai函数中用循环来处理所有事物,循环调用相应的函数完成事物的处理。有时候也可以通过中断完成一些处理。相对多任务系统而言,这种就是单任务系统,也称作前后台系统,中断服务函数作为前台程序,大循环while(1)作为后台程序。
然而前后台系统的实时性差,前后台系统各个任务(应用程序)都是排队等着轮流执行,不管任务的紧急程度,相当于所有的任务(应用程序)的优先级都是一样的。
多任务系统会把一个大问题(应用程序)“分而治之”。把大问题划成很多的小问题,逐个将小问题解决掉,大问题也就会随之解决。这些小问题是并发处理的,并不是说同一时刻一起执行很多任务,而是由于每个任务执行的时间很短,看起来像同一时刻执行了很多任务。通过FreeRTOS里面的任务调度器完成任务的先后执行。在FreeRTOS中是一个抢占式的实时多任务系统,其任务调度器也是抢占式的。
高优先级的任务可以打断低优先级任务的运行而取得CPU的使用权,这样
就保证了那些紧急任务的运行。这样我们就可以为那些对实时性要求高的任务设置一个很高的优先级,比如自动驾驶中的障碍物检测任务等。高优先级的任务执行完成以后重新把CPU的使用权归还给低优先级的任务,这个就是抢占式多任务系统的基本原理。

二、任务状态

FreeRTOS中的任务永远只有运行态、就绪态、阻塞态、挂起态。
1、运行态
当一个任务正在运行时,那么就说这个任务处于运行态,处于运行态的任务就是当前正在使用处理器的任务。如果使用的是单核处理器的话那么不管在任何时刻永远都只有一个任务处于运行态。
2、就绪态
处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起),可以运行的任务,但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行!
3、阻塞态
如果一个任务当前正在等待某个外部事件的话就说它处于阻塞态,比如说如果某个任务调用了函数vTaskDelay0的话就会进入阻塞态,直到延时周期完成。任务在等待队列、信号量、事件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临!
4、挂起态
像阻塞态一样,任务进入挂起态以后也不能被调度器调用进入运行态,但是进入挂起态的任务没有超时时间。任务进入和退出挂起态通过调用函数vTaskSuspend()和xTaskResume()。
任务状态切换如下图。

三、任务优先级

每个任务都可以分配一个从0~(configMAX_PRIORITIES-1)的优先级,
configMAX_PRIORITIES在文件FreeRTOSConfig.h中有定义,前面我们讲解FreeRTOS系统配置的时候已经讲过了。如果所使用的硬件平台支持类似计算前导零这样的指令(可以通过该指令选择下一个要运行的任务,Cortex-M处理器是支持该指令的),
并且宏configUSE_PORT_OPTIMISED_TASK_SELECTION也设置为了1,那么宏configMAX_PRIORITIES不能超过32!也就是优先级不能超过32级。其他情况下宏configMAX_PRIORITIES可以为任意值,但是考虑到RAM的消耗,宏configMAX_PRIORITIES最好设置为一个满足应用的最小值。优先级数字越低表示任务优先级越低,0的优先级最低,configMAX_PRIORITIES-1的优先级最高。空闲任务的优先级最低,为0FreeRTOS调度器确保处于就绪态或运行态的高优先级的任务获取处理器使用权,换句话说就是处于就绪态的最高优先级的任务才会运行。当宏configUSE_TIME_SLICING定义为1的时候多个任务可以共用一个优先级,数量不限。默认情况下宏configUSE_TIME_SLICING在文件FreeRTOS.h中已经定义为1。此时处于就绪态的优先级相同的任务就会使用时间片轮转调度器获取运行时间。

四、任务实现

在使用FreeRTOS的过程中,需要使用xTaskCreat()或者xTaskCreatStatic()来创建任务,这两个函数的第一个参数为pxTaskCode,就是任务函数本体。任务函数就是完成本任务工作的函数。FreeRTOS官方给出的任务函数模板为:

void vATaskFunction(void *pvParameters){          (1)for(;;){                                      (2)--任务应用程序--                           (3)vTaskDelay();                             (4)
}VTaskDelete(NULL);                            (5)
}
  • (1)、任务函数本质也是函数,所以肯定有任务名什么的,不过这里要注意:任务函数的返回类型一定要为void类型,也就是无返回值,而且任务的参数也是void指针类型的!任务函数名可以根据实际情况定义。
  • (2)、任务的具体执行过程是一个大循环,for(;;)就代表一个循环,作用和while(1)一样,笔者习惯用while(1)。
  • (3)、循环里面就是真正的任务代码了,此任务具体要干的活就在这里实现!
  • (4)、FreeRTOS的延时函数,此处不一定要用延时函数,其他只要能让FreeRTOS发生任务切换的API函数都可以,比如请求信号量、队列等,甚至直接调用任务调度器。只不过最常用的就是FreeRTOS的延时函数。
  • (5)、任务函数一般不允许跳出循环,如果一定要跳出循环的话在跳出循环以后一定要调用函数vTaskDelete(NULL)删除此任务!FreeRTOS的任务函数和UCOS的任务函数模式基本相同的,不止FreeRTOS,其他RTOS的任务函数基本也是这种方式的。

五、任务控制块

FreeRTOS的每个任务都有一些属性需要存储,FreeRTOS把这些属性集合到一起用一个结构体来表示,这个结构体叫做任务控制块:TCB_t,在使用函数xTaskCreate()创建任务的时候就会自动的给每个任务分配一个任务控制块。在老版本的FreeRTOS中任务控制块叫做tskTCB,新版本重命名为TCB_t,但是本质上还是tskTCB,此结构体在文件tasks.c中有定义,如下:

typedef struct tskTaskControlBlock
{volatile StackType_t   *pxTopOfStack;  /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */#if ( portUSING_MPU_WRAPPERS == 1 )xMPU_SETTINGS    xMPUSettings;       /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */#endifListItem_t            xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ListItem_t          xEventListItem;     /*< Used to reference a task from an event list. */UBaseType_t           uxPriority;         /*< The priority of the task.  0 is the lowest priority. */StackType_t           *pxStack;           /*< Points to the start of the stack. */char             pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */#if ( portSTACK_GROWTH > 0 )StackType_t      *pxEndOfStack;      /*< Points to the end of the stack on architectures where the stack grows up from low memory. */#endif#if ( portCRITICAL_NESTING_IN_TCB == 1 )UBaseType_t      uxCriticalNesting;  /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */#endif#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t        uxTCBNumber;        /*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */UBaseType_t     uxTaskNumber;       /*< Stores a number specifically for use by third party trace code. */#endif#if ( configUSE_MUTEXES == 1 )UBaseType_t      uxBasePriority;     /*< The priority last assigned to the task - used by the priority inheritance mechanism. */UBaseType_t       uxMutexesHeld;#endif#if ( configUSE_APPLICATION_TASK_TAG == 1 )TaskHookFunction_t pxTaskTag;#endif#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];#endif#if( configGENERATE_RUN_TIME_STATS == 1 )uint32_t        ulRunTimeCounter;   /*< Stores the amount of time the task has spent in the Running state. */#endif#if ( configUSE_NEWLIB_REENTRANT == 1 )/* Allocate a Newlib reent structure that is specific to this task.Note Newlib support has been included by popular demand, but is notused by the FreeRTOS maintainers themselves.  FreeRTOS is notresponsible for resulting newlib operation.  User must be familiar withnewlib and must provide system-wide implementations of the necessarystubs. Be warned that (at the time of writing) the current newlib designimplements a system-wide malloc() that must be provided with locks. */struct   _reent xNewLib_reent;#endif#if( configUSE_TASK_NOTIFICATIONS == 1 )volatile uint32_t ulNotifiedValue;volatile uint8_t ucNotifyState;#endif/* See the comments above the definition oftskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )uint8_t   ucStaticallyAllocated;      /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */#endif#if( INCLUDE_xTaskAbortDelay == 1 )uint8_t ucDelayAborted;#endif} tskTCB;

六、任务堆栈

FreeRTOS之所以能正确的恢复一个任务的运行就是因为有任务堆栈在保驾护航,任务调度器在进行任务切换的时候会将当前任务的现场(CPU寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行。创建任务的时候需要给任务指定堆栈,如果使用的函数xTaskCreate()创建任务(动态方法)的话那么任务堆栈就会由函数xTaskCreate()自动创建。如果使用函数xTaskCreateStatic()创建任务(静态方法)的话就需要程序员自行定义任务堆栈,然后堆栈首地址作为函数的参数puxStackBuffer传递给函数,如下:

TaskHandle_t xTaskCreateStatic(  TaskFunction_t pxTaskCode,const char * const pcName,const uint32_t ulStackDepth,void * const pvParameters,UBaseType_t uxPriority,StackType_t * const puxStackBuffer,StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */

FreeRTOS创建任务(1)相关推荐

  1. freertos 创建互斥量_STM32CubeMX+FreeRTOS学习[6] 互斥量(Lu)

    FreeRTOS 学习之六:互斥量 前提:默认已经装好 MDK V5 和 STM32CubeMX ,并安装了 STM32F1xx 系列的支持包. 硬件平台: STM32F1xx 系列. 目的:学习互斥 ...

  2. 【STM32】FreeRTOS创建和删除任务示例(静态方法)(了解)

    00. 目录 文章目录 00. 目录 01. 概述 02. 功能描述 03. 任务设计 04. 程序设计 05. 结果验证 06. 附录 07. 参考 01. 概述 FreeRTOS中创建和删除任务A ...

  3. 【STM32】FreeRTOS创建和删除任务示例(动态方法)

    00. 目录 文章目录 00. 目录 01. 概述 02. 功能描述 03. 任务设计 04. 程序设计 05. 结果验证 06. 附录 07. 参考 01. 概述 FreeRTOS中创建和删除任务A ...

  4. TMS570LS3137 FreeRTOS——创建任务

    实验目的:将FreeRTOS移植到Hercules开发板中,并进行创建任务,通过指示灯显示看到任务状态. 实验操作:通过开发板上的LED1和D5指示灯看出当前的任务状态. 工作原理:系统先执行任务1L ...

  5. freertos 创建互斥量_FreeRTOS互斥信号量

    FreeRTOS互斥信号量 本文完整版地址:http://http://bbs.armfly.com/read.php?tid=21381 本章节讲解FreeRTOS重要的资源共享机制---互斥信号量 ...

  6. freertos 创建互斥量_FreeRTOS的信号量和互斥量

    1. 理解如下,言简意赅的说,信号量解决同步,互斥量解决竞争. 信号量用于同步,主要任务间和中断间同步:互斥量用于互锁,用于保护同时只能有一个任务访问的资源,为资源上一把锁. 互斥量具有优先级继承,信 ...

  7. freertos 创建互斥量_freertos任务通信

    说明 rtos内核基本上除了任务之间的调度以外,就剩下任务通信了.如果再广一点区分,任务通信也算任务调度了,它其实是为了提高内核效率而衍生出来的内核组件,为了将这些更规范,故而大家取名为信号量,邮箱, ...

  8. 【FreeRTOS】02 任务的创建

    上一节我们利用cubemx自动生成了一个实例,它建立了两个用户任务和一个默认任务,并成功运行起来了.本节我们将分析一下FreeRTOS任务创建的过程,并结合创建时需要的参数讲解一下FreeRTOS任务 ...

  9. FreeRTOS信号量---二值信号量

    信号量可以用来进行资源管理和任务同步,FreeRTOS中信号量又分为二值信号量.计算型信号量.互斥信号量和递归互斥信号量. 0x01 二值信号量 二值信号量其实就是一个只有一个队列项的队列,这个特殊的 ...

最新文章

  1. 3. Swift 数组|字典|集合
  2. Java系统资源消耗定位概述
  3. Git Push 避免输入用户名和密码方法
  4. python实现决策树数据直接赋值导入_决策树在python中的数据实现
  5. 这个是我的第一篇日志
  6. 【五级流水线CPU】—— 6. 加载存储指令(14)
  7. SCOM 2012 SP1安装过程
  8. python科学坐标系绘制分析_Python电子教案9-1-科学计算和可视化.ppt
  9. 厉害了!这款百度炼丹神器绝了!
  10. Consul添加配置详解
  11. 边缘检测法之Roberts算子
  12. 主板风扇转速测试软件,技嘉风扇转速调节及超频软件EasyTune6
  13. 解决 Win 10 输入法(仅桌面)的问题
  14. 申通核心业务系统上云战役
  15. 华为路由器时间同步_系统时间同步的方式
  16. 新唐 Nuvoton M031 入门 点亮板载LED
  17. Metro风格用户界面设计原则
  18. axure文件如何加密_axure怎么锁定位置
  19. Excel:宏运行打开新表后excel崩溃
  20. C++ OpenCV特征提取之KAZE检测

热门文章

  1. Android开源的精美日历控件,热插拔设计的万能自定义UI,flutter调用原生sdk
  2. 计算机考研历年真题在手,大大提高上车几率,408历年真题
  3. 2022年全球市场小型耕耘机总体规模、主要生产商、主要地区、产品和应用细分研究报告
  4. python春节集五福_2020支付宝过年集福活动,支付宝春节集五福
  5. 夏敏捷主编的书(2008-2014,八本)
  6. python实现微信登录破解版_网站微信登录-python 实现
  7. 三星新机今日发售,或意在抢滩区块链手机蓝海
  8. 英特尔第十代处理器为什么不支持win7_十代处理器是否可以安装Win7系统?安装Win7系统需要注意什么?...
  9. 一键锁定计算机快捷键,win10系统创建一键锁定计算机的快捷方式的处理技巧
  10. 我的第一本著作:Spark技术内幕上市!