记录自己学习freeRTOS的过程,跟着B站韦东山老师学习,由于之前有stm32基础,我没有购买对应开发板,而是用自己原有的stm32f407,主要学习RTOS的一些概念,思想,不拘泥于代码。
使用freeRTOS创建多种任务,本质上是对时间进行切片,保留现场,实现多任务运行的现象。
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 // 静态分配的任务结构体的指针,用它来操作这个任务
);
区别:最后两个参数不一样,需要手动写静态分配的栈以及任务结构体。
void vTaskDelete( TaskHandle_t xTaskToDelete );
xTaskCreate 任务句柄,创建任务时可以得到一个句柄。 也可传入NULL,这表示删除自己。
怎么删除任务?举个不好的例子:
自杀:vTaskDelete(NULL)
被杀:别的任务执行vTaskDelete(pvTaskCode),pvTaskCode是自己的句柄
杀他:执行vTaskDelete(pvTaskCode),pvTaskCode是别的任务的句柄
任务删除以后,可以加一个清除函数,不然状态会停留在删除前的时刻,列如:删除蜂鸣器任务以后,蜂鸣器会持续发声,这时就需要一个删除函数。
优先级的取值范围是:0~(configMAX_PRIORITIES – 1),数值越大优先级越高。
在这你只要初略地知道:
Tick:
对于同优先级的任务,它们“轮流”执行。怎么轮流?你执行一会,我执行一会。
"一会"怎么定义?
人有心跳,心跳间隔基本恒定。
FreeRTOS中也有心跳,它使用定时器产生固定间隔的中断。这叫Tick、滴答,比如每10ms发生一次时钟中断。
相同优先级的任务怎么切换呢?
有了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
的用途控制任务执行频率: 在实时操作系统中,不是所有任务都需要一直运行。例如,一个传感器读取任务可能每秒读取一次数据。通过 vTaskDelay
,我们可以使任务在读取数据后休眠一段时间,从而实现定期执行。
避免 CPU 过载: 如果任务不停地执行而不进行任何延迟,CPU 将会一直处于繁忙状态。使用 vTaskDelay
可以让出 CPU 给其他任务执行,提升系统的整体效率。
降低功耗: 在一些低功耗应用中,控制任务的执行频率可以有效降低功耗。例如,在电池供电的嵌入式设备中,任务可以在完成工作后进入阻塞状态,从而减少不必要的电量消耗。