搜索
bottom↓
回复: 22

基于STM32F103 UCOS-II临界区无法关闭中断的问题

[复制链接]

出0入0汤圆

发表于 2017-1-11 19:54:31 | 显示全部楼层 |阅读模式
说一下事情的经过,首先我自己移植了一份基于UCOS操作系统的代码,一直以来用的也挺好,当然使用的也是小项目,什么TCP/IP,USB之类的没有用过,最多的任务量也就用到7—8个,可最近有个项目任务量用了12个,一下子出问题了(不是堆栈溢出),现象是调用了操作系统进入临界区的代码后,然后退出调用代码,再进去观察中断仍然是开着的,最后导致系统逻辑混乱。
大家用UCOS也用得多,所以这里进行简单的修改就可以测试。
首先修改os_cpu.a.asm文件中的OS_CPU_SR_Save,OS_CPU_SR_Restore函数,修改后如下,其实就是添加了红色字体的2条语句,意思就是在执行OS_CPU_SR_Save后监视有没有对primask操作成功,同时在进入OS_CPU_SR_Restore时监控当前的中断是否是处于屏蔽状态。

OS_CPU_SR_Save
MRS     R0, PRIMASK                                       
CPSID   I
        MRS     R1, PRIMASK
    BX      LR

OS_CPU_SR_Restore
    MRS     R1, PRIMASK
    MSR     PRIMASK, R0
BX      LR


在用户的任务里面先进行初始化工作,然后进行临界区的进入和退出函数调用
void Task_1(void *p_arg)
{           
    OS_CPU_SR  cpu_sr = 0u;
        (void)p_arg;
        
        RCC_Config();
        NVIC_Config();
        
        while(1)
        {               
        OS_ENTER_CRITICAL();   //在这里加断点,然后单步调试
        OS_EXIT_CRITICAL();
                OSTimeDly(1000);
        }
}
单步进入OS_ENTER_CRITICAL()

返回后

单步进入OS_EXIT_CRITICAL()

好戏即将上演

可以看到从PRIMASK寄存器里面读出来的值仍然是0,说明中断并没有关闭成功,于是把自己搞蒙了。
大家如何解释这个问题呢?
附件是基于KEIL的工程

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2017-1-11 20:21:23 | 显示全部楼层
没人来看,赶紧顶起来!

出0入0汤圆

 楼主| 发表于 2017-1-12 07:58:54 | 显示全部楼层
来人啦!!!!!!

出0入8汤圆

发表于 2017-1-12 11:01:43 | 显示全部楼层
这个开关中断的逻辑是没有错误的,
你试下直接看看 PRIMASK 寄存器的值。

出0入0汤圆

 楼主| 发表于 2017-1-12 11:29:48 | 显示全部楼层
security 发表于 2017-1-12 11:01
这个开关中断的逻辑是没有错误的,
你试下直接看看 PRIMASK 寄存器的值。

我也想看,但在KEIL里面是直接看不到的,必须通过MRS指令读回到普通寄存器才可以查看

出0入8汤圆

发表于 2017-1-12 11:47:44 | 显示全部楼层
IAR 是可以直接看到这些 core registers
那你就弄一个能中断的 demo
然后试下,在硬件临界区内,中断是否还能响应,确认过了没有?

出0入0汤圆

发表于 2017-1-12 12:46:49 | 显示全部楼层
代码中的将PRIMASK读取到R1的这段代码是你自己临时添加的吧
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()这两个函数先后调用,中间没有任何其他操作,编译器有可能将这段无意义的代码优化掉;

出0入0汤圆

 楼主| 发表于 2017-1-12 13:17:08 | 显示全部楼层
孙为 发表于 2017-1-12 12:46
代码中的将PRIMASK读取到R1的这段代码是你自己临时添加的吧
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()这两 ...

首先编译器并没有将这段代码优化掉,否则在执行OS_EXIT_CRITICAL时,有一句MRS R1, PRIMASK,这条语句在执行器R1是1,执行后是0,所以语句是按照想要的结果进行执行了的

出0入0汤圆

 楼主| 发表于 2017-1-12 13:21:53 | 显示全部楼层
security 发表于 2017-1-12 11:47
IAR 是可以直接看到这些 core registers
那你就弄一个能中断的 demo
然后试下,在硬件临界区内, ...

确认过操作系统的定时器中断仍然会得到响应

出0入0汤圆

发表于 2017-1-12 13:35:18 | 显示全部楼层
函数内部用到了R1 ,你首先得把R1压栈啊。

出0入8汤圆

发表于 2017-1-12 13:43:58 | 显示全部楼层
haoyurenzhu 发表于 2017-1-12 13:35
函数内部用到了R1 ,你首先得把R1压栈啊。

R1 不需要压栈。

出0入8汤圆

发表于 2017-1-12 13:55:48 | 显示全部楼层
amxx 发表于 2017-1-12 13:21
确认过操作系统的定时器中断仍然会得到响应


换颗 MCU 吧,换块板。
你这个硬件出问题的可能性较大。

出0入8汤圆

发表于 2017-1-12 13:58:04 | 显示全部楼层
你也可以将工程,换成仿真模式,再调试看看运行的结果。

出0入0汤圆

发表于 2017-1-12 14:29:58 | 显示全部楼层

                                          

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2017-1-12 16:34:19 | 显示全部楼层

实际上我展开过,在KEIL下面是看不到的,我的KEIL版本为V4.22.15.0

出0入0汤圆

 楼主| 发表于 2017-1-12 16:52:01 | 显示全部楼层


进一步的实验如何确认OS_ENTER_CRITICAL()后中断仍然是可以进入的
首先在main函数里面只创建一个TASK,在创建的任务里面先进行相关的初始化工作,然后调用OS_ENTER_CRITICAL(),接着WHILE(1),在WHILE(1)里面添加一个断点,在系统时钟中断里面添加断点
int main(void)
{
       STM_Init();
       OSInit();
       OSTaskCreate(Task_1,(void*)0,&Task_1_stk[TASK_1_STK_SIZE-1]
              ,TASK_1_PRIO);
//     OSTaskCreate(Task_2,(void*)0,&Task_2_stk[TASK_2_STK_SIZE-1]
//            ,TASK_2_PRIO);
      
       OSStart();
      
       return0;
}



void Task_1(void *p_arg)
{
static int test = 0;
OS_CPU_SR  cpu_sr = 0u;

       (void)p_arg;
      
       RCC_Config();
       NVIC_Config();

       OS_ENTER_CRITICAL();   //在这里加断点,然后单步调试
       while(1)
       {                              
     test++;
       }
}



TASK1中添加断点,并在stm32f10x_it.c文件的操作系统的时间中断里面添加断点


好戏上演了




大家赶紧来看啊!





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2017-1-12 16:54:03 | 显示全部楼层
security 发表于 2017-1-12 13:55
换颗 MCU 吧,换块板。
你这个硬件出问题的可能性较大。

我换过2个CPU了  STM32F103VCT6

出0入8汤圆

发表于 2017-1-12 17:00:59 | 显示全部楼层
amxx 发表于 2017-1-12 16:54
我换过2个CPU了  STM32F103VCT6

你用仿真模式试验过了吗?
换个高版本的 MDK 吧,你的版本太 low 了啊,我已经 2 年多没用 MDK 了,2 年前用的版本就已经是 5.11 了。
我用高版本的,跑了一下你的 demo,用仿真模式,运行是正常的。

出0入0汤圆

 楼主| 发表于 2017-1-12 17:10:20 | 显示全部楼层
security 发表于 2017-1-12 17:00
你用仿真模式试验过了吗?
换个高版本的 MDK 吧,你的版本太 low 了啊,我已经 2 年多没用 MDK 了,2 年 ...

哦,我试试看

出0入0汤圆

 楼主| 发表于 2017-1-12 17:17:43 | 显示全部楼层
security 发表于 2017-1-12 17:00
你用仿真模式试验过了吗?
换个高版本的 MDK 吧,你的版本太 low 了啊,我已经 2 年多没用 MDK 了,2 年 ...

测试了一下,在仿真模式下目前的KEIL V4版本是可以的,但实际接了硬件不知道为什么不行,晚点我换个高版本的KEIL测试一下

出0入8汤圆

发表于 2017-1-19 09:44:21 | 显示全部楼层
amxx 发表于 2017-1-12 17:17
测试了一下,在仿真模式下目前的KEIL V4版本是可以的,但实际接了硬件不知道为什么不行,晚点我换个高版 ...

楼主同学,
过了好多天了,问题解决了没有?
分享一下?

出0入0汤圆

 楼主| 发表于 2017-2-6 11:53:54 | 显示全部楼层
security 发表于 2017-1-19 09:44
楼主同学,
过了好多天了,问题解决了没有?
分享一下?

说起来惭愧,是KEIL的版本问题导致的,后来换了高版本的KEIL问题,仿真也就没有出现这个问题了

出0入8汤圆

发表于 2017-2-7 08:57:54 | 显示全部楼层
amxx 发表于 2017-2-6 11:53
说起来惭愧,是KEIL的版本问题导致的,后来换了高版本的KEIL问题,仿真也就没有出现这个问题了 ...

解决了就好。
所以说要紧跟时代潮流,尽量用用新的版本,不要一直停留在过老的版本。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-19 06:34

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

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