uC/OS-III之临界段代码学习总结

1.临界段代码,也叫临界区,是指那些必须完整连续运行,不可被打断的代码段。在uC/OS-III中存在大量的临界段代码。

2.中断处理程序和任务都会访问的临界段代码,需要使用关中断的方法加以保护;仅由任务访问的临界段代码,可以通过给调度器上锁的方法来保护。

3.在uC/OS-III中,使用宏OS_CRITICAL_ENTER()进入临界区;使用宏OS_CRITICAL_EXIT()和OS_CRITICAL_EXIT_NO_SCHED()退出临界区。
注:上面的三个宏是uC/OS-III内部的定义,外部的任务不能使用。

3.uC/OS-III可以使用两种方式保护临界段代码:关中断或锁定调度器。
OS_CFG_ISR_POST_DEFERRED_EN为0,使用关中断的方式;OS_CFG_ISR_POST_DEFERRED_EN为1,使用锁定调度器方式。
注:OS_CFG_ISR_POST_DEFERRED_EN在os_cfg.h文件中定义

4.有关保护临界段代码的宏定义的代码位于os.h文件中,87行 - 141行

#if OS_CFG_ISR_POST_DEFERRED_EN > 0u                           // 延迟发布模式,采用锁定调度器方式

// 进入临界区
#define  OS_CRITICAL_ENTER()                                       \
         do {                                                      \
             CPU_CRITICAL_ENTER();                                 \
             OSSchedLockNestingCtr++;                              \
             if (OSSchedLockNestingCtr == 1u) {                    \
                 OS_SCHED_LOCK_TIME_MEAS_START();                  \
             }                                                     \
             CPU_CRITICAL_EXIT();                                  \
         } while (0)
// 进入临界区且中断已关闭
#define  OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT()                     \
         do {                                                      \
             OSSchedLockNestingCtr++;                              \
             if (OSSchedLockNestingCtr == 1u) {                    \
                 OS_SCHED_LOCK_TIME_MEAS_START();                  \
             }                                                     \
             CPU_CRITICAL_EXIT();                                  \
         } while (0)
// 退出临界区
#define  OS_CRITICAL_EXIT()                                        \
         do {                                                      \
             CPU_CRITICAL_ENTER();                                 \
             OSSchedLockNestingCtr--;                              \
             if (OSSchedLockNestingCtr == (OS_NESTING_CTR)0) {     \
                 OS_SCHED_LOCK_TIME_MEAS_STOP();                   \
                 if (OSIntQNbrEntries > (OS_OBJ_QTY)0) {           \
                     CPU_CRITICAL_EXIT();                          \
                     OS_Sched0();                                  \
                 } else {                                          \
                     CPU_CRITICAL_EXIT();                          \
                 }                                                 \
             } else {                                              \
                 CPU_CRITICAL_EXIT();                              \
             }                                                     \
         } while (0)
// 退出临界区,不调度
#define  OS_CRITICAL_EXIT_NO_SCHED()                               \
         do {                                                      \
             CPU_CRITICAL_ENTER();                                 \
             OSSchedLockNestingCtr--;                              \
             if (OSSchedLockNestingCtr == (OS_NESTING_CTR)0) {     \
                 OS_SCHED_LOCK_TIME_MEAS_STOP();                   \
             }                                                     \
             CPU_CRITICAL_EXIT();                                  \
         } while (0)

#else                                                           // 直接发布模式,采用关中断方式

#define  OS_CRITICAL_ENTER()              CPU_CRITICAL_ENTER()  // 进入临界区
#define  OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT()                  // 进入临界区
#define  OS_CRITICAL_EXIT()               CPU_CRITICAL_EXIT()   // 退出临界区
#define  OS_CRITICAL_EXIT_NO_SCHED()      CPU_CRITICAL_EXIT()   // 退出临界区

#endif

5.再深入研究一下

#define  CPU_INT_DIS()         do { cpu_sr = CPU_SR_Save(); } while (0)  // 保存CPU的状态寄存器并禁止中断
#define  CPU_INT_EN()          do { CPU_SR_Restore(cpu_sr); } while (0)  // 恢复CPU状态寄存器的值

#ifdef   CPU_CFG_INT_DIS_MEAS_EN                    // 允许计算中断关闭时间
// 禁止中断,并开启计算
#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS();         \
                                    CPU_IntDisMeasStart(); }  while (0)
// 使能中断,并停止计算
#define  CPU_CRITICAL_EXIT()   do { CPU_IntDisMeasStop();  \
                                    CPU_INT_EN();          }  while (0)
#else                                               // 禁止计算中断关闭时间                                   
#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS(); } while (0)  // 禁止中断                                                 
#define  CPU_CRITICAL_EXIT()   do { CPU_INT_EN();  } while (0)  // 使能中断
#endif

6.说明
上面的代码中涉及到计算中断关闭时间或锁定调度器时间的部分,这里不再做详细说明,以后用到之后再详细解释。

7.注意
在使用进入临界区和退出临界区的宏定义时,需要在使用前声明一个宏CPU_SR_ALLOC(),该宏的定义位于cpu.h文件中,295行 - 299行

#if     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
#define  CPU_SR_ALLOC()             CPU_SR  cpu_sr = (CPU_SR)0  // 声明cpu_sr变量,临时存储CPU的状态寄存器的值
#else
#define  CPU_SR_ALLOC()
#endif

你可能感兴趣的:(uC/OS-III)