ucos-ii开关中断

摘自:http://www.arm32.com/post/229.html

为了处理临界区代码,必须关中断,等处理完毕后,再开中断。关中断可以避免其他任务或中断进入临界区代码。uC/OS-II定义了这两个宏来实现,但注意一条:调用uC/OS-II功能函数时,中断应该总是开着的。

1 )当 OS_CRITICAL_METHOD= = 1 时,简单实现如下:
    #define  OS_ENTER_CRITICAL() disable_int() 
    #define OS_EXIT_CRITICAL() enable_int()
但这样有一个问题,如果禁止中断的情况下调用 uC/OS-II 功能函数,那么从功能函数返回时,中断可能变成允许的了,而实际上还是希望是禁止的。

 2 )当 OS_CRITICAL_METHOD= = 2 时,实现如下:
    #define  OS_ENTER_CRITICAL()    
            asm(“PUSH PSW”);
            asm(“DI”);
    
#define  OS_EXIT_CRITICAL()
            asm(“POP PSW”);
执行 OS_ENTER_CRITICAL() 时,先将中断状态保存到堆栈,然后关中断;执行 OS_EXIT_CRITICAL() 时,再从堆栈中恢复原来的中断开 / 关状态。这种方法不会改变中断状态,避免前面的问题。
3 )当 OS_CRITICAL_METHOD= = 3 时,实现如下:
  #define  OS_ENTER_CRITICAL()    
        cpu_sr 
=  get_processor_psw();
        disable_interrupts();
 
#define  OS_EXIT_CRITICAL()
        set_ processor_psw(cpu_sr);

====================
这里注意的是OS_CRITICAL_METHOD ,ucos提供了3种方法实现,第一种方法是直接简单的开关中断方式,但是一旦嵌套会发生意外,比如:

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
void Task (void *data)   
  
    .........         
  
   OS_ENTER_CRITICAL();    
   //进入临界区1   
  
   //调用了某一函数,该函数也需要进入临界区:   
   {   
     OS_ENTER_CRITICAL();    
     ................   
     OS_EXIT_CRITICAL();    
   }   
   //这里就自然变成废墟了   
   ...........   
   //临界区切掉   
   OS_EXIT_CRITICAL();    
       
}  
 void Task (void *data)
{
     .........     

    OS_ENTER_CRITICAL(); 
    //进入临界区1

    //调用了某一函数,该函数也需要进入临界区:
    {
      OS_ENTER_CRITICAL(); 
      ................
      OS_EXIT_CRITICAL(); 
    }
    //这里就自然变成废墟了
    ...........
    //临界区切掉
    OS_EXIT_CRITICAL(); 
     
 }

此方法太多弊端,所以新内核中看不到她的影子了

于是出现第二种方法,执行OS_ENTER_CRITICAL()时首先保存中断状态到堆栈中,然后关中断,执行OS_EXIT_CRITICAL()时,再从堆栈中恢复原来的中断开/关状态。这种方法不会改变中断状态,由于用到堆栈,这样会带来隐忧,看邵贝贝翻译的有这样说:

        “但是,用户在使用这种方法的时候还得十分小心,因为如果用户在调用象OSTimeDly()之类的服务之前就禁止中断,很有可能用户的应用程序会崩溃。发生这种情况的原因是任务被挂起直到时间期满,而中断是禁止的,因而用户不可能获得节拍中断!很明显,所有的PEND调用都会涉及到这个问题,用户得十分小心。一个通用的办法是用户应该在中断允许的情况下调用µC/OS-Ⅱ的系统服务!”

第3种方法直接保存到任务局部变量中去

#if     OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL()  (cpu_sr = OSCPUSaveSR())
#define OS_EXIT_CRITICAL()   (OSCPURestoreSR(cpu_sr))
#endif

避免了使用堆栈

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值