TA的每日心情 | 奋斗 昨天 13:25 |
---|
签到天数: 292 天 [LV.8]以坛为家I
荣誉版主
- 积分
- 3468
|
本帖最后由 CosyOS 于 2023-12-29 11:45 编辑
STC 原生RTOS PK 移植RTOS
一、移植RTOS可能涉及到的一些问题
1、任务切换
不同内核的MCU,在任务切换时,出入栈的方法可能有所不同,需做相关调整。
2、临界区保护
不同内核的MCU,开关中断的方法可能有所不同,需做相关调整。
3、系统全局变量访问
8051:只有单字节变量访问不会重入;
80251:data、edata直接寻址(1~4字节)不会重入,间接寻址(1~2字节)不会重入;
Arm32:所有(1~4字节)访问不会重入;
如果一个原生仅支持Arm32或更高端内核的RTOS,移植到51或251,所有系统全局变量都要
考虑是否有重入的可能(因为RTOS的作者从来不会考虑这个问题,因为根本不需要)。
4、系统服务函数可重入
很多RTOS中的系统服务函数,是需要可重入的,典型的示例如下(以任务中调用服务为例):
RET_t Function(p1, p2, ..., pn)
{
lv1; lv2; ... lvn; // 定义局部变量
... ...;
进入任务临界区;
临界区保护代码;
退出任务临界区;
... ...;
}
如果这样的RTOS移植到251,还非常好处理,只需要一定大小的edata,并生成全局可重入函数即可解决。
可如果移植到51,将变得非常艰难。
1、仔细检查每个服务函数是否已经是可重入函数(形参和局部变量都是寄存器变量),然而这又取决于多方面因素,还与编译器优化等级有关(keil c51 4级优化以上才支持寄存器变量),是无常的,所以根本无法采用。
2、每个服务函数的声明和定义都加上“reentrant”属性,再增加XBP入出任务栈,虽然可以实现,但性能将会大打折扣,使本来就弱的51更加雪上加霜。
二、CosyOS对相关问题的处理
由于CosyOS是原生支持STC 8051和32位8051的,在设计之初就考虑到了上述问题,并采取了一系列行之有效的措施,不但解决了问题,还可实现高性能。
下面主要介绍一下CosyOS对系统服务可重入的处理(以任务中调用服务为例):
1、本地代码
do{ \
进入任务临界区; \
本地执行服务; \
退出任务临界区; \
}while(false)
由于是本地独立的代码,并非调用函数,所以不存在重入的问题。
2、调用服务函数(无返回值)
do{ \
进入任务临界区; \
调用服务函数(); \
}while(false)
由于是在进入任务临界区之后才调用的服务函数,所以服务函数是不会重入的,也不需要可重入。
服务函数在返回时会自动退出任务临界区。
3、调用服务函数(有返回值)
( \
__enter_critical() ? 调用服务函数() : 返回一个其它值 \
)
采用了三目运算,巧妙的实现了在进入任务临界区之后再调用服务函数并返回值。
__enter_critical()的返回值为真,必然会调用服务函数并返回值;为假时返回一个其它值是在欺骗编译器,这种情况永远不会发生。
这一类服务又可细分为三类:
1、服务函数在退出任务临界区后返回常量或寄存器变量或当前任务节点中的变量,这一类服务函数,在退出任务临界区之前是不会重入的,在退出之后是可重入的。
2、服务函数会中途退出任务临界区并触发任务调度,当再次回到当前位置时,会直接返回任务节点中的变量,这一类服务函数,与上一类相同。
3、服务函数会中途退出任务临界区并触发任务调度,当再次回到当前位置时,会再次访问形参或局部变量,而后返回,这一类服务函数需额外定义为可重入函数。
CosyOS需额外定义为可重入函数的系统服务(已加入了reentrant属性):
1、任务中接收私信,uRecvDM(tc);
2、任务中接收邮件,uRecvMail(mail, mbox, tc);
3、中断中接收邮件,iRecvMail(mail, mbox);
4、中断中接收消息,iRecvMsg(que);
对于用户来说:
1、如果是8051内核、80251内核(keil C251 Version 1.x),如果用户调用了上述的四个服务,需要用户自行在启动文件中配置可重入栈[XBP]。
2、Arm内核、80251内核(keil C251 Version 2或更高版本),用户无需理会。
但有一点需要注意:
对于80251内核(keil C251 Version 2或更高版本),您的自定义函数如需可重入,可使用reentrant属性声明,
但不要勾选编译器的 Generate reentrant functions 选项,原因是CosyOS内核为实现高效大量声明或定义了局部的bit型变量,将与此选项冲突。
可见,CosyOS所用的方法可以说是各种内核通吃,尽可能的摆脱了系统服务对可重入栈的依赖,即使是8051也可轻松实现高性能。
计划在下一版本中把任务中接收私信、任务中接收邮件调整为不使用可重入栈;
针对51,中断中接收邮件、中断中接收消息调整为限制调用(只允许在相同优先级的各个中断中调用),用户的自定义函数也不允许使用可重入栈,使51彻底摆脱可重入栈,全面提速。
|
|