其他分享
首页 > 其他分享> > ucos(五)临界区

ucos(五)临界区

作者:互联网

一、概述

代码的临界段也称为临界区,指处理时不可分割的代码。一旦这部分代码开始执行,则不允许执行被打断。 大多数系统为确保临界段代码的执行不被中断,在进入临界段之前必须关中断,而临界段代码执行完后,要立即开中断。常见案例为喂狗、FLASH的写入、获取当前时钟节拍计数器等保护操作。   在UCOSIII中存在大量的临界区代码,分以下情况:   在os.h头文件有以下函数:
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u                             /* Deferred ISR Posts ------------------------------ */
                                                                 /* Lock the scheduler                                */
#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_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)       
#else         
#define  OS_CRITICAL_ENTER()                    CPU_CRITICAL_ENTER()
#define  OS_CRITICAL_EXIT()                     CPU_CRITICAL_EXIT()   
#endif      


#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS(); } while (0)          /* Disable   interrupts.                        */
#define  CPU_CRITICAL_EXIT()   do { CPU_INT_EN();  } while (0)          /* Re-enable interrupts.                        */

#define  CPU_INT_DIS()         do { cpu_sr = CPU_SR_Save(); } while (0) /* Save    CPU status word & disable interrupts.*/
#define  CPU_INT_EN()          do { CPU_SR_Restore(cpu_sr); } while (0) /* Restore CPU status word.                     */
上述代码:OS_CFG_ISR_POST_DEFERRED_EN该宏定义决定进入临界区时的操作   注: OS_CFG_ISR_POST_DEFERRED_EN使能的延迟中断提交已经不被推荐使用了。在uC/OS-III v3.06.00发布的更新记录中,已经将延迟中断提交列为了过时的方法并且去除了,推测可能是出于实时性和稳定性的考虑。
Deferred interrupt processing is now obsolete and has been removed。

二、如何使用

  情况1:若该临界区不希望受到异常与中断的影响,直接使用CPU_CRITICAL_ENTER与CPU_CRITICAL_EXIT函数,步骤如下:
CPU_SR_ALLOC();

CPU_CRITICAL_ENTER();  //屏蔽除NMI和fault以外的所有异常和中断,即将进入临界区 

临界区代码,该代码涉及中断访问

CPU_CRITICAL_EXIT() ;  //开启除NMI和fault以外的所有异常和中断,退出临界区

 

情况2:OS_CFG_ISR_POST_DEFERRED_EN为1,若临界区即使被中断打断,也不会影响结果,只是用于任务之间的互斥访问,步骤如下:
CPU_SR_ALLOC();

OS_CRITICAL_ENTER();  //锁定调度器,即将进入临界区 

临界区代码,该代码不涉及中断访问

OS_CRITICAL_EXIT() ;  //解锁调度器,退出临界区
  使用示例:获取当前时钟节拍计数器
OS_TICK  OSTimeGet (OS_ERR  *p_err)
{
    OS_TICK  ticks;
    CPU_SR_ALLOC();
    :
    :     
    CPU_CRITICAL_ENTER();
    ticks = OSTickCtr;
    CPU_CRITICAL_EXIT();
   *p_err = OS_ERR_NONE;
    return (ticks);
}

三、关所有异常和中断

1.屏蔽除NMI和fault以外的所有异常和中断,最后会调用以下代码:  
#define  CPU_INT_DIS()         do { cpu_sr = CPU_SR_Save(); } while (0) /* Save    CPU status word & disable interrupts.*/
#define  CPU_INT_EN()          do { CPU_SR_Restore(cpu_sr); } while (0) /* Restore CPU status word.                     */

CPU_SR_Save
        MRS     R0, PRIMASK                     ; Set prio int mask to mask all (except hard faults)
        CPSID   I
        BX      LR

CPU_SR_Restore                                  ; See Note #2.
        MSR     PRIMASK, R0
        BX      LR
  2.Cortex-M 处理器的异常中,编号 1~15 的为系统异常,16及以上的则为中断异常。     3.PRIMASK用于屏蔽除NMI和fault以外的所有异常和中断。该寄存器可以通过 MRS和MSR以下例方式访问: 《Cortex M3与M4权威指南》章节7.10.1 P265 In many applications you might need to temporarily disable all interrupts to carry out some timing critical tasks. You can use the PRIMASK register for this purpose. The PRIMASK register can only be accessed in privileged state. The PRIMASK register is used to disable all exceptions except NMI and Hard Fault. It effectively changes the current priority level to 0 (highest programmable level). In C programming, you can use the functions provided in CMSIS-Core to set and clear PRIMASK: 1)关中断
MOV R0,#1

MSR PRIMASK,R0
或者:
CPSID I;等价上面语句
  2)开中断
MOV R0,#0 MSR PRIMASK,R0
或者:
CPSIE I;等价上面语句

  

  

 

标签:ucos,中断,临界,CRITICAL,EXIT,OS,CPU
来源: https://www.cnblogs.com/yuanqiangfei/p/15229024.html