搜索
bottom↓
回复: 20

ucos中断服务疑问

[复制链接]

出0入0汤圆

发表于 2010-2-13 21:13:40 | 显示全部楼层 |阅读模式
用户中断服务子程序:
保存全部CPU寄存器; (1)
调用OSIntEnter或OSIntNesting直接加1; (2)
执行用户代码做中断服务; (3)
调用OSIntExit(); (4)
恢复所有CPU寄存器; (5)
执行中断返回指令;

以前写单片机时在中断我都是一进就关中断做关键处理,没有涉及保存全部CPU寄存器,我觉得这部分应该是硬件完成的吧?
之所以禁止任务调度是因为这是中断产生的压栈打乱原来任务在栈中的结构?

出0入0汤圆

 楼主| 发表于 2010-2-13 21:41:39 | 显示全部楼层
大过年的,都不容易啊

出0入0汤圆

发表于 2010-2-16 23:59:47 | 显示全部楼层
不同的处理器都会有不同的中断系统,
像cortex-m3在中断(异常)发生的时候,就会自动入栈xPSR,PC LR R12 R0-R3,不需要额外代码来完成。

51单片机也是会自动入栈中断点PC以及PSW等寄存器。

如果自动入栈的寄存器不足以完成你中断里面的操作,就需要额外的的入栈操作,也就是把没有自动入栈的手动入栈,然后在用已经入栈的寄存器做相关中断程序的操作。

禁止中断中进行任务调度主要是为了实时性的考虑,有低优先级中断挂起等待处理却在一个高优先级的中断中进行任务上下文切换的工作是不允许的(延长了低优先级中断的响应时间,再低优先级的中断也是中断,也要尽可能快地响应)

“禁止任务调度是因为这是中断产生的压栈打乱原来任务在栈中的结构”这种说法应该是不对的。

UCOS会判断中断套嵌的层数决定是不是要进行任务切换。如果有中断套嵌发生,直到最后一个中断响应需要推出的时候才会进行任务上下文的切换工作。

比如taskA执行过程中打入了int1,int1执行过程中打入了int2。int1和int2的入栈都可以是根据中断系统自己来完成,结合中断程序实际情况,决定额外入栈的寄存器进行手动入栈操作,这时候不用根据UCOS基于任务的堆栈格式。

int2返回到int1,由于不是最外层中断,所以不会进行任务切换处理,只是履行正常的出栈操作。
int1执行完成返回,由于已经是最外层的中断,返回时需要进行任务切换,所以需要在OSIntExit()的OSIntCtxSw 里面把int1从taskA任务打入时候入栈的寄存器按照UCOS规定的任务寄存器入栈顺序进行排列,可能还需要进行额外的寄存器入栈操作。 这样在从int1返回以后就会切换到当前优先级最高的任务开始执行。等以后切换回taskA的时候也会从原来被int1打断的位置从新开始执行了。

所以不会存在“中断产生的压栈打乱原来任务在栈中的结构”这种情况。

以上全部个人观点,如有问题请指正。

aaa1982

出0入0汤圆

 楼主| 发表于 2010-2-18 15:36:49 | 显示全部楼层
楼上功底不错呀,我没有研究过任何一款CPU结构,看来还得努力呀

出0入0汤圆

发表于 2010-2-28 21:44:40 | 显示全部楼层
纠正一下“51单片机也是会自动入栈中断点PC以及PSW等寄存器”,好像只会自动入栈PC,其他的都需要手动保护。

出0入0汤圆

发表于 2010-7-6 16:36:16 | 显示全部楼层
楼上的 兄台 厉害!
我最近在玩 ucos ATMEGA128 . 在运行中断函数的时候,总是会 复位!

/*外部中断INT6,下降沿触发*/
#pragma interrupt_handler Int6: 8
void Int6(void)
{
       
        OSIntEnter ( );
       
       
        PORTB ^= (1 << PB6);                /*PB1电平取反*/
       
        OSMboxPost(MBox,&MSg[2]);
       
        OSIntExit ( );
       
}


OSIntExit()函数如下:
void  OSIntExit (void)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
   
   

    cpu_sr = 0;                                            /* Prevent compiler warning                 */
#endif   
    if (OSRunning == TRUE)
        {
        OS_ENTER_CRITICAL();
        if (OSIntNesting > 0)
        {                            /* Prevent OSIntNesting from wrapping       */
            OSIntNesting--;
        }
        if (OSIntNesting == 0)
        {                           /* Reschedule only if all ISRs complete ... */
            if (OSLockNesting == 0)
                {                      /* ... and not locked.                      */
                y             = OSUnMapTbl[OSRdyGrp];         
                OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
                if (OSPrioHighRdy != OSPrioCur)
                        {          /* No Ctx Sw if current task is highest rdy */
                    OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
                    OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task  */
#endif
                    OSCtxSwCtr++;                          /* Keep track of the number of ctx switches */
                    OSIntCtxSw();                          /* Perform interrupt level ctx switch       */
                    
                }
            }
        }
        OS_EXIT_CRITICAL();
    }
}
/*$PAGE*/


下面是  中断任务调度的 汇编代码


;/*$PAGE*/.
;********************************************************************************************************
;                                       TASK LEVEL CONTEXT SWITCH
;
; Description : This function is called when a task makes a higher priority task ready-to-run.
;
; Note(s)     : 1) Upon entry,
;                  OSTCBCur     points to the OS_TCB of the task to suspend
;                  OSTCBHighRdy points to the OS_TCB of the task to resume
;
;               2) The stack frame of the task to suspend looks as follows:
;
;                                       SP+0 --> LSB of task code address
;                                         +1     MSB of task code address                (High memory)
;
;               3) The saved context of the task to resume looks as follows:
;
;                  OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer           (Low memory)
;                                                SPH of (return) stack pointer
;                                                Flags to load in status register
;                                                R31
;                                                R30
;                                                R27
;                                                .
;                                                .
;                                                R0
;                                                PCH
;                                                PCL                                     (High memory)
;********************************************************************************************************

_OSCtxSw::
                PUSH_ALL                            ; Save current task's context
                PUSH_SREG
                PUSH_SP

                LDS     R30,_OSTCBCur               ; Z = OSTCBCur->OSTCBStkPtr
                LDS     R31,_OSTCBCur+1             ;
                ST      Z+,R28                      ; Save Y (R29:R28) pointer
                ST      Z+,R29                      ;

                CALL    _OSTaskSwHook               ; Call user defined task switch hook

                LDS     R16,_OSPrioHighRdy          ; OSPrioCur = OSPrioHighRdy
                STS     _OSPrioCur,R16

                LDS     R30,_OSTCBHighRdy           ; Let Z point to TCB of highest priority task
                LDS     R31,_OSTCBHighRdy+1         ; ready to run
                STS     _OSTCBCur,R30               ; OSTCBCur = OSTCBHighRdy
                STS     _OSTCBCur+1,R31             ;

                LD      R28,Z+                      ; Restore Y pointer
                LD      R29,Z+                      ;

                POP_SP                              ; Restore stack pointer
                POP_SREG                            ; Restore status register
                POP_ALL                             ; Restore all registers

                RET

;/*$PAGE*/.
;*********************************************************************************************************
;                                INTERRUPT LEVEL CONTEXT SWITCH
;
; Description : This function is called by OSIntExit() to perform a context switch to a task that has
;               been made ready-to-run by an ISR.
;
; Note(s)     : 1) Upon entry,
;                  OSTCBCur     points to the OS_TCB of the task to suspend
;                  OSTCBHighRdy points to the OS_TCB of the task to resume
;
;               2) The stack frame of the task to suspend looks as follows:
;
;                  OSTCBCur->OSTCBStkPtr ------> SPL of (return) stack pointer           (Low memory)
;                                                SPH of (return) stack pointer
;                                                Flags to load in status register
;                                                R31
;                                                R30
;                                                R27
;                                                .
;                                                .
;                                                R0
;                                                PCH
;                                                PCL                                     (High memory)
;
;               3) The saved context of the task to resume looks as follows:
;
;                  OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer           (Low memory)
;                                                SPH of (return) stack pointer
;                                                Flags to load in status register
;                                                R31
;                                                R30
;                                                R27
;                                                .
;                                                .
;                                                R0
;                                                PCH
;                                                PCL                                     (High memory)
;*********************************************************************************************************

_OSIntCtxSw::
                CALL    _OSTaskSwHook               ; Call user defined task switch hook

                LDS     R16,_OSPrioHighRdy          ; OSPrioCur = OSPrioHighRdy
                STS     _OSPrioCur,R16              ;

                LDS     R30,_OSTCBHighRdy           ; Z = OSTCBHighRdy->OSTCBStkPtr
                LDS     R31,_OSTCBHighRdy+1         ;
                STS     _OSTCBCur,R30               ; OSTCBCur = OSTCBHighRdy
                STS     _OSTCBCur+1,R31             ;

                LD      R28,Z+                      ; Restore Y pointer
                LD      R29,Z+                      ;

                POP_SP                              ; Restore stack pointer
                POP_SREG                            ; Restore status register
                POP_ALL                             ; Restore all registers
            
                RET

;/*$PAGE*/.

请大侠 不吝赐教

出0入0汤圆

发表于 2010-7-6 16:48:38 | 显示全部楼层
回复【2楼】aaa1982
如果自动入栈的寄存器不足以完成你中断里面的操作,就需要额外的的入栈操作,也就是把没有自动入栈的手动入栈,然后在用已经入栈的寄存器做相关中断程序的操作。
-----------------------------------------------------------------------
这个说法是有问题的,在有OS的情况下,如果OS允许抢占式任务切换(即在中断服务程序中进行任务切换),那么在中断服务程序的开始处必须保存任务的全部现场信息,因为本次中断可能会使一个具有比被中断任务更高优先级的任务转为就绪态、在嵌套的中断退出前可能会有任务切换。

出0入0汤圆

发表于 2010-7-6 17:48:39 | 显示全部楼层
顶楼上的哥!!!!
这个说法是有问题的,在有OS的情况下,如果OS允许抢占式任务切换(即在中断服务程序中进行任务切换),那么在中断服务程序的开始处必须保存任务的全部现场信息,因为本次中断可能会使一个具有比被中断任务更高优先级的任务转为就绪态、在嵌套的中断退出前可能会有任务切换。
----------------------------------------------------------------------------------------
“那么在中断服务程序的开始处必须保存任务的全部现场信息”
手动保存 还是 交给 编译器???
我在 ATMEGA128 下 UCOS   编译器ICC, 只要 函数 触发中断 ,整个系统 就会复位,调试了 好久,好像是 这个函数---
OSIntExit ( ); 的问题。。。。。、、

不知道 我这样写的 格式对不对啊, 中断代码 如下

  /*外部中断INT6,下降沿触发*/
#pragma interrupt_handler Int6: 8
void Int6(void)  
{

OSIntEnter ( );


PORTB ^= (1 << PB6); /*PB1电平取反*/

OSMboxPost(MBox,&MSg[2]);

OSIntExit ( );

}

出0入0汤圆

发表于 2010-7-7 02:03:55 | 显示全部楼层
记得在中断中使用μC/OS-II的系统调用,是有限制的——只能使用OSInt...开头的那些API,你的代码中,是否应该使用OSIntMboxPost啊?

出0入0汤圆

发表于 2010-7-7 02:06:29 | 显示全部楼层
回复【7楼】wu_jin_liang
顶楼上的哥!!!!
“那么在中断服务程序的开始处必须保存任务的全部现场信息”
手动保存 还是 交给 编译器???
-----------------------------------------------------------------------

因为你不能控制编译器所生成的、进出中断服务程序的代码(在用C语言编程的情况下),所以,编译器保存了的,你就不用再管了;编译器没有保存的,那就得你自己负责给压到堆栈里去。

出0入0汤圆

发表于 2010-7-7 09:45:32 | 显示全部楼层
我来说两句:

   1. 【4楼】 aaa1982
         纠正一下“51单片机也是会自动入栈中断点PC以及PSW等寄存器”,好像只会自动入栈PC,其他的都需要手动保护。
-----------------------------------------------------------------------------------------------------------
      大家都使用C语言编写中断服务程序,可能没有看到入栈方面的代码,其实这部分代码只是编译器帮你完成了。
         如果你使用汇编语言编写中断服务程序,这部分代码必须由你来完成。

   2、中断服务程序中,必须调用OSIntCtxSw()进行任务切换。
   3、任务程序代码中,必须调用OSCtxSw()进行任务切换

   4、OSMboxPost(MBox,&MSg[2]); 必须在任务切换中使用,不能在中断服务程序中使用。
         中断服务程序中必须使用“无等待”的信号量函数;否则如果出现等待不到信息,那么程序就会在中断服务程序中“死等”,造成系统崩溃。

出0入0汤圆

发表于 2010-7-8 09:37:19 | 显示全部楼层
Int Mark

出0入0汤圆

发表于 2010-7-8 10:39:34 | 显示全部楼层
回复【7楼】wu_jin_liang  
顶楼上的哥!!!!  
“那么在中断服务程序的开始处必须保存任务的全部现场信息”  
手动保存 还是 交给 编译器???  
-----------------------------------------------------------------------

因为你不能控制编译器所生成的、进出中断服务程序的代码(在用C语言编程的情况下),所以,编译器保存了的,你就不用再管了;编译器没有保存的,那就得你自己负责给压到堆栈里去。  
__________________________


问题解决了 ,  在OS下  进入中断后 ,C编译器 自动将 寄存器内容 压入  公栈,  而  ISR结束后 调OSIntExit ( )恢复现场;调出当时 的 就绪状态 优先级最高的运行。 那么 之前被中断的函数 就 丢掉了

所以必须在 进入 中断 后 ,用汇编把 软件堆栈指针 保存到 OSTCBCur中 ,就可以了。

。。。。下一步 开始学习LINUX  但是不知道怎么 下手啊?? 难道要像学 UCOS一样 分析 源代码吗》????

出0入0汤圆

发表于 2010-7-13 17:20:52 | 显示全部楼层
回复【12楼】wu_jin_liang
基本上 跟你同步 不知道这个LINUX是怎么个学法 没有接触过。不过我想,首先看一下它的内核是必须得吧?

出0入0汤圆

发表于 2010-8-12 08:04:14 | 显示全部楼层
回复【10楼】ba_wang_mao
我来说两句:
   1. 【4楼】 aaa1982  
         纠正一下“51单片机也是会自动入栈中断点pc以及psw等寄存器”,好像只会自动入栈pc,其他的都需要手动保护。
-----------------------------------------------------------------------------------------------------------
      大家都使用c语言编写中断服务程序,可能没有看到入栈方面的代码,其实这部分代码只是编译器帮你完成了。
         如果你使用汇编语言编写中断服务程序,这部分代码必须由你来完成。
   2、中断服务程序中,必须调用osintctxsw()进行任务切换。
   3、任务程序代码中,必须调用osctxsw()进行任务切换
   4、osmboxpost(mbox,&amp......
-----------------------------------------------------------------------

看来需要确认一下,我直接看得disasemble view,在函数调用和中断程序都没看到压栈指令,但是sp增加了2个字节,存储的PC返回地址,ret 或者reti 返回这个地址。所以我说是自动入栈的。

当然都是我的个人意见

出0入0汤圆

发表于 2010-8-12 08:29:51 | 显示全部楼层
回复【10楼】ba_wang_mao  
我来说两句:
   1. 【4楼】 aaa1982
         纠正一下“51单片机也是会自动入栈中断点pc以及psw等寄存器”,好像只会自动入栈pc,其他的都需要手动保护。
-----------------------------------------------------------------------------------------------------------
      大家都使用c语言编写中断服务程序,可能没有看到入栈方面的代码,其实这部分代码只是编译器帮你完成了。
         如果你使用汇编语言编写中断服务程序,这部分代码必须由你来完成。
   2、中断服务程序中,必须调用osintctxsw()进行任务切换。
   3、任务程序代码中,必须调用osctxsw()进行任务切换
   4、OSMboxPost(MBox,&MSg[2]); 必须在任务切换中使用,不能在中断服务程序中使用。  
         中断服务程序中必须使用“无等待”的信号量函数;否则如果出现等待不到信息,那么程序就会在中断服务程序中“死等”,造成系统崩溃。
-----------------------------------------------------------------------

1, 就AVR而言,执行CALL,ISR等,硬件自动保存PC到堆栈,SP自动加2,(有些自动加3,如MEGA2561等),而执行RET,RETI等指令,SP自动减2或减3,同时将PC还原,不需你人为参与。
4,还真没见过post不能在中断中执行的说法,只听过不能在中断里pend的道理。

出0入0汤圆

发表于 2010-9-7 13:26:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-16 22:09:20 | 显示全部楼层
恩,深受教育~~

出0入0汤圆

发表于 2012-6-15 11:32:23 | 显示全部楼层
wu_jin_liang 发表于 2010-7-8 10:39
回复【7楼】wu_jin_liang  
顶楼上的哥!!!!  
“那么在中断服务程序的开始处必须保存任务的全部现场信 ...

你好,我在论坛上看到你在ucos里调试串口中断时遇到的问题,并已解决,我母亲在用maga128调试时也遇到类似问题了,希望你能把中断处理那部分的汇编代码发给我参考下,谢谢!

出0入0汤圆

发表于 2012-6-15 13:25:48 | 显示全部楼层
cheeery 发表于 2012-6-15 11:32
你好,我在论坛上看到你在ucos里调试串口中断时遇到的问题,并已解决,我母亲在用maga128调试时也遇到类 ...

你好,我在论坛上看到你在ucos里调试串口中断时遇到的问题,并已解决,我母亲在用maga128调试时也遇到类 ...


你母亲也是弄UCOS的

出0入0汤圆

发表于 2014-11-18 11:01:54 | 显示全部楼层
我在ucos中使用开门狗产生复位的中断,有问题呢
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-9 02:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表