??调度锁就是 RTOS 提供的调度器开关函数,如果某个任务调用了调度锁开关函数,处于调度锁开和调度锁关之间的代码在执行期间是不会被高优先级的任务抢占的,即任务调度被禁止。这一点要跟临界段的作用区分开,调度锁只是禁止了任务调度,并没有关闭任何中断,中断还是正常执行的。而临界段进行了开关中断操作。
??中断锁就是 RTOS 提供的开关中断函数,FreeRTOS 没有专门的中断锁函数,使用上一讲里面介绍的中断服务程序临界段处理函数就可以实现同样效果。
??简单的说,为了防止当前任务的执行被其它高优先级的任务打断而提供的锁机制就是任务锁。FreeRTOS 也没有专门的任务锁函数,但是使用 FreeRTOS 现有的功能有两种实现方法:
利用调度锁关闭任务切换
利用 FreeRTOS 的任务代码临界段处理函数关闭 PendSV 中断和 Systick 中断,进而关闭任务切换。
调度锁开启函数 void vTaskSuspendAll(void)
??使用这个函数要注意以下问题:
??①. 调度锁函数只是禁止了任务调度,并没有关闭任何中断。
??②. 调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 一定要成对使用。
??③. 切不可在调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 之间调用任何会引起任务切换的 API,比如 vTaskDelayUntil、vTaskDelay、xQueueSend 等。
调度锁关闭函数 BaseType_t vTaskResumeAll(void)
??调度锁关闭后,如果需要任务切换,此函数返回 pdTRUE,否则返回 pdFALSE。
??使用这个函数要注意以下问题:
??①. 调度锁函数只是禁止了任务调度,并没有关闭任何中断。
??②. 调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 一定要成对使用。
??③. 切不可在调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 之间调用任何会引起任务切换的 API,比如 vTaskDelayUntil、vTaskDelay、xQueueSend 等。
实验方法:
创建 2 个任务,情况如下:
??任务 1:优先级低,启用调度锁,调度锁开关之间使用 HAL_Delay 延时 5s,退出调度锁后,使用 HAL_Delay 继续延时 2s
??任务 2:优先级高,指示灯 100ms 快闪
实验分析:任务 2 本应该间隔 100ms 连续快闪,由于低优先级的任务一调用了调度锁开关函数,而且延时了 5s,延时期间关闭了任务切换,在此期间,任务 2 不运行,结果就是任务 2 的指示灯间隔 5s 快闪 10 次。