声明:本专栏参考韦东山,野火,正点原子以及其他博主的FreeRTOS教程,如若侵权请告知,马上删帖致歉,个人总结,如有不对,欢迎指正。
FreeRTOS任务调度
在freeRTOS中任务分为四种状态,就绪态,运行态,阻塞态,停止态。
我的理解:
运行态:当前正在运行的任务
就绪态:正在排队的任务
阻塞态:睡觉的任务
停止态:离线的任务
任务的删除
把任务看成一个人,这个人可以去杀人,可以自杀,也可能被别人杀。
换做任务,我们可以自杀杀别人,被别人杀
实验一:
创建三个任务函数,这是最高优先级的任务,我们放了vTaskDelay函数,低优先级的任务可以执行,在这个任务中计数,计数到一定时间来删除自己,在这个实验中,我加大了轮转调度的时间,可以把串口的数据打印完整
逻辑分析仪中可以看到任务1运行一段时间后就把自己删除了
这里的仿真来看,在调用任务删除函数后,就不能执行该任务了,只有剩下来的两个任务参与cpu调度
串口打印显示临死前说了一句话
实验二:
这个实验为同优先级下三个任务,
任务二三正常执行,看看任务1,任务一运行了一段时间之后就开始删除task2任务,删除了task任务后就自杀了
逻辑分析仪中表示为在执行某一段时间之后,任务一删除了任务二,任务二,任务二不再运行,再自杀,任务一也不再运行,最后只剩下最后一个任务独享cpu资源,体现为Task3一直处于高平
串口:开始杀人后接着自杀,就只剩下任务3运行了
对于任务一来说,他是在杀别人任务,对于任务二来说,他是被别的任务杀了(ε=(´ο`*)))唉,真可怜)
突然想到一种,低优先级能杀高优先级么,说干就干
实验三:
任务1,2,3的优先级分别为232,任务1杀了任务2之后自杀
实验结果逻辑分析仪中如下:结论,低优先级可以杀高优先级
任务的挂起与恢复
实验四:
同优先级下的三个任务,第一个任务反复挂起和恢复任务三
以上实验可以看出,任务三在被不断的挂起与恢复
任务删除总结总结:一个任务可以自杀,杀别人,被别人杀,任务的删除可以调用自己的任务句柄,也可以传输参数NULL(仅限自杀,自杀可以多一种选择,哈哈),低优先级的任务可以杀高优先级的任务
任务的挂起与恢复总结:任务的挂起与恢复,任务挂起同任务删除一样,任务可以挂起自己,也可以挂起别人,也可以被别人挂起,任务的恢复只能由别人来恢复,被挂起的任务不参与调度
上一节知识点扩充
同优先级下为什么是后创建的任务先运行,我们来看看三个同优先级的任务运行情况
在上一节的实验一中,串口会先打印LED2……来看一下这是为什么
实验五:
我创建了三个任务,但是根据时间片轮转的大小不同,运行的先后顺序也不同,这能有什么关系???任务运行的先后顺序到底是由什么来决定??
这个不同会影响运行先后顺序,有待验证
查阅资料验证如下:
在 FreeRTOS 中,如果有多个同优先级的任务,它们的运行顺序是不确定的,由系统的任务调度器决定。但是,在实际应用中,我们可能需要确保某些任务先于其他任务执行,或者让任务按照一定的顺序依次执行。这时,可以通过任务通知(task notification)或者信号量(Semaphore)等机制来实现
以任务通知为例,可以在任务中使用 ulTaskNotifyTake() 函数等待通知事件,然后使用 xTaskNotify() 函数向其他任务发送通知。在创建任务时,可以使用 xTaskCreate() 函数的 pvTaskCode 参数指定任务函数,然后在任务函数中使用任务通知来实现任务之间的同步和协作。
假设我们要创建三个同优先级的任务 A、B、C,按照顺序依次执行,可以按照以下步骤进行设置:
实现如下
在任务创建时,使用 xTaskCreate() 函数设置任务优先级和任务函数,例如:
xTaskCreate(TaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
xTaskCreate(TaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
xTaskCreate(TaskC, "TaskC", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
其中,优先级设置为 2,表示这三个任务具有相同的优先级。
在任务函数中使用任务通知来实现任务之间的同步和协作。例如,任务 A 在执行完任务内容后
向任务 B 发送通知,任务 B 在接收到通知后再向任务 C 发送通知,以此类推。
void TaskA(void *pvParameters)
{
// 执行任务 A 的代码
// 向任务 B 发送通知
xTaskNotifyGive(TaskB);
vTaskSuspend(NULL); // 挂起任务 A
}
void TaskB(void *pvParameters)
{
// 等待任务 A 的通知
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// 执行任务 B 的代码
// 向任务 C 发送通知
xTaskNotifyGive(TaskC);
vTaskSuspend(NULL); // 挂起任务 B
}
void TaskC(void *pvParameters)
{
// 等待任务 B 的通知
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// 执行任务 C 的代码
vTaskSuspend(NULL); // 挂起任务 C
}
在上面的代码中,任务 A 在执行完任务内容后向任务 B 发送通知,然后挂起自己等待任务 B 的通知;
任务 B 在接收到任务 A 的通知后执行自己的任务内容,然后向任务 C 发送通知,挂起自己等待任务 C 的通知;
任务 C 在接收到任务 B 的通知后执行自己的任务内容,然后挂起自己。这样,任务 A、B、C 就可以按照顺序依次执行
git仓库源码地址:https://gitee.com/he-dejiang/free-rtos.git