天天看点

学习FreeRTOS之第七章——资源管理

一,在多任务操作系统中,当一个任务访问一个资源时,在没有访问完成的情况下,任务切换出运行状态。这时,可能会出现数据损坏等问题。看看下面几种情况:

1,访问外围设备。例如:两个任务写数据到LCD,任务A写“Hello,world”到LCD,在任务A未写完的情况下,任务B抢占了任务A,任务B写其他的数据到LCD,这时LCD会显示错误。

2,常见的“读,修改,写”三步操作。

3,对变量的非原子访问。例如:当结构体或者变量大于CPU架构的字大小时,对该结构体或者变量进行访问(在16位的机器上,对32的变量进行写操作)。

4,函数的重入。例如:下面的函数是不可重入的。

学习FreeRTOS之第七章——资源管理

二, 为了解决上面的问题,FreeRTOS提供了很多解决方法,但是最好的方法是在进行应用程序设计时,使资源不在任务之间进行共享,并且每个任务只能访问一个资源。

1,临界段保护

使用taskENTER_CRITICAL()/taskEXIT_CRITICAL()和taskENTER_CRITICAL_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR()。临界段保护是一个宏,根据configMAX_SYSCALL_INTERRUPT_PRIORITY的设置,要么完全禁止了中断或者禁止configMAX_SYSCALL_INTERRUPT_PRIORITY设置优先级以上的中断。理想使用情况是临界段间的代码越短越好。可以嵌套使用。

2,挂起调度器

使用vTaskSuspendAll()和xTaskResumeAll()来保护资源。这种方式可以避免任务切换,但是中断仍然在工作。挂起调度器可以嵌套,任务调度器挂起时,不能调用API函数。

3,互斥信号量

使用互斥信号量需要将configUSE_MUTEXES设置为1。当任务要访问一个资源时,首先要获得互斥信号量,访问完成时,释放该互斥信号量。

学习FreeRTOS之第七章——资源管理
学习FreeRTOS之第七章——资源管理

在上面的执行过程中出现了任务优先级反转的问题,高优先级的Task2等待低优先级的Task1。在最差的情况下,如果有一个介于任务2和任务1之间优先级的其他任务,这时,任务2会一直等待,甚至任务1都不会执行。

为了解决优先级反转问题,互斥信号量引入了优先级继承,这也是互斥信号量和二进制信号量的一个不同点。拥有互斥信号量的低优先级任务会继承等待该互斥信号量的任务中最高优先级,并在释放该互斥信号量时,复位优先级。互斥信号量不能在ISR中使用。

学习FreeRTOS之第七章——资源管理

 在使用互斥信号量时,当两个任务都在等待对方的资源释放时,可能会发生死锁现象。避免死锁的最好方法是在设计时,避免死锁发生,尤其是在等待信号量时,不要设置为死等。

4,递归互斥信号量

当一个任务在没有释放信号量的情况下,获取两次信号量,会造成自锁。这种情况可以通过使用递归互斥信号量替代标准互斥信号量。

学习FreeRTOS之第七章——资源管理

 在使用互斥信号量的应用中,如果两个任务优先级相同,可能会出现其中一个任务的运行时间不如预期时间,例如:

学习FreeRTOS之第七章——资源管理

5,守护任务

守护任务是一个唯一对资源拥有所有权的任务,只有守护任务能够直接访问资源。其他任务要访问该资源,需要通过守护任务提供的服务进行间接访问。

继续阅读