FreeRTOS 实时内核实用指南之第一章任务管理知识总结

2023-05-16

  1. 任务函数
  2. 顶层任务状态
  3. 创建任务
  4. 任务优先级
  5. 扩充“非运行态”
  6. 空闲任务与空闲任务钩子函数
  7. 改变任务优先级
  8. 删除任务
  9. 调度算法-简述

 

一、任务函数 

1.pvParameters:代表传入函数的参数

2.变量i和变量j 是在任务函数中的变量,但是变量j被static定义的话,则该变量在别的任务中也可以访问。

3.vTaskDelete();该函数是删除任务,里边的参数NULL代表的是删除当前的任务

void ATaskFunction(void *pvParameters)
{
    int i=0;
    static int j=1;//该j变量可以让任何实例都可以访问。
    for(;;)
    {
        //code
    }
    //执行完code之后会跳出死循环,然后通过vTaskDelete函数删除本任务。NULL代表删除当前任        
   //务。
    vTaskDelete(NULL);
}

二、顶层任务状态

1.不同微控制器,能同时执行多少个任务?

eg:stm32只有一个核(core),即一个cpu处理,则在任意给定的时间,实际上只有一个任务被执行,别的任务处于非运行状态。

2.任务的状态变化

(1)“切换”、“切入”、“交换入”(swapped in):任务从非运行态转移到运行态。

(2)“切换出”、“切出”(swapped out):任务从运行态转移到非运行态。

3.不同的状态转变,通过FreeRTOS的调度器

三、创建任务

1.xTaskCreate()函数:

eg:
portBASE_TYPE xTaskCreate(pdTASK_CODE pvTaskCode,
                          const signed portCHAR *const pcName,
                          unsigned portSHORT usStackDepth,
                          void *pvParameters,
                          unsigned portBASE_TYPE uxPriority,
                          xTaskHandle *pxCreatedTask);
PS:
参数1:pvTaskCode:函数名(指向函数的指针)

参数2:pcName:任务名称(任务名称的长度有config_MAX_TASK_NAME_LEN来定义其最大的长度,包括‘\0’结束符,如果超过该最大长度,则会被截断)

参数3:usStackDepth:栈的长度(告诉内核应该分配给任务多大的栈空间)。
       如果是32位的宽的栈空间,传入的usStackDepth如果为100,则会被分配给的栈的空间是100*        
      (32/8)=400bytes.
       PS:栈的空间不能大于size_t 类型变量所能表示的最大值。
       栈的空间由config_MINIMAL_STACK_SIZE 来决定空闲任务栈空间大小。

参数4:pvParameters :接收的是一个指向void的指针(void *)。pvParameters的值即是传递到任务 
      中的值。

参数5:uxPriority:任务执行的优先级。取值范围为:最低优先级0-最高优先级 
      (configMAX_PRIORITIES-1)

参数6:pxCreatedTask :pxCreateTask用于传出任务的句柄,该任务在API调用中对该创建出来的任 
      务进行引用,例如:改变任务优先级,或者删除任务。

返回值:
        1.pdTRUE:表示创建任务成功
        2.errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY:因为内存对空间不足,FreeRTOS无法分配 
        足够的空间来保存任务结构数据和任务栈,因此无法创建任务。

2.使用任务参数:

//参数的声明
static const char *pcTextForTask1="Task 1 is running\r\n";
//参数的引用
xTaskCreate(vTaskFunction,"Task 2",100,(void*)pcTextForTask2,1,NULL);

四、任务优先级

1.任务优先级:

其配置在文件FreeRTOSConfig.h。取值范围为:最低优先级0-最高优先级 (configMAX_PRIORITIES-1)

 2.要能够选择下一个运行的任务,调度器需要在每个时间片的结束时刻运行自己本 身。一个称为心跳(tick,有些地方被称为时钟滴答,本文中一律称为时钟心跳)中断的 周期性中断用于此目的。时间片的长度通过心跳中断的频率进行设定,心跳中断频率由 FreeRTOSConfig.h 中的编译时配置常量 configTICK_RATE_HZ 进行配置。比如说, 如果 configTICK_RATE_HZ 设为 100(HZ),则时间片长度为 10ms。

3.FreeRTOS API 函数调用中指定的时间总是以心跳中断为单位(通 常的提法为心跳”ticks”)。常量 portTICK_RATE_MS 用于将以心跳为单位的时间值转化 为以毫秒为单位的时间值。有效精度依赖于系统心跳频率。

五、扩充"非运行态"

1.阻塞状态:(一个任务在等待某个时间,则该任务进入了”阻塞态“),阻塞态是非运行状态的一个子态。

(1)任务进入阻塞状态一般是等待这两种类型的事件:定时(时间相关)事件同步事件(源于其他任务或中断的事件)

PS:FreeRTOS 的队列,二值信号量,计数信号量,互斥信号量(recursive semaphore, 递归信号量,本文一律称为互斥信号量,因为其主要用于实现互斥访问)和互斥量都可 以用来实现同步事件

 (2)挂起状态:也是一种非运行状态的子状态。处于挂起状态的任务对于FreeRTOS的调度器而言是不可见的。进入挂起状态:调用vTaskSuspend()API函数 ; 退出挂起状态:调用vTaskResume()或者vTaskResumeFromISR API 函数。大多数应用程序中都不会用到挂起状态。

(3)就绪状态;处于非运行状态,既没有挂起,也没有阻塞,处于就绪状态能被运行,只是准备运行,而尚未运行。

(4)状态转换图:

六、空闲任务与空闲任务钩子函数

1.空闲任务存在的意义

当创建的任务状态都处于阻塞状态时,所有的任务都不可运行,也不会被任务调度器所选中,但是处理器还是要有代码去执行,所以这个时候需要在调用vTaskStartScheduler()时,调度器会创建一个空闲任务,该空闲任务有非常短小的循环

2.空闲任务的特性:处于最低优先级(0),别的任务也可以和空闲任务共享优先级

3.空闲任务钩子函数:(当空闲任务每循环一次就会被自动调用一次

4.空闲任务钩子函数的用途

(1)执行低优先级,后台或需要不停处理功能代码

(2)测试处系统处理裕量(因为空闲任务是没有别的任务执行的时候才执行的,所以可以通过空闲任务的处理时间来知道系统有多少富余的处理时间)

(3)省电:在处理器处于空闲状态时,将其配置到低功耗模式,这个时候系统自动进入省电模式。

5.空闲任务钩子函数的实现限制:

(1)绝对不能阻塞或者挂起,不然的话,别的任务就进入不了运行态了。

(2)如果应用程序用到了vTaskDelete()AP函数,则空闲函数必须能够尽快返回。因为在任务删除后,空闲任务负责回收内核资源。如果空闲任务一直在钩子函数中,则进行不了回收工作。

七、改变任务优先级

1.函数vTaskPrioritySet()API函数

void vTaskPrioritySet(xTaskHandle pxTask,unsigned portBASE_TYPE uxNewPriority)
//pxTask:被修改优先级的任务句柄(目标函数),如果是NULL的话,是本任务(myself)
//uxNewPriority:新的优先级

2.uxTaskPriorityGet() API函数

unsigned portBASE_TYPE uxTaskPriorityGet(xTaskHandle pxTask)
//pxTask:所查询任务优先级的任务句柄(目标任务)

八、删除任务

vTaskDelete() API 函数

void vTaskDelete(xTaskHandle pxTaskToDelete);
//pxTaskToDelete:被删除任务的句柄(目标任务)

九、调度算法

1.优先级抢占式调度

2.协作式调度

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS 实时内核实用指南之第一章任务管理知识总结 的相关文章

随机推荐