FreeRTOS多任务管理

本文详细介绍了FreeRTOS中任务的创建、调度和状态转换,包括就绪态、运行态、阻塞态和挂起态,并展示了动态创建任务、延时函数和关键任务操作如挂起、恢复和删除。通过LED示例演示了如何使用vTaskCreate、vTaskDelay和vTaskSuspend等API。



1、任务

1.1 任务简介

(1) 在裸机系统中,系统的主体就是 main 函数里面顺序执行的无限循环,这个无限循环里面 CPU 按照顺序完成各种事情。
(2) 在FreeRTOS中,根据功能的不同,把整个系统分割成一个个独立无限循环无法返回的函数,这个函数就称为 任务

1.2 任务调度

任何时刻,只有一个任务得到运行,FreeRTOS调度器 决定运行哪个任务。调度器会不断的启动、停止每一个任务,宏观看上去所有的任务都在同时在执行。
FreeRTOS 中的任务是 抢占式 调度机制,高优先级的任务可打断 低优先级任务,低优先级任务必须在高优先级任务阻塞结束后 才能得到调度。

1.3 任务的状态 (就绪态 / 运行态 / 阻塞态 / 挂起态)

任务状态通常分为以下四种:
1、就绪态 (ready):该任务在就绪列表中,就绪的任务已经具备执行的能力,只等待调度器进行调度,新创建的任务会初始化为就绪态

2、运行态 (running):该状态表明任务正在执行,此时它占用处理器,FreeRTOS调度器选择运行的永远是处于最高优先级的 就绪态任务,当任务被运行的一刻,它的任务状态就变成了运行态

3、阻塞态 (blocked):正在运行的任务发生阻塞 (延时、读信号量等待、读写队列或者等待读写事件) 时,该任务会从就绪列表中删除,任务状态由运行态变成阻塞态

4、挂起态 (suspended):处于挂起态的任务 对调度器而言是不可见的,让一个任务进入挂起状态的唯一办法就是调用 vTaskSuspend() 函数;而把一个挂起状态的任务恢复 的唯一途径 就是调用 vTaskResume() 或 vTaskResumeFromISR() 函数。

挂起态阻塞态的区别:
当任务有较长的时间不允许运行的时候,我们可以挂起任务,这样 调度器就不会管这个任务的任何信息,直到我们调用恢复任务的 API 函数;
而任务处于阻塞态的时候,系统还需要判断 阻塞态的任务是否超时,是否可以解除阻塞。

他们之间的转换关系如下图:
在这里插入图片描述
(1):创建任务→就绪态 (ready):任务创建完成后进入就绪态,表明任务已准备就绪,随时可以运行,只等待调度器进行调度。
(2):就绪态→运行态 (running):发生任务切换时,就绪列表最高优先级的任务被执行,从而进入运行态。
(3):运行态→就绪态:有更高优先级任务创建或者恢复后,会发生 任务调度,此刻就绪列表中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪列表中,等待最高优先级的任务运行完毕,继续运行原来的任务 (此处可以看做是 CPU使用权被更高优先级的任务抢占了)。
(4):运行态→阻塞态 (blocked):正在运行的任务发生阻塞 (延时、读信号量等待) 时,该任务会从就绪列表中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪列表中当前最高优先级任务。
(5):阻塞态→就绪态:阻塞的任务被恢复后 (任务恢复、延时时间超时、读信号量超时 或读到信号量等),此时被恢复的任务会被加入就绪列表,从而由阻塞态变成就绪态;如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,将该任务将再次转换任务状态,由就绪态变成运行态
(6) (7) (8):就绪态、阻塞态、运行态→挂起态 (suspended):任务可以通过调用 vTaskSuspend() API 函数都可以将处于任何状态的任务挂起,被挂起的任务得不到CPU的使用权,也不会参与调度,除非它从挂起态中解除。
(9):挂起态→就绪态:把一个挂起状态的任务 恢复的唯一途径就是调用 vTaskResume() 或 vTaskResumeFromISR() API 函数,如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生 任务切换,将该任务将再次转换任务状态,由就绪态 变成 运行态。

1.4 空闲任务

空闲任务是系统在 启动调度器的时候,创建的优先级最低的任务,空闲任务主体主要是做一些系统内存的清理工作。
如果没有其它任务可以运行,这个时候CPU就运行空闲任务。

2、动态创建两个任务

2.1 定义动态内存空间的堆(heap)

使用动态内存,即 堆(heap),也属于 SRAM。
FreeRTOS 做法是在SRAM里面定义一个大数组,也就是堆内存,供 FreeRTOS的动态内存分配函数使用,在第一次使用的时候,系统会将定义的堆内存进行初始化。

//系统所有总的堆大小
#define configTOTAL_HEAP_SIZE    ((size_t)(36*1024))    (1)
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; 	    (2)

(1) 堆内存的大小为 configTOTAL_HEAP_SIZE,在 FreeRTOSConfig.h 中,由用户自己定义,configSUPPORT_DYNAMIC_ALLOCATION 这个宏定义在使用FreeRTOS操作系统的时候必须开启。
(2) 从内部SRAM 里面定义一个静态数组 ucHeap,大小由configTOTAL_HEAP_SIZE这个宏决定,目前定义为 36KB。

2.2 定义任务函数

创建两个任务,分别 让 LED 灯以 500ms / 1000ms的频率闪烁,具体实现见代码清单:

 static void LED1_Task(void* parameter){
   
   
   while (1) {
   
   							
     LED1_ON;
     vTaskDelay(500); /*  延时500个tick */
     LED1_OFF;
     vTaskDelay(500); /*  延时500个tick */
   }
 }
static void LED2_Task(void* parameter){
   
   
  while (1) {
   
   									(1)
    LED2_ON;
    vTaskDelay(1000); /*  延时1000个tick */  	(2)
    LED2_OFF;
    vTaskDelay
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值