freeRTOS任务管理—新手入门

记录自己学习freeRTOS的过程,跟着B站韦东山老师学习,由于之前有stm32基础,我没有购买对应开发板,而是用自己原有的stm32f407,主要学习RTOS的一些概念,思想,不拘泥于代码。

1.基本概念

使用freeRTOS创建多种任务,本质上是对时间进行切片,保留现场,实现多任务运行的现象。

2.创建任务的函数

动态创建:

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
                        const char * const pcName, // 任务的名字
                        const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节
                        void * const pvParameters, // 调用任务函数时传入的参数
                        UBaseType_t uxPriority,    // 优先级
                        TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务

静态创建:

TaskHandle_t xTaskCreateStatic ( 
    TaskFunction_t pxTaskCode,   // 函数指针, 任务函数
    const char * const pcName,   // 任务的名字
    const uint32_t ulStackDepth, // 栈大小,单位为word,10表示40字节
    void * const pvParameters,   // 调用任务函数时传入的参数
    UBaseType_t uxPriority,      // 优先级
    StackType_t * const puxStackBuffer, // 静态分配的栈,就是一个buffer
    StaticTask_t * const pxTaskBuffer // 静态分配的任务结构体的指针,用它来操作这个任务
);

区别:最后两个参数不一样,需要手动写静态分配的栈以及任务结构体。 

 3.任务的删除

void vTaskDelete( TaskHandle_t xTaskToDelete );

参数说明:

xTaskCreate 任务句柄,创建任务时可以得到一个句柄。 也可传入NULL,这表示删除自己。

怎么删除任务?举个不好的例子:

自杀:vTaskDelete(NULL)

被杀:别的任务执行vTaskDelete(pvTaskCode),pvTaskCode是自己的句柄

杀他:执行vTaskDelete(pvTaskCode),pvTaskCode是别的任务的句柄

任务删除以后,可以加一个清除函数,不然状态会停留在删除前的时刻,列如:删除蜂鸣器任务以后,蜂鸣器会持续发声,这时就需要一个删除函数。

4.任务优先级和Tick(重点)

优先级的取值范围是:0~(configMAX_PRIORITIES – 1),数值越大优先级越高。

在这你只要初略地知道:

  • FreeRTOS会确保最高优先级的、可运行的任务,马上就能执行        
  • 对于相同优先级的、可运行的任务,轮流执行        

Tick:

对于同优先级的任务,它们“轮流”执行。怎么轮流?你执行一会,我执行一会。

"一会"怎么定义?

人有心跳,心跳间隔基本恒定。

FreeRTOS中也有心跳,它使用定时器产生固定间隔的中断。这叫Tick、滴答,比如每10ms发生一次时钟中断。

  • 假设t1、t2、t3发生时钟中断
  • 两次中断之间的时间被称为时间片(time slice、tick period)
  • 时间片的长度由configTICK_RATE_HZ 决定,假设configTICK_RATE_HZ为100,那么时间片长度就是10ms

相同优先级的任务怎么切换呢?

  • 任务2从t1执行到t2
  • 在t2发生tick中断,进入tick中断处理函数:
    • 选择下一个要运行的任务
    • 执行完中断处理函数后,切换到新的任务:任务1

有了Tick的概念后,我们就可以使用Tick来衡量时间了,比如:

vTaskDelay(2);  // 等待2个Tick,假设configTICK_RATE_HZ=100, Tick周期时10ms, 等待20ms

// 还可以使用pdMS_TO_TICKS宏把ms转换为tick
vTaskDelay(pdMS_TO_TICKS(100));	 // 等待100ms

注意,基于Tick实现的延时并不精确,比如vTaskDelay(2)的本意是延迟2个Tick周期,有可能经过1个Tick多一点就返回了。 

使用vTaskDelay函数时,建议以ms为单位,使用pdMS_TO_TICKS把时间转换为Tick。

vTaskDelay 的用途

  1. 控制任务执行频率: 在实时操作系统中,不是所有任务都需要一直运行。例如,一个传感器读取任务可能每秒读取一次数据。通过 vTaskDelay,我们可以使任务在读取数据后休眠一段时间,从而实现定期执行。

  2. 避免 CPU 过载: 如果任务不停地执行而不进行任何延迟,CPU 将会一直处于繁忙状态。使用 vTaskDelay 可以让出 CPU 给其他任务执行,提升系统的整体效率。

  3. 降低功耗: 在一些低功耗应用中,控制任务的执行频率可以有效降低功耗。例如,在电池供电的嵌入式设备中,任务可以在完成工作后进入阻塞状态,从而减少不必要的电量消耗。

  • vTaskDelay:阻塞状态
  • vTaskSuspend 暂停状态
  • vTaskResume 恢复状态

你可能感兴趣的:(freertos学习记录,stm32)