FreeRTOS--任务创建与管理

一、“任务”的特点

1.简而言之 :

        使用 RTOS 的实时应用程序可以被构建为一组独立的任务每个任务在自己的上下文中执行,不依赖于系统内的其他任务或 RTOS 调度器本身。在任何时间点,应用程序中只能执行一个任务,实时 RTOS 调度器负责决定所要执行的任务。因此, RTOS 调度器可以在应用程序执行时重复启停每个任务(将任务调入或调出)。由于任务不了解 RTOS 调度器活动,因此实时 RTOS 调度器负责确保任务调入时的处理器上下文(寄存器值、堆栈内容等)与任务调出时的处理器上下文完全相同。为实现这一点,每个任务都分配有自己的堆栈。当任务调出时执行上下文被保存到该任务的堆栈中,以便以后再调入相同的任务时可以准确地恢复其执行上下文。

2.任务状态:·运行 ·就绪 ·阻塞 ·挂起

3.任务优先级:低优先级数字表示低优先级任务

        每个任务均被分配了从 0 到 ( configMAX_PRIORITIES - 1 ) 的优先级,其中的 configMAX_PRIORITIES 在 FreeRTOSConfig.h 中定义。

 低优先级数字表示低优先级任务。 空闲任务的优先级为(tskIDLE_PRIORITY)。

 任意数量的任务可共用相同的优先级。 如果 configUSE_TIME_SLICING 未经定义, 或者如果 configUSE_TIME_SLICING 设置为 1,则相同优先级的就绪状态任务 将使用时间切片轮询调度方案共享可用的处理时间

4.任务调度:默认使用固定优先级的抢占式调度策略执行时间片轮询调度

configUSE_PREEMPTION 设置为 0,则关闭“抢占”,1 表示开启“抢占”

  • “固定优先级” 是指调度器不会永久更改任务的优先级, 尽管它可能会因 优先级继承而暂时提高任务的优先级。
  • 抢占式调度” 是指调度器始终运行优先级最高且可运行的 RTOS 任务, 无论任务何时能够运行。例如, 如果中断服务程序 (ISR) 更改了优先级最高且可运行的任务, 调度器会停止当前正在运行的低优先级任务 并启动高优先级任务——即使这发生在同一个时间片内 。此时,据说高优先级任务 “抢占”了低优先级任务。
  • 轮询调度” 是指具有相同优先级的任务轮流进入运行状态
  • 时间片” 是指调度器会在每个 tick 中断上在同等优先级任务之间进行切换, tick 中断之间的时间构成一个时间片。tick 中断是 RTOS 用来衡量时间的周期性中断。

 5.任务实现

TaskFunction_t 类型是指返回 void 并将 void 指针作为其唯一参数的函数。所有实现任务的函数 都应该是这种类型的函数。该参数可用于将任何类型的信息传递到任务中

 二、任务创建

TaskHandle_t 任务引用的类型,调用 xTaskCreate(通过指针参数)返回 TaskHandle_t 变量,可以将该变量用作 vTaskDelete 的参数来删除任务。

struct tskTaskControlBlock; 
typedef struct tskTaskControlBlock * TaskHandle_t;

1、 动态任务创建:

        xTaskCreate   默认 configSUPPORT_DYNAMIC_ALLOCATION 为1 时生效

    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName, 
                            const configSTACK_DEPTH_TYPE usStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )

 返回值:任务创建成功,返回pdPASSxTaskCreate() 创建任务,则所需的 RAM 将自动   从 FreeRTOS堆中分配。

参数:
pvTaskCode  	指向任务入口函数的指针
pcName  	    任务的描述性名称。
                任务名称的最大长度由 FreeRTOSConfig.h 中的 configMAX_TASK_NAME_LEN 定义。
uxStackDepth  	要分配用于任务堆栈的堆栈。
                如果堆栈的宽度为 16 位,uxStackDepth为100则将分配200字节用作该任务的堆栈。 
pvParameters  	作为参数传递给创建的任务的一个值。
uxPriority  	创建任务执行的优先级 。
pxCreatedTask  	用于将句柄传递至由xTaskCreate()函数创建的任务,pxCreatedTask 是可选的,
                可设置为NULL。

2、静态任务创建:

       xTaskCreateStatic 默认configSUPPORT_STATIC_ALLOCATION 为0,函数不可用。使用 xTaskCreateStatic() 创建任务,则 RAM 由应用程序编写者提供,这会产生更多的参数但允许在编译时静态分配 RAM。

TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
                                    const char * const pcName,
                                    const uint32_t ulStackDepth,//注意是32位
                                    void * const pvParameters,
                                    UBaseType_t uxPriority,
                                    StackType_t * const puxStackBuffer,
                                    StaticTask_t * const pxTaskBuffer )

 静态创建任务个别参数定义与动态创建任务不同:

参数:

ulStackDepth	puxStackBuffer 参数用于将 StackType_t 变量数组传递给 xTaskCreateStatic()。、        
                必须将 ulStackDepth 设置为数组中的索引数。
puxStackBuffer	必须指向至少具有 ulStackDepth 索引的 StackType_t 数组(请参阅上面的         
                ulStackDepth 参数),该数组用作任务的堆栈,因此必须是永久性的(而不是在函数的堆    
                栈上声明)。
pxTaskBuffer	必须指向 StaticTask_t 类型的变量。该变量用于保存新任务的数据结构体 (TCB) ,因此 
                必须是持久的(而不是在函数的堆栈中声明)。

返回:
    如果 puxStackBuffer 和 pxTaskBuffer 均不为 NULL,则创建任务,并返回任务的句柄。如果 puxStackBuffer 或 pxTaskBuffer 为 NULL,则不会创建任务,并返回 NULL。

 静态创建任务需要实现两个函数:空闲任务与定时器任务

        vApplicationGetIdleTaskMemory();

        vApplicationGetTimerTaskMemory();

3、移除任务:

void vTaskDelete( TaskHandle_t xTaskToDelete ),配置为1才可以使用

参数:

xTask 待删除的任务的句柄。传递 NULL 将导致调用任务被删除

4、 任务恢复:

void vTaskResume( TaskHandle_t xTaskToResume );

参数:

xTaskToResume 要恢复的任务句柄。

从 ISR 内调用的恢复挂起任务的函数

BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume );

需要在FreeRTOSConfig 定义以下,默认是开启状态

 5、任务优先级

  IRQ 任务: IRQ 任务是指通过中断服务程序进行触发的任务, 此类任务应该设置为所有任务里面优先级最高的。

高优先级后台任务: 比如按键检测串口消息处理等,都可以归为这一类任务。

低优先级的时间片调度任务: 比如 emWin 的界面显示, LED 数码管的显示等不需要实时执行的都可以归为这一类任务。 实际应用中用户不必拘泥于将这些任务都设置为优先级 1 的同优先级任务,可以设置多个优先级, 只需注意这类任务不需要高实时性。

 空闲任务: 空闲任务是系统任务

 特别注意: IRQ 任务和高优先级任务必须设置为阻塞式(调用消息等待或者延迟等函数即可) , 只有这样, 高优先级任务才会释放 CPU 的使用权, ,从而低优先级任务才有机会得到执行。

注意:

        对于 STM32F103, F407 和 F429 来说, 中断优先级的数值越小, 优先级越高。 而 FreeRTOS的任务优先级是, 任务优先级数值越小, 任务优先级越低。

(1)任务优先级修改

void vTaskPrioritySet( TaskHandle_t xTask,

                                    UBaseType_t uxNewPriority );

/* 任务句柄 */

/* 给任务配置的新优先级 */

使用注意:1.第二个参数里面填的是 NULL,即数值 0 的话,那么配置的就是当前正在执行的任务

   2. 如果被修改的任务的优先级修改后高于正在执行的任务, 将执行任务切换,切换到修改好的高优先级任务。需要uxNewPriority <  configMAX_PRIORITIES !!!

(2)任务优先级获取            

 UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ); /* 任务句柄 */

 如果传递 NULL 句柄会导致返回的是调用任务的优先级

 三、测试例程

https://gitee.com/hutaooooooo/git_keil/tree/master/freetos_CreateTask

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值