裸机开发
裸机程序的设计模式可以分为:轮询、前后台、定时器驱动、基于状态机。
前面三种方法都无法解决一个问题:假设有A、B两个都很耗时的函数,无法降低它们相互之间的影响。第4种方法可以解决这个问题,但是实践起来有难度。
创建多个任务,音乐播放,灯,屏幕显示等
功能为:
- 当监测到遥控器的播放按键被按下后,创建音乐播放任务。
- 当监测到遥控器的Power按键被按下后,删除音乐播放任务
提问:频繁地创建、删除任务,好吗?有什么坏处?如何解决?
频繁创建可能导致内存被频繁动态分配,产生内存碎片,浪费资源
新增加一个暂停Suspended功能,通过提高音乐播放的优先级,使用vTaskDelay进行延时。
- 多任务不会卡顿,优先处理,可以暂停和开始
- vTaskDelay为阻塞Blocked状态,不会一直占用cpu
FreeRTOS任务状态转换图:
任务管理与调度
重点是优先级、链表的管理、任务切换、Tick
- 同优先级的任务轮流运行
- 高优先级的任务先运行
- 高优先级的任务未执行完,低优先级的任务无法执行
- 一旦高优先级的任务就绪,马上执行
- 最高优先级的任务有多个,轮流运行
以链表的形式保存任务,共56个,默认等级为24,空闲任务优先级为0。
调度顺序为从上往下,遍历第一个非空链表,取出任务执行。
- 首先指针指向任务3,执行任务3,指针移到下一位任务1;
- Tick中断,再次从ReadyList从上往下遍历找到第一个非空链表,此时指针在任务1,执行任务1;
- Tick中断,再次从ReadyList从上往下遍历找到优先级24非空链表,此时指针在任务2,执行任务2;
- 。。。
空闲任务(Idle任务)的作用之一:释放被删除的任务的内存
除了上述目的之外,为什么必须要有空闲任务?一个良好的程序,它的任务都是事件驱动的:平时大部分时间处于阻塞状态。有可能我们自己创建的所有任务都无法执行,但是调度器必须能找到一个可以运行的任务:所以,我们要提供空闲任务。在使用vTaskStartScheduler0函数来创建、启动调度器时,这个函数内部会创建空闲任务:
- 空闲任务优先级为0:它不能阻碍用户任务运行
- 空闲任务要么处于就绪态,要么处于运行态,永远不会阻塞
空闲任务的优先级为0,这意味着一旦某个用户的任务变为就绪态,那么空闲任务马上被切换出去,让这个用户任务运行。在这种情况下,我们说用户任务“抢占”(pre·empt)了空闲任务,这是由调度器实现的。