找回密码
 立即注册
查看: 1100|回复: 36

STC单片机 uC/OS-II核心技术(4):关闭总中断的临界区保护方法测试

[复制链接]

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10906
发表于 2023-9-19 16:19:37 | 显示全部楼层 |阅读模式
本帖最后由 杨为民 于 2024-3-31 10:50 编辑

关闭总中断是单片机RTOS进行临界区保护的常用方法,本介绍一个对这种方法的嵌套性进行的程序和对两款在STC32G单片机上使用替代软中断进行任务调度的uC/OS-II移植版进行测试的结果。
本文测试的硬件平台是使用STC32G单片机的“降龙棍”开发板,并在P2端口连接了一个8通道逻辑分析仪。
一、非中断任务调度测试程序
(1)在uC/OS-II中有两个基本的任务调度函数,一个是“OSIntExit()”,这个函数在中断ISR中使用,完成中断任务调度和退出中断。另一个是“OS_Sched()”,这函数是在非中断过程的程序中使用,完成任务调度功能。通常的任务管理函数像“OSTaskResume()”和“OSTaskSuspend()”都是调用它来实现任务调度的功能。
(2)本文非中断任务调度测试程序包括3个实时任务,优先级最高的任务A的程序如下:
Fig_01_TaskA.jpg
其中第71行到79行是任务的起始信号,当任务第一次获得控制权时被执行一次。
第83行到第97行是任务A主体,视觉效果是连接在P1端口的LED灯左右闪动。程序执行到第97行时就交出CPU控制权将自己挂起,等到下次被激活后才会从第99行开始继续执行。

(3)优先级次高的任务B的程序如下:
Fig_02_TaskB.jpg
任务B的程序结构与任务A类似,只是视觉效果是连接在P32到P37的六个LED做跑马灯闪烁。

(4)优先级最低的任务C是主控任务,它的程序如下:
Fig_03_TaskC_1.jpg
任务C的每个主循环进行一轮测试。由于有些单片机RTOS的BUG必须经过多次循环后才会显现出来,因此本测试程序是不断地循环进行测试的。
上面第148行到154行是每轮测试的起始信号,它是在连接在P2端口的逻辑分析仪上的所有通道产生一个正脉冲。

第156行到165行程序是第一个测试区间,它在P0端口的奇数位产生一个正脉冲,偶数位产生一个负脉冲。
Fig_04_TaskC_2.jpg
上面第167行到第182行是第2个测试区间,视觉效果是P0端口的LED灯分左右两边交替闪烁。
第185行是测试区间3,用“OSTaskResume(2);”激活任务A(优先级为2)。由于任务A的优先级比任务C(优先级为4),所以所以CPU控制权将转给任务A去执行,直到任务A挂起自己,CPU控制权又回到任务C这里,从第188行开始执行。
第187行到198行是测试区间4,视觉效果是在P0端口上产生一轮跑马灯。

第201行是测试区间5,与第185行的测试区间3一样,只是这次激活的任务B(优先级为3)。
Fig_05_TaskC_3.jpg
第204行到第206行是测试区间6,是在逻辑分析仪的第2通道显示一个高电平。
第208行到第210行是测试区间7,是在逻辑分析仪的第2通道显示一个低电平。
第212行到第228行是测试区间8,视觉效果是P0端口的LED灯交替闪烁。

下面是这个测试1程序运行的视频效果:

(5)整个测试程序启动时的时序如下图所示:
Fig_06_开机.jpg
其中左边全部通道的3个负脉冲是RTOS的启动LOGO,然后是第4通道优先级最高的任务A开始启动,可以看到第一次运行的起始信号,再然后是第5通道优先级次高的任务B开始启动,可以看到第一次运行的起始信号,再后是任务C开始启动,不断地循环进行测试,每循环一次都可以看明显的开始测试信号。

(6)对于每一轮测试的信号次序如下图:
Fig_07_测试.jpg
其中通道2是任务C的进程信号,从测试起始信号到区间1至区间8。这个时间次序很重要,代表了任务C的程序逐行执行顺序。
(7)本次测试对象是“C251-UCOSII”移植版和“uCOSII-STC32G-V1.00”移植版。这两个STC32G单片机上移植版都是采用硬中断模拟软中断的“替代法”来进行任务切换的。

对于使用替代法的RTOS,除了常见的关闭总中断的临界区保护方法外,还有一种方法0,见下图:
Fig_08_方法0.jpg
如果用户定义临界区保护方法为第47行的方法0,那么由于第51行和第52行是空定义,相当于取消了临界区保护。
(8)测试1结果。对于上面两个移植版,临界区保护分别用方法0和方法3进行了测试,测试结果完全正常,效果如上面视频和截图显示的那样。
(9)测试1结论。由于测试1的测试程序用户没有用到临界区保护,所以可以得到结论:对于在STC32G单片机上使用替代法的uC/OS-II系统本身,可以不需要进行任何关闭总中断的临界区保护。
二、关闭总中断的临界区保护方法测试

(10)第二个测试是在用户程序中加入临界区保护,用来检测关闭总中断的临界区保护方法对用户程序的保护作用。第二个测试程序是在第一个测试程序的任务C里加上双层的临界区保护语句,见下图:
Fig_09_方法3_程序A.jpg
其中第169行和第191行进入临界区保护,
Fig_09_方法3_程序B.jpg
然后第210行和第216行退出临界区保护。
(11)方法0的测试结果。采用方法0,上面用户测试程序中每个进入和退出临界区保护的语句就是只有一个分号的“空语句”,所以对两个移植版测试的结果与上面没有临界区保护的结果一模一样。

(12)方法3的测试结果。采用方法3,对两个移植版的测试结果均为系统崩溃,见下图:
Fig_10_方法3_崩溃.jpg
从图中可以看到第一轮进入关闭总中断临界区保护后,第0通道的系统定时器中断停止了(这很正常),第4、5通道的任务A和任务B没有激活(这很正常)。但是,退出临界区保护后,第0通道代表的定时器中断再没有恢复,而同时任务C还在不断地执行。
如果系统中断停止工作,程序陷入死循环,代表RTOS系统已经崩溃不能恢复正常了。
(13)测试2结论:如果对用户程序进行临界区保护,会带来系统崩溃。
(14)综合结论:采用方法0不关闭总中断,不进行任何临界区保护,对系统本身和用户程序没有任何影响,都可以正常运行。采用方法3,采用关闭总中断对用户程序进行临界区保护,系统会崩溃。

(15)存在BUG:在采用软中断的uC/OS-II移植版中,向用户提供关闭总中断的临界区方法就是BUG。

下面是测试程序
测试1_C251-UCOSII.rar (714.57 KB, 下载次数: 27)

测试1_uCOSII-STC32G-V1.00.rar (695.79 KB, 下载次数: 35)

测试2_C251-UCOSII.rar (714.94 KB, 下载次数: 30)

测试2_uCOSII-STC32G-V1.00.rar (696.3 KB, 下载次数: 35)


回复 送花

使用道具 举报

该用户从未签到

20

主题

575

回帖

1191

积分

荣誉版主

积分
1191
发表于 2023-9-19 16:28:13 | 显示全部楼层
有图有真相, 值得学习
回复 支持 反对 送花

使用道具 举报

该用户从未签到

11

主题

331

回帖

886

积分

荣誉版主

积分
886
发表于 2023-9-19 16:57:24 | 显示全部楼层
后面的测试方法本来就是之前讨论的。又来一次?
采用中断方式切换任务的,关闭了中断,怎么切换任务?

除非这个时候激活定时器0的模式3,模式三不能被关闭EA屏蔽的,可以用来切换任务。
在临界区嵌套的时候,激活不可屏蔽定时器0中断这个方案是可行的。
问题是有必要吗?

点评

激活定时器模式3不行,一旦激活不能改的。  详情 回复 发表于 2023-9-19 20:28
“问题是有必要吗?” 你就声明你的移植版通不过这个测试程序,请用户慎入,然后把这个测试程序附在你的移植版后面做危险警示就好了呀? 这不丢人呀,就像电动车声明不下水,汽车声明泡水里请勿点火一样,何必去与  详情 回复 发表于 2023-9-19 17:16
回复 支持 反对 送花

使用道具 举报

该用户从未签到

11

主题

331

回帖

886

积分

荣誉版主

积分
886
发表于 2023-9-19 17:15:04 | 显示全部楼层
要不就是OS_TASK_SW(),OSCtxSw() 改用代码切换方式呗。这个又需要对ERET和RETI对齐操作问题。

点评

又拿嘴说,你做出来看看呀?要么上修改的移植版程序,要么上酸菜!  详情 回复 发表于 2023-9-19 17:18
回复 支持 反对 送花

使用道具 举报

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10906
 楼主| 发表于 2023-9-19 17:16:57 | 显示全部楼层
熊仔 发表于 2023-9-19 16:57
后面的测试方法本来就是之前讨论的。又来一次?
采用中断方式切换任务的,关闭了中断,怎么切换任务?

问题是有必要吗?

你就声明你的移植版通不过这个测试程序,请用户慎入,然后把这个测试程序附在你的移植版后面做危险警示就好了呀?
这不丢人呀,就像电动车声明不下水,汽车声明泡水里请勿点火一样,何必去与人争论有没有必要下水,有没有必要点火一样。
不过也有特殊车辆针对这种缺点去改进的。
所以不需要争论有没有必要,你没有必要,全世界60亿人都没有这个必要吗?


回复 支持 反对 送花

使用道具 举报

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10906
 楼主| 发表于 2023-9-19 17:18:33 | 显示全部楼层
熊仔 发表于 2023-9-19 17:15
要不就是OS_TASK_SW(),OSCtxSw() 改用代码切换方式呗。这个又需要对ERET和RETI对齐操作问题。 ...

又拿嘴说,你做出来看看呀?要么上修改的移植版程序,要么上酸菜!
回复 支持 反对 送花

使用道具 举报

  • TA的每日心情
    奋斗
    昨天 11:08
  • 签到天数: 173 天

    [LV.7]常住居民III

    5

    主题

    579

    回帖

    2347

    积分

    荣誉版主

    积分
    2347
    发表于 2023-9-19 17:59:51 | 显示全部楼层
    本帖最后由 CosyOS 于 2023-9-19 18:09 编辑

    我只能说CosyOS也一定不能通过这种测试。
    关闭总中断后,不能再进入SysTick和PendSV,无法
    切换任务,程序只能在原地顺序执行。
    而且CosyOS当调用恢复任务等服务时,程序还有机会进入死循环(因为它在等待进入PendSV切换任务,不过这个问题是可以解决的)。
    但是对于延时、超时等阻塞类型的服务,是绝对无法解决的,它必须要等待进入PendSV切换任务后才能继续。
    所以,很多服务是不允许在临界区中调用的。
    所以,CosyOS做了一个规定,不允许用户在临界区中(包括任务临界区和全局临界区)调用服务,仅能执行用户自己的代码。

    据我了解,FreeRTOS也有这个规定,其它RTOS不了解。




    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    11

    主题

    331

    回帖

    886

    积分

    荣誉版主

    积分
    886
    发表于 2023-9-19 18:34:38 | 显示全部楼层
    (13)测试2结论:如果对用户程序进行临界区保护,会带来系统崩溃。



    这个结论应该改成临界区保护处于嵌套的时候,调用系统服务函数,会带来系统崩溃。
    因为不在嵌套区是没有问题。

    点评

    你说“结论:目前移植的ucos到STC32上,没惊天大BUG之二。” (1)你的移植版不接受方法0,是不是你说的? (2)你的移植版使用方法3,没有通过这个测试,是不是事实? (3)一个程序在测试时崩溃了,我的语境叫做“  详情 回复 发表于 2023-9-20 12:55
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    11

    主题

    331

    回帖

    886

    积分

    荣誉版主

    积分
    886
    发表于 2023-9-19 20:28:02 | 显示全部楼层
    熊仔 发表于 2023-9-19 16:57
    后面的测试方法本来就是之前讨论的。又来一次?
    采用中断方式切换任务的,关闭了中断,怎么切换任务?

    激活定时器模式3不行,一旦激活不能改的。
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 11:08
  • 签到天数: 173 天

    [LV.7]常住居民III

    5

    主题

    579

    回帖

    2347

    积分

    荣誉版主

    积分
    2347
    发表于 2023-9-19 20:43:53 | 显示全部楼层
    本帖最后由 CosyOS 于 2023-9-20 00:13 编辑

    刚才我的描述有bug,再重新整理一下。。。

    CosyOS的现状描述:
    1:在任务中并已进入临界区(包括任务临界区和全局临界区),不允许调用“
    阻塞服务”,因为当前任务有时要进入阻塞状态并等待进入PendSV切换任务。
         CosyOS的“
    阻塞服务”包括阻塞延时、二值信号量等待、二值信号量获取、互斥信号量获取、计数信号量获取、等待标志组、接收私信、接收飞信、接收邮件、接收消息,共十个服务。
    2:在任务中并已进入任务临界区(嵌套),不允许调用“非阻塞服务”,因为“非阻塞服务”也是要进入任务临界区执行的,而且当前是非嵌套的代码,将与用户调用的任务临界区API相冲突(不过这个问题是可以解决)。

    结论:
    在临界区中,CosyOS允许在以下情况调用部分系统服务:
    1:在任务中并已进入任务临界区(非嵌套),可调用“非
    阻塞服务”。
    2:在任务中并已进入全局临界区,可调用“非
    阻塞服务”。
    3:在中断中并已进入全局临界区,可调用所有中断服务。


    未来调整的话,可调整第一条:在任务中并已进入任务临界区(不管嵌不嵌套),都可调用“非
    阻塞服务”。
    如果这样调整的话,约束就只有一条:在任务中并已进入临界区(包括任务临界区和全局临界区),不允许调用“
    阻塞服务”。







    点评

    (1)一直关注你的方法,如果你继续沿着:提供临界区阻塞检测,提供阻塞区队列,然后在总中断恢复后对阻塞队列再进行处理这条正确的道路上走下去,那么只要你的这些队列处理不是通过中断完成的,那么你的采用替代法  详情 回复 发表于 2023-9-20 13:12
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-18 03:20 , Processed in 0.082772 second(s), 74 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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