临界段代码保护
什么是临界段?
临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段。
那么什么场合不能被打断?适用的场合:
1.外设:需严格按照时序初始化的外设:IIC、SPI等等 。软件IIC需要几微秒的延时,所以不能被打断。
2.系统:系统自身需求 。
3.用户:系统自身需求 。
问题:那么什么可以打断当前程序的运行?
中断、任务调度器(任务切换,低优先级的被高优先级的抢占)。
问题:如何不被打断?
直接关中断,关中断,一是可以把中断给关闭,二是任务调度器也打断不了。为什么关中断也会导致任务调度器也无法打断正在运行的程序呢?因为中断中有一个pendsv,他就是实现任务切换的一个中断,所以关中断也会导致任务调度器也打断不了现在正在运行的程序。
为什么关闭中断后,任务调度器也打断不了?
PendSV是实现我们任务切换的一个中断,而这个中断我们设置的是最低的优先级,我们关闭中断后,肯定是没有办法响应的(FreeRTOS所管理范围的中断,不在范围内的还是可以打断的)。
临界段代码保护函数
FreeRTOS 在进入临界段代码的时候需要提前关闭中断,为什么要提前关闭中断呢?
因为临界段代码的含义就是“不能被打断的代码”,所以肯定进入前要关闭中断,当处理完临界段代码以后再打开中断。
函数
描述
taskENTER_CRITICAL()
任务级进入临界段,其实就是关中断
taskEXIT_CRITICAL()
任务级退出临界段,其实就是开中断
taskENTER_CRITICAL_FROM_ISR()
中断级进入临界段
taskEXIT_CRITICAL_FROM_ISR()
中断级退出临界段
我们上节课所学的中断管理,也是开关中断,只不过所用的函数是:portDISABLE_INTERRUPTS()和portENABLE_INTERRUPTS(),那么这两个函数和上面的函数有什么不同呢?
其实表格中的函数的本质也是调用这两个中断函数,只不过多了嵌套的功能。为什么会多了嵌套功能呢?我查看了函数内部,其实就是设置了一个变量,每调用一次taskENTER_CRITICAL()函数,这个变量就会++,每调用一次taskEXIT_CRITICAL()函数,这个变量就会--。
任务调度器的挂起和恢复
任务调度器被挂起,就说明任务不能被切换了,但是中断依旧正常响应,就说明此函数不需要关闭中断。
函数
描述
vTaskSuspendAll()
挂起任务调度器
xTaskResumeAll()
恢复任务调度器
1、与临界区不一样的是,挂起任务调度器,未关闭中断;
2、它仅仅是防止了任务之间的资源争夺,中断照样可以直接响应;
3、挂起调度器的方式,算是一种任务与任务之间的“临界区”,只不过这个“临界区”既不用去延时中断,又可以做到临界区的相对安全。什么叫“延时中断”?因为中断特别是FreeRTOS中,不能太长时间,所以当临界区的代码过多,可能会导致执行的时间长,紧急中断如果被屏蔽,可能会导致严重的错误,所以就有了这两个函数。