搜索
bottom↓
回复: 6

ucos中断问题

[复制链接]

出0入0汤圆

发表于 2012-10-22 22:49:42 | 显示全部楼层 |阅读模式
最近学习ucos的移植代码。看到开关中断处。有点问题



首先ucos支持三种开关中断方式

下面是pc移植的代码(ucos官方)

#define  OS_CRITICAL_METHOD    2



#if      OS_CRITICAL_METHOD == 1

#define  OS_ENTER_CRITICAL()  asm  CLI                    /* Disable interrupts                        */

#define  OS_EXIT_CRITICAL()   asm  STI                    /* Enable  interrupts                        */

#endif



#if      OS_CRITICAL_METHOD == 2

#define  OS_ENTER_CRITICAL()  asm {PUSHF; CLI}            /* Disable interrupts                        */

#define  OS_EXIT_CRITICAL()   asm  POPF                   /* Enable  interrupts                        */

#endif



#if      OS_CRITICAL_METHOD == 3

#define  OS_ENTER_CRITICAL()  (cpu_sr = OSCPUSaveSR())    /* Disable interrupts                        */

#define  OS_EXIT_CRITICAL()   (OSCPURestoreSR(cpu_sr))    /* Enable  interrupts                        */

第一种方式最简单,就不再说了。

问题是后面两种方式,这两种方式都是为了解决如下情况,逻辑一样,只是一个存到栈,一个存到变量cpu_sr中了



1.OS_ENTER_CRITICAL()

2.。。。。。。。。。。。代码

3.           OS_ENTER_CRITICAL()

4.           。。。。。。。。用户代码

5.           OS_EXIT_CRITICAL()

6.。。。。。。。。。。代码

7.OS_EXIT_CRITICAL()



如果这种情况用 第一种方式不能保证 1-7行中断都是关着的,因为第5行调用了开中断指令

所以用后两种方式就很好的解决了这个问题

!!!!!!!

这才有我的问题。问题处在(比如第二种方式)

#if      OS_CRITICAL_METHOD == 2

#define  OS_ENTER_CRITICAL()  asm {PUSHF; CLI}            /* Disable interrupts                        */

#define  OS_EXIT_CRITICAL()   asm  POPF                   /* Enable  interrupts                        */

这样的话 pushf实现了保存状态标志,在退出 关中断的时候popf出栈恢复 标志寄存器内容

但是pushf不仅会将中断允许标志压入栈,同时会将其他标志,比如ZF。OF压入。那么问题就来了。调用popf恢复的中断状态标志就变成了代码第 3行执行处的标志状态了。。。。。。。。。

里面的ZF OF等标志也会恢复到了第三行的状态,正常的话那么第6行以后的代码执行应该用第5行执行后的状态标志,但是因为pushf popf的调用,那么ZF OF等的标志只是第三行的标志态。。。。岂不是执行程序就不对了



想了很久,很纠结,希望高手指教

QQ:1183557534,有知道的请回帖或联系我

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2012-10-23 09:33:14 | 显示全部楼层
确实像你说的那样,所以在关中断和开中断之间的代码(即临界区的代码),要求简单,且只完成独立的功能。LZ可以参考几个例程,看看什么时候用此两条指令,中间做了什么工作,就明白了。

出0入0汤圆

 楼主| 发表于 2012-10-23 12:55:20 | 显示全部楼层
再简单,也肯定会影响标志寄存器啊。哪怕是加减运算都要对标志位有影响的。
不知道 是不是我哪里理解的不对。楼上能点拨一下小弟吗

出0入0汤圆

发表于 2012-10-24 09:04:43 | 显示全部楼层
要求简单是为了尽量保证操作系统的实时性,上面的举例中你提到“ 里面的ZF OF等标志也会恢复到了第三行的状态,正常的话那么第6行以后的代码执行应该用第5行执行后的状态标志,但是因为pushf popf的调用,那么ZF OF等的标志只是第三行的标志态。。。。岂不是执行程序就不对了 ”,其实不是这样的,第6行以后的代码就应该执行第3行执行后的状态标志,第3-5行的代码功能是独立的,执行完后不需要保存3-5行中产生的标志位。反倒是第二行代码中产生的状态标志,在第6行中可能要用到,用汇编写程序时要注意这些,用C编程时就可以不用担心ZF OF标志了。

出0入0汤圆

 楼主| 发表于 2012-10-25 23:34:28 | 显示全部楼层
"第3-5行的代码功能是独立的,执行完后不需要保存3-5行中产生的标志位。" 楼上这叫话我不太明白,,,
还有
“用汇编写程序时要注意这些,用C编程时就可以不用担心ZF OF标志了。”用c为啥不用担心呢。。。。。
cpu不就是有一个状态寄存器而已嘛???

出0入0汤圆

发表于 2012-10-26 09:57:18 | 显示全部楼层
1、比如ucos中的一段源码:
void  OSStatInit (void)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif



    OSTimeDly(2);                                /* Synchronize with clock tick                        */
    OS_ENTER_CRITICAL();
    OSIdleCtr    = 0L;                           /* Clear idle counter                                 */
    OS_EXIT_CRITICAL();
    OSTimeDly(OS_TICKS_PER_SEC / 10);            /* Determine MAX. idle counter value for 1/10 second  */
    OS_ENTER_CRITICAL();
    OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1/10 second    */
    OSStatRdy    = OS_TRUE;
    OS_EXIT_CRITICAL();
}

OSIdleCtr    = 0L;语句功能对于后面的语句OSTimeDly(OS_TICKS_PER_SEC / 10); 功能是独立的,OSTimeDly(OS_TICKS_PER_SEC / 10);并不会用到由于OSIdleCtr    = 0L;语句的执行导致的状态标志位变化。
2、比如说一段简单的代码:
int i = 1;
        int j = 1;
        if(i == 1)
        {
                j = 2;
        }
        else
        {
                j = 3;
        }
用汇编编写大概是:
0x08000176 2401      MOVS     r4,#0x01
0x08000178 2501      MOVS     r5,#0x01
0x0800017A 2C01      CMP      r4,#0x01
0x0800017C D101      BNE      0x08000182
0x0800017E 2502      MOVS     r5,#0x02
0x08000180 E000      B        0x08000184
0x08000182 2503      MOVS     r5,#0x03

其中
0x0800017A 2C01      CMP      r4,#0x01
0x0800017C D101      BNE      0x08000182
这两条语句用到了状态标志位。那么有没有可能在0x0800017A 2C01      CMP      r4,#0x01语句之前插入一条OS_ENTER_CRITICAL();,而在0x0800017A 2C01      CMP      r4,#0x01语句之后插入OS_EXIT_CRITICAL();语句。用汇编可以做到,虽然这样写是错误的,不合逻辑的。但用c语言写的代码中,没有办法做到,因为0x0800017A 2C01      CMP      r4,#0x01
0x0800017C D101      BNE      0x08000182
这两条语句在c程序中就一条if(i==1)。所以c语言在一定程度上可以避免这种问题的发生。

出0入0汤圆

 楼主| 发表于 2012-10-26 19:44:04 | 显示全部楼层
额,谢谢,明白了许多
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-8-26 15:15

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

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