本帖最后由 杨为民 于 2024-5-27 07:33 编辑
一、前言 本文是华山论剑系列文章的的第5篇。在裸机编程中,如果在后台任务与中断任务(或者一个以上的中断任务)中都调用了同一个函数,那么这个函数必须是可重入的函数,否则会产生不可预料的灾难后果。 同样在RTOS中,如果在一个以上的实时任务(含中断任务)中调用了同一个函数,那么这个函数也必须是可重入的函数。 比如一个实时任务正好运行该函数时发生看任务切换,被切换的新任务也调用了这个函数,如果该函数是不可重入的,那么当任务切换回来后,该函数的现场得不到恢复,则该函数往下执行时就会不正常,甚至该任务或者整个系统都会崩溃。 本文给出了对RTOS不可重入函数的实际测试例子,测试结果表明“CosyOS-II-STC8H”目前的版本是不支持函数重入的,碰到有函数重入时崩溃了。 二、RTOS函数不可重入的实际例子 (1)本文的测试方法是对本论坛RTOS排行榜的方法进行改造而来的。对CosyOS-II-STC8H的测试程序来源于该排行榜,测试结果仅适用于那个测试版本,未必代表CosyOS-II-STC8H最新版本的水平。 (2)本文的测试程序有3个实时任务,优先级最高的任务A是在P04端口产生一个500毫秒宽度的方波作为参考信号,程序见下图: (3)本文测试采用的不可重入的函数如下图: 这是一个3重循环的超长延时函数。其中第28行函数定义没有加任何关键字,对于C51编译器,这个函数肯定是不可重入的。
(4)任务B和任务C都调用了这个超长延迟函数,这两个任务的程序如下: 其中任务B产生一个700毫秒的正脉冲,任务C产生10毫秒宽度的方波。
(5)由于函数是不可重入的,对倚天剑x51和CosyOS-II-STC8H测试结果如下: 从图中可以看出当任务B第一次执行不可重入函数“DelayMS()”后,任务C便崩溃了,程序陷入死循环状态。
(6)程序继续执行下去的结果见下图: 只有任务A和任务B还在正常运行,任务C已经死在那里了。 三、RTOS函数可重入的实际例子
(7)对于C51编译器,将一个不可重入函数变为可重入函数的标准方法是对该函数加“reentrant”的关键字。加关键字的程序见下图 其中第28行函数定义已经加了“reentrant”的关键字。
(8)将“DelayMS()”函数设置为可重入后,倚天剑x51的系统启动信号如下图: 其中任务C可以连续运行下去了。图中任务C中的缺口是高优先级任务B调用“DelayMS()”函数时对剥夺了低优先级任务C的执行权产生的停滞。
程序继续运行下去的信号见下图: (9)当对CosyOS-II-STC8H的“DelayMS()”函数加了“reentrant”的关键字后,系统启动时的信号是这样的: 当任务B第3次执行不可重入函数“DelayMS()”后,任务C便崩溃了,程序陷入死循环状态。同时任务C的方波宽度缩小到13个微秒。
程序继续运行下去的信号见下图: 任务C继续崩溃,死在那里了。
(10)结论:CosyOS-II-STC8H碰到加了“reentrant”的关键字后的函数便会崩溃,这对于“抢占式”的RTOS是一个不能接受的硬伤。
附件501_倚天剑x51_V31_STC8H_函数重入问题.rar
(87.45 KB, 下载次数: 84)
附件502_CosyOS-II-STC8H-TEST_函数重入问题.rar
(408.43 KB, 下载次数: 77)
|