打印

关于OS_ENTER(EXIT)_CRITICAL使用

[复制链接]
13623|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lord_fan|  楼主 | 2011-10-15 13:48 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 lord_fan 于 2011-10-15 17:31 编辑

这两个必须是成对出现的?并且是成对执行完?

在中断子程序中,必须执行osintexit();

在osintexit()中,使用了OS_ENTER(EXIT)_CRITICAL这对宏,但是在判断应该做中断切换的时候,执行了osintctxsw(),该函数没有返回吧?那就执行不到os_EXIT_CRITICAL了吧?那和开头的enter宏不久没成对执行了?有关中断宏,没开中断宏?

求解。

void  OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif
   
   
    if (OSRunning == TRUE) {
        OS_ENTER_CRITICAL();
        if (OSIntNesting > 0) {                            /* Prevent OSIntNesting from wrapping       */
            OSIntNesting--;
        }
        if ((OSIntNesting == 0) && (OSLockNesting == 0)) { /* Reschedule only if all ISRs complete ... */
            OSIntExitY    = OSUnMapTbl[OSRdyGrp];          /* ... and not locked.                      */
            OSPrioHighRdy = (INT8U)((OSIntExitY << 3) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]);
            if (OSPrioHighRdy != OSPrioCur) {              /* No Ctx Sw if current task is highest rdy */
                OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];
                OSCtxSwCtr++;                              /* Keep track of the number of ctx switches */
                OSIntCtxSw();                              /* Perform interrupt level ctx switch       */
            }
        }
        OS_EXIT_CRITICAL();
    }
}
/*$PAGE*/

相关帖子

沙发
lord_fan|  楼主 | 2011-10-15 13:49 | 只看该作者
嵌入式版没人。这版比较火。就发这了。

使用特权

评论回复
板凳
airwill| | 2011-10-15 14:03 | 只看该作者
嗯, 楼主分析得很仔细. 所有的分析都很正确, 就一个地方.
osintctxsw(), 这个函数执行后还会回过来继续往下执行的.

OS_ENTER(EXIT)_CRITICAL 还是会成对的.
这两个函数不仅要成对出现, 而且通常执行次数都必须完全相同(不管进入任何分支条件).

使用特权

评论回复
地板
ayb_ice| | 2011-10-15 14:39 | 只看该作者
既然程序已经在中断中了,显然中断是开放的,那么中断切换任务后,直接开中断即可,速度还更快,显然也绝对不会出错
有些OS会保存各个任务的中断情况,不成对也行的,切换任务时通过堆栈恢复中断开关,当然USOS-II本身不是这样的,但也有人这样移植过

使用特权

评论回复
5
lord_fan|  楼主 | 2011-10-15 15:38 | 只看该作者
本帖最后由 lord_fan 于 2011-10-15 15:41 编辑
嗯, 楼主分析得很仔细. 所有的分析都很正确, 就一个地方.
osintctxsw(), 这个函数执行后还会回过来继续往下执行的.

OS_ENTER(EXIT)_CRITICAL 还是会成对的.
这两个函数不仅要成对出现, 而且通常执行次数都必须完全 ...
airwill 发表于 2011-10-15 14:03

不理解他为什么会返回来。
osintctxsw()不是已经用类似reti的中断返回指令弹出PC值呢?那么不是直接转到高优先级的任务了。中断程序ISR剩余的程序不会再执行了?为什么会再返回来?

使用特权

评论回复
6
lord_fan|  楼主 | 2011-10-15 15:44 | 只看该作者
既然程序已经在中断中了,显然中断是开放的,那么中断切换任务后,直接开中断即可,速度还更快,显然也绝对不会出错
有些OS会保存各个任务的中断情况,不成对也行的,切换任务时通过堆栈恢复中断开关,当然USOS-II本身不是这 ...
ayb_ice 发表于 2011-10-15 14:39


在osintctxsw()里面的程序有一条类似on_exit_critical的类似开中断语句?然后使用中断返回指令切到普通任务级?

使用特权

评论回复
7
ayb_ice| | 2011-10-15 15:49 | 只看该作者
任意中断的优先级其实都高于最高优先级的任务,所以任务切换必须等到中断退出后才能进行,否则RTOS就没有意义了,因为任何任务,哪怕他是最高级,其实时响应性能还是不能和中断相比的,所以有很多RTOS根本不管理中断,由用户自己管理

使用特权

评论回复
8
lord_fan|  楼主 | 2011-10-15 17:23 | 只看该作者
本帖最后由 lord_fan 于 2011-10-15 17:28 编辑
任意中断的优先级其实都高于最高优先级的任务,所以任务切换必须等到中断退出后才能进行,否则RTOS就没有意义了,因为任何任务,哪怕他是最高级,其实时响应性能还是不能和中断相比的,所以有很多RTOS根本不管理中断,由用 ...
ayb_ice 发表于 2011-10-15 15:49


我表达不是很清楚。图2的中间那个方框--中断子程序代码(不是整个ISR程序,而是用户编写部分)应该算是结束了吧?。那算不算从中断中切入普通任务?          图2和图3看起来的意思是不是从osintctxsw退出?   那楼主位的OS_EXIT_CRITICAL()和图2末尾的恢复CPU寄存器内容和中断返回指令不是没执行到了?

1.jpg (45.34 KB )

1.jpg

2.jpg (47.34 KB )

2.jpg

3.jpg (22.97 KB )

3.jpg

使用特权

评论回复
9
刘前辈| | 2011-10-16 11:09 | 只看该作者
  if (OSRunning == TRUE) {
        OS_ENTER_CRITICAL();

    if (OSIntNesting > 0) {  /* Prevent OSIntNesting from wrapping   */
            OSIntNesting--;
        }
………………


3楼说得对:LZ 程序完成的是一个多层中断嵌套!也就是当一个中断ISR还没执行完,又收到一个中断申请触发,因此挂起当前ISR,接收新的中断申请,进入新的ISR ;并且OSIntNesting++。——可以嵌套256 level 中断,所以CPU一直在优先完成这个中断嵌套,直到OSIntNesting=0 为止。所以:
    {
     if ((OSIntNesting == 0) && (OSLockNesting == 0))
     {
          ……
         if(……)
             {…………
        OSIntCtxSw();    /* Perform interrupt level ctx switch       */
            }
     }
}
这是中断嵌套程序,一层层完成并退出直到最后退出到:
       OS_EXIT_CRITICAL();

绝对匹配,一个不多/一个不少。
显然:
OSIntCtxSw();    /* Perform interrupt level ctx switch       */
执行完必然返回到上面循环,直到
((OSIntNesting == 0) && (OSLockNesting == 0))
为止。



、、

使用特权

评论回复
10
lord_fan|  楼主 | 2011-10-16 12:36 | 只看该作者
本帖最后由 lord_fan 于 2011-10-16 12:47 编辑

OSIntCtxSw();    /* Perform interrupt level ctx switch       */
执行完必然返回到上面循环,直到
((OSIntNesting == 0) && (OSLockNesting == 0))
为止。
刘前辈 发表于 2011-10-16 11:09

中断嵌套大致是明白了。
不过,不太明白的是:OSIntCtxSw()的作用。
他的作用是切换到高优先级的普通任务(即从中断任务到普通任务?)?  还会返回到最后的一层中断LEVEL=1?(普通任务执行玩回到中断?)  
根据aby_ice的回答应该不会是上面的这个意思。
他只执行一次吧。?

使用特权

评论回复
11
刘前辈| | 2011-10-16 14:36 | 只看该作者
本帖最后由 刘前辈 于 2011-10-16 17:14 编辑

少说了一句。中断嵌套挂起了很多待处理的中断任务 ISR,排成OSUnMapTbl[OSRdyGrp]队列;
  OSIntCtxSw();  切换的是从这个队列中查找出的中断优先级任务 ISR(上下文)。(是中断优先级任务队列,不是用户任务。别一说任务就理解成用户任务。中断级ISR也称为任务。凡是能被切换调度的都是任务(进程),无论内核还是用户 简单点说,2级中断嵌套,前面一个ISR还没完成,后面一个就到了;于是前面一个任务(进程)挂起(备份上下文)让后面一个执行,后面一个执行完后,运行OSIntCtxSw();  切换到前面一个已经挂起的任务 ISR(恢复上下文)。——注意不是用户任务(上下文)。 这样一层层执行恢复嵌套的中断队列,待所有嵌套中断任务都执行完(队列空)后,才会退出中断,返回到被中断的用户任务。
      按中断规则,从中断退出到被中断的用户任务,不是切换程序OSIntCtxSw()的调度作用,没有上下文切换过程,就是RETI返回。 这和裸奔程序一样。

       OSIntCtxSw();  的名称已经显式地表明了它是Int Context Switching 切换,肯定不会切到用户任务Context 去。

      所以,OSIntCtxSw( )一直是在中断级(内核环境)切换工作,和用户任务级无关。
               据说这一点是UC/OS 的得意之笔。


、、

使用特权

评论回复
12
lord_fan|  楼主 | 2011-10-16 20:17 | 只看该作者
少说了一句。中断嵌套挂起了很多待处理的中断任务 ISR,排成OSUnMapTbl[OSRdyGrp]队列;
  OSIntCtxSw();  切换的是从这个队列中查找出的中断优先级任务 ISR(上下文)。(是中断优先级任务队列,不是用户任务。别一 ...
刘前辈 发表于 2011-10-16 14:36

3Q。  我以为中断嵌套都是硬件处理的。 只要优先级高的硬件自动切换到高级中断里面运行,无需软件切换。原来高优先级中断嵌套也需要用软件来调度切换。


那么在中断里面就算使某一用户级任务高于被中断用户任务的话,也没办法在中断退出的时候立即调度,而是需要在返回被中断用户任务里面,然后才能调度?

使用特权

评论回复
13
刘前辈| | 2011-10-16 21:01 | 只看该作者
那么在中断里面就算使某一用户级任务高于被中断用户任务的话,也没办法在中断退出的时候立即调度,而是需要在返回被中断用户任务里面,然后才能调度?


没讲清楚,你所说的高于被中断的用户任务是属于真正的用户任务,还是属于中断ISR激活的任务?
    如果是后者,它还是属于内核级任务,它属于软中断任务,将在所有硬中断完成之后被调度执行;——也就是优先级按照 硬中断——软中断——用户任务 排序执行。很合理的OS规则。
    如果是前者,激活高优先级任务的事件必然触发中断,进入内核任务。——还是中断嵌套的事。
    如果是信号唤醒,不经过中断,那属于用户任务级,当然排在软中断任务后面调度,这是被中断的普通用户任务可能真的不会被中断ISR返回执行(返回到高优先级用户任务了)而被挂起了。——因为从中断返回用户之前总是需要进行一次调度查询。——这是一次调度时机。
若没有优先级任务请求,正常RETI返回到被中断任务;若有,帅先调度。

    无论谁设计OS优先级规则,都是这样吧。


、、


、、

使用特权

评论回复
14
lord_fan|  楼主 | 2011-10-16 22:03 | 只看该作者
本帖最后由 lord_fan 于 2011-10-16 22:05 编辑
在中断里面使某一个用户级任务高于被此中断的另外一个用户任务。刘前辈 发表于 2011-10-16 21:01


1、只有一个中断ISR。  用户任务优先级task1 <task2 ,task2获取信号量不到而被挂起
2、首先task1执行时,被中断进入ISR,ISR给task2信号量而激活他
3、但是不马上执行task2,而是等ISR执行完后,返回task1继续执行?然后再调度到task2?
4、上面这种情景是属于13L哪一种?没有中断嵌套,OSIntCtxSw()不会被执行到了?
5、不知道刘前辈说的ISR是指8L图2的整个中断服务子程序,还是图2其中的倒数第4个矩形框中断服务代码,不包括CPU push pop?

有点懵了。刘前辈有木有好书推荐。

使用特权

评论回复
15
pentral0311| | 2011-10-17 08:17 | 只看该作者
取经来的,我

使用特权

评论回复
16
刘前辈| | 2011-10-17 09:08 | 只看该作者
15#
1、只有一个中断ISR。  用户任务优先级task1 <task2 ,task2获取信号量不到而被挂起2、首先task1执行时,被中断进入ISR,ISR给task2信号量而激活他
    …………


基本概念:中断ISR,或者说内核任务里不允许使用信号量。

首先感谢你,能提出问题。

13#讲的有错误,以后来修改。



、、

使用特权

评论回复
17
lord_fan|  楼主 | 2011-10-18 12:43 | 只看该作者
基本概念:中断ISR,或者说内核任务里不允许使用信号量。

首先感谢你,能提出问题。

13#讲的有错误,以后来修改。

、、
刘前辈 发表于 2011-10-17 09:08


GOOD

使用特权

评论回复
18
yyql008| | 2012-3-11 17:43 | 只看该作者
不一定会执行 OS_EXIT_CRITICAL();

只有进入中断后,切不执行任务切换(就是普通的中断,并原处返回时),才执行 OS_EXIT_CRITICAL();
-------即恢复中断开关状态。
而如果执行了中断级切换,是不用执行OS_EXIT_CRITICAL();


这里可能大家又有疑惑----如果进行了任务切换,不执行OS_EXIT_CRITICAL();
会不会影响到原来被中断的任务(比如如果定义的是第2中开关中断方法,会不会老是把状态寄存器入栈而不出栈导致堆栈溢出?)。不会影响的!因为OSTickISR前面已经保存了栈顶指针。

使用特权

评论回复
19
mdq123| | 2012-8-4 14:29 | 只看该作者
灰常的有帮助,我也是在分析。3q

使用特权

评论回复
20
mdq123| | 2012-8-4 14:30 | 只看该作者
灰常的有帮助,我也是在分析。3q

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

308

帖子

0

粉丝