找回密码
 立即注册
查看: 954|回复: 17

STC单片机 uC/OS-II核心技术(1):STC32G单片机RTOS任务切换的“替代法”介绍

[复制链接]

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10904
发表于 2023-9-16 14:56:52 | 显示全部楼层 |阅读模式
本帖最后由 杨为民 于 2024-3-31 10:48 编辑

一、简 介
(1)uC/OS-II分三个重要部分:下层硬件接口、任务调度核心和任务间协调工作。uC/OS-II程序框架设计巧妙,通常只需要改写下层硬件接口就可以将uC/OS-II移植到新的单片机上了,目前将uC/OS-II移植到8051类单片机上有多个版本都只是改写了这个部分。
下层硬件接口中最重要的部分是两个任务切换函数:在中断程序中使用的“中断内任务切换”函数“OSIntCtxSw()”和在非中断程序中使用的“任务内任务切换” 函数“OSCtxSw()”。
(2)最原始的uC/OS-II移植例子是使用80x86的CPU,这两个任务切换函数都是利用80x86指令集里的“软中断指令”实现的。由于8051指令集里面没有“软中断指令”,所以以前移植到8051单片机上的uC/OS-II都采用了“程序实现”的方法,我发表的系列移植帖子也都是介绍这种方法的。
(3)STC32G/F系列单片机采用了80251指令集作为基本指令集,80251指令集里面有一个供构造RTOS这类操作系统的软中断指令“TRAP”,但这个TRAP指令目前在STC32G/F系列单片机上还没有对用户开发,因此笔者在将uC/OS-II移植到STC32G单片机上的时候仍然采用了和移植到STC8H单片机上一样的“程序实现法”。
(4)最近坛友“挑战者”(网名“tzz1983”)在论坛里提供他在STC32G单片机上实现的“C251-UCOSII”移植版,其中他采用了利用定时器4硬件中断代替软中断的方法(以后称这种方法为“替代法”)。这种替代法具有明显的两个优点:程序简明易懂和任务切换速度很快。
本文将介绍挑战者坛友在STC32G单片机移植uC/OS-II的新方法:“替代法”的具体实现程序和实测任务切换速度比较。
二、替代法的实现方法
替代法是在STC32G单片机上用硬中断替代软中断实现任务切换的方法,本节介绍挑战者实现的程序方法。
(5)uC/OS-II核心代码中的两个任务调度函数“OSIntExit()”和“OS_Sched”中分别使用了任务切换函数宏“OSIntCtxSw()”和“OS_TASK_SW()”
Fig_01_中断任务调度.jpg
Fig_02_程序中任务调度.jpg
(6)上面的两个宏定义在“OS_CPU.h”中定义:
Fig_03_宏定义.jpg
这三个宏定义都指向一个宏定义“PendSv_GenerateSWInterrupt()”,这个就是替代法的软中断。它的定义如下:
Fig_04_中断标志.jpg
最终落实为一行C语言语句:“T4IF=1;”

(7)在定时器4的中断标志被设置起来后,当中断允许(EA=1)的时候,就会产生定时器4中断,这个中断的ISR如下:
Fig_05_中断ISR.jpg
其中第95行和第139行是供逻辑分析仪测试的信号。
整个任务的ISR分为6个部分:当前任务的寄存器现场存入系统堆栈,保存系统堆栈指针SP到任务堆栈中,将就绪任务中最高优先级的任务设置为当前任务,将任务堆栈中保存的SP恢复为系统堆栈指针,从系统堆栈中恢复任务现场寄存器,最后使用“RETI”指令将CPU控制权交到新任务手中。
(8)为了测试替代法的任务切换速度,本文范例硬件采用了最简单的“降龙棍”作为STC32G单片机的开发板。测试范例只使用开发板上的LED灯作为实时任务的视觉显示,同时使用P2端口连接一个8通道逻辑分析仪来显示各个任务的时序关系以及测量各种性能指标。

下面是测试范例程序运行的效果视频:

从视频中可以看到开机时的LED闪烁LOGO,可以看到开发板左上部的P0端口LED的交替闪烁(任务A),左下部的P1端口LED的左右闪烁(任务B),右下部的P3端口LED的跑马灯(任务C),以及右上部的P2端口逻辑分析仪的LED闪烁。

下图是6.5秒逻辑分析仪的整体截屏:
Fig_06_整体.jpg
图中第0通道是1KHz的定时器0中断信号(系统任务切换中断),
第1通道是中断任务切换信号,同时也是非中断任务切换信号。
第2通道是任务A信号。
第4通道是任务B信号。
第5通道是任务C信号。
三、替代法的任务切换时间

(9)下图是第1通道的任务切换信号的放大图:
Fig_07_切换.jpg
前面一个是替代法的非中断任务切换信号,经过测量为1.375微秒(33M主频),后面一个是替代法的中断任务切换信号,经过测量为1.125微秒(33M主频)。
(10)微山x51-uCOSII是笔者用传统的“程序法”在STC32G单片机上移植的uC/OS-II系统,同样的测试程序和同样的主频,这两个任务切换时间分别为4.000和3.375微秒。
(11)结论:与传统的8051方法相比,挑战者坛友采用替代法移植的uC/OS-II系统的任务切换速度是程序法的三倍。


下面是采用替代法的STC32G单片机上的uC/OS-II的任务切换速度测试程序:
Demo_0101_C251 - UCOSII.rar (703.36 KB, 下载次数: 23)
下面是采用传统8051程序法的STC32G单片机上的uC/OS-II的任务切换速度测试程序:
Demo_0101_uCx51_uCOSII_STC32G.rar (80.72 KB, 下载次数: 22)

回复 送花

使用道具 举报

该用户从未签到

11

主题

331

回帖

886

积分

荣誉版主

积分
886
发表于 2023-9-16 19:31:01 来自手机 | 显示全部楼层
本帖最后由 熊仔 于 2023-9-16 19:32 编辑

杨老师弄的版本怎么这么慢呢?
以前弄Freertos,上下文切换部分,记得是2us左右。代码直接切换的方案也没4us这么慢啊。
晚点看一下。

点评

这是教学版,给学生讲课用的,不是玩家版,不是产品版,也不是专业版  详情 回复 发表于 2023-9-16 21:03
回复 支持 反对 送花

使用道具 举报

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10904
 楼主| 发表于 2023-9-16 21:03:33 | 显示全部楼层
熊仔 发表于 2023-9-16 19:31
杨老师弄的版本怎么这么慢呢?
以前弄Freertos,上下文切换部分,记得是2us左右。代码直接切换的方案也没4us ...

这是教学版,给学生讲课用的,不是玩家版,不是产品版,也不是专业版
回复 支持 反对 送花

使用道具 举报

该用户从未签到

11

主题

331

回帖

886

积分

荣誉版主

积分
886
发表于 2023-9-16 21:46:05 | 显示全部楼层
截图202309162143048091.jpg

截图202309162143482038.jpg

截图202309162145348435.jpg

截图202309162145015884.jpg

原来这几个函数花了不少时间。

点评

你可以继续破解下去,这个部分正是解决你和挑战者正在讨论的 “如果真的考虑这么细,可以这样做。这样肯定没有问题了。中断入口第一条OSIntNesting++。高优先级打断也没有问题。最保险的做法。” 这个主题的最好解决  详情 回复 发表于 2023-9-16 21:53
回复 支持 反对 送花

使用道具 举报

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10904
 楼主| 发表于 2023-9-16 21:53:49 | 显示全部楼层
熊仔 发表于 2023-9-16 21:46
原来这几个函数花了不少时间。

你可以继续破解下去,这个部分正是解决你和挑战者正在讨论的
“如果真的考虑这么细,可以这样做。这样肯定没有问题了。中断入口第一条OSIntNesting++。高优先级打断也没有问题。最保险的做法。”
这个主题的最好解决方法。以后我会做专题介绍的
回复 支持 反对 送花

使用道具 举报

该用户从未签到

11

主题

331

回帖

886

积分

荣誉版主

积分
886
发表于 2023-9-16 22:13:36 | 显示全部楼层
本帖最后由 熊仔 于 2023-9-16 22:15 编辑

这个版本太慢了,没必要破解这个,只是看看为啥这么慢。
因为FreeRTOS我经验,测试过2us左右能完成的。触发中断方式不可能快3倍这么多。也就快了不需要对中断压栈的进出处理。

点评

你不心急就等一下,这是uC/OS-II移植的教学版,以后会公开讲解的。我目前准备先回应一下挑战者坛友的关于他那个临界区保护的测试过不过的问题,免的他认为我们是在吊他胃口  详情 回复 发表于 2023-9-16 22:19
回复 支持 反对 送花

使用道具 举报

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10904
 楼主| 发表于 2023-9-16 22:19:21 | 显示全部楼层
熊仔 发表于 2023-9-16 22:13
这个版本太慢了,没必要破解这个,只是看看为啥这么慢。

你不心急就等一下,这是uC/OS-II移植的教学版,以后会公开讲解的。我目前准备先回应一下挑战者坛友的关于他那个临界区保护的测试过不过的问题,免的他认为我们是在吊他胃口
回复 支持 反对 送花

使用道具 举报

该用户从未签到

20

主题

575

回帖

1191

积分

荣誉版主

积分
1191
发表于 2023-9-17 09:11:21 | 显示全部楼层
本帖最后由 tzz1983 于 2023-9-17 09:16 编辑
熊仔 发表于 2023-9-16 21:46
原来这几个函数花了不少时间。

严格来说,"中断入口第一条OSIntNesting++", 也不一定能解决问题.  

理由: 从硬件机制的角度来讲, 向量入口第一条转移指令, 也是属于中断代码的一部分, 极限来说, 他也是"可能"没有机会执行的. (需要问硬件工程师才能知道)
个人考虑, 这种情况不会有, 因为硬件机制按时钟步骤一步一步的来走, 上一个时钟查询到当前中断(并且没有更高优先级中断)才会走到当前中断向量口, 从硬件原理来说, 为了更高效率, 此时应该已经在运行下一条指令(考虑到流水,至少是准备执行了). 即已执行,就不会发生一条指令也执行不了的结果.
以上分析基于单时钟周期转移到向量入口, 可是呢, 硬件在做"PC地址转移到向量地址和入栈"这部分工作时, 可能需要多个时钟,  别的高优先级中断仍有机会,  从严谨的态度上来说,  需要硬件工程师最后一锤子定音.  (当然了, 不管它也没事, 反正这样用了这么多年了)


以上发言纯属个人臆想, 因为产品手册上也没说这么细. 当是玩笑吧, 一笑而过.


但是Cortex_M3内核的说明书上是有相关的内容的, 迟来的高优先级中断, 可以百度搜"晚到中断机制",

点评

8051硬件中断的软件程序执行过程 8051单片机在硬件中断前后如何执行相关的程序对于设计一个高可靠性的RTOS至关重要,下面就给出分析。(1)术语。在下面的程序中:[attachimg]21522[/attachimg] 其中第100行的地址“  详情 回复 发表于 2023-9-17 11:42
回复 支持 反对 送花

使用道具 举报

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10904
 楼主| 发表于 2023-9-17 11:42:49 | 显示全部楼层
tzz1983 发表于 2023-9-17 09:11
严格来说,"中断入口第一条OSIntNesting++", 也不一定能解决问题.  

理由: 从硬件机制的角度来讲, 向量入 ...

8051硬件中断的软件程序执行过程
8051单片机在硬件中断前后如何执行相关的程序对于设计一个高可靠性的RTOS至关重要,下面就给出分析。
(1)术语。在下面的程序中:
FIG_51中断_00.jpg
其中第100行的地址“009BH”称中断矢量地址。由于两个相邻的中断矢量地址只差8个字节,所以通常放一条远跳转指令到该中断的ISR。这里第97行和第101行是硬件中断开始执行的“第一条指令”。
其中第92行是中断返回指令,该指令会跳转到位于堆栈顶部的16位地址,该地址开始的指令成为退出中断后开始执行的“第一条指令”。

(2)以下资料来自:
FIG_51中断_01.jpg
这书是我国最早的8051单片机权威手册。
FIG_51中断_02.jpg
该书的作者是姚总的导师,我是1991年开始自学8051单片机的。

(3)关于硬件中断的发生条件:
FIG_51中断_03.jpg
FIG_51中断_04.jpg
根据这段话的第二条,结论是:中断矢量的第一条指令在硬件中断开始的时候肯定执行,不会被其他中断打断。

(4)关于中断返回指令的执行:
FIG_51中断_05.jpg
FIG_51中断_06.jpg
这段话的结论是中断后开始执行的“第一条指令”肯定不会被打断,肯定会被执行。



回复 支持 反对 送花

使用道具 举报

该用户从未签到

20

主题

575

回帖

1191

积分

荣誉版主

积分
1191
发表于 2023-9-17 12:37:44 | 显示全部楼层
本帖最后由 tzz1983 于 2023-9-17 12:49 编辑
杨为民 发表于 2023-9-17 11:42
8051硬件中断的软件程序执行过程 8051单片机在硬件中断前后如何执行相关的程序对于设计一个高可靠性的RTO ...

杨老师辛苦了,感谢老师解决了迷团. 正应了你那句话, 我在这反驳你正是为了解开自己的迷惑, 哈哈. 让我自己去找这么古老的东西还真有些犯愁.

这里面有个很更要的概念是, 中断采样和执行相差一个机器周期, 如果在执行硬件生成的"LCALL"采样到新的中断,会在执行完下一条指令后才发生下一个中断. 所以向量口的指令一定可以完成, 迷解开了,谢谢

不过昨天我测试了一段程序,代码大至如下:

EA=1;// 或IE|=0X80;  //
_asm { MOV A IE }

_asm { MOV A IE }
_asm { MOV A IE }
_asm { MOV A IE }
_asm { MOV A IE }
_asm { MOV A IE }

论坛内现打的代码, 书写得对不对也不知道, 反正大至就是这么个意思, 第一条语句打开中断, 之后都是对IE读的操作, 然后我用STC32G仿真, 结果发再执行到第三条语句时, 转到中断了
其实我也不是很在意这个细节, 因为对我的实际代码没什么影响.
也正是因为这个原因, 我不再绝对相信访问IE能"至少执行完下一条指令再产生中断", 所以在我论坛的贴上, 我最后采用了熊仔的JBC指令单指令读并清除EA标志的方法, 其实如果访问IE能阻止中断, 是可以做到更快的. 因为转移需要三个时钟.
有时候觉得理论和实际还是有些差距. 或许像熊仔说的那样, 仿真也或许有少许偏差, 又或许是STC发展了这么多年, 硬件升级变化也未可知.
不管怎么, 我自己是不会在这个问题上纠缠了. 你们如果知道答案, 可以为我解或.  如果不知道答案, 那你们也不用再去查了, 这种细节有时候能磨死人, 不确定我们就绕开它










点评

“然后我用STC32G仿真”。我猜测问题出在仿真上,但是除了相信那本书,我也想不出测试的方法来  详情 回复 发表于 2023-9-17 13:33
回复 支持 反对 送花

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-17 23:37 , Processed in 0.075776 second(s), 68 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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