RTX51系统

RTX51 是 KEIL 公司开发的针对 8051 系列单片机的多任务实时操作系统(RTOS)。它提供了多任务处理能力,允许程序以并行方式执行,适用于对时间要求严格的嵌入式应用。RTX51 具有简单的 API 和任务调度机制,使开发者能够更方便地管理任务和资源,确保系统的响应性和稳定性。RTX51 系统提供了任务管理、任务调度、任务通讯、定时器、信号量、邮箱等实时操作系统的基本功能,并与 Keil 公司的 C51 编译器紧密集成,从而方便开发人员进行开发和调试。

RTX51 的多任务处理能力指的是系统能够同时管理和执行多个任务或进程的能力。多个任务看似同时运行,实际上是通过快速切换来实现的。这种切换由操作系统的调度器控制。

多核和多 CPU

  • 单核与多核

    • 单核:系统只有一个处理核心,所有任务都由这一核心处理。虽然能够完成基本的计算任务,但在同时执行多个任务时效率较低。

    • 多核:系统有多个处理核心(如双核、四核等),每个核心可以独立执行任务。这种架构可以提高并行处理能力,允许多个任务同时进行,从而提升整体性能。

  • 单 CPU 与多 CPU

    • 单 CPU:系统只配备一个中央处理单元(CPU),类似于单核,但可以是一个复杂的多核处理器。

    • 多 CPU:系统配备多个 CPU,每个 CPU 可以独立处理任务,通常用于需要极高性能和处理能力的服务器

    • 或高性能计算机。多 CPU 系统通过并行处理可以显著提高计算能力。

RTX51 包含两个版本:

RTX51 Tiny

  • RTX51 Tiny是一个非常小型的实时操作系统,具有基本的任务调度功能,包括任务优先级和时间片轮转等RTX51 Tiny适用于基于51系列单片机的应用程序,特别是对于小型和简单的应用程序,因为它不需要太多的RAM和ROM资源。
  • 相对于 RTX51 Full 不具备如下功能:
    • 由循环多任务处理和信号实现任务切换
    • 不支持优先任务切换
    • 不包含信息子程序
    • 无存储器库分配子程序

RTX51 Full

  • RTX51 Full则是一个功能更为强大的实时操作系统,它不仅支持基本的任务调度功能,还提供了更多的RTOS特性,例如信号量、邮箱、消息队列、事件标志和互斥量等,使得它更加适合于需要更高级RTOS特性的应用程序。

RTX51 Tiny是一个轻量级的RTOS,适用于简单的应用程序,而RTX51 Full则提供了更多的RTOS特性,适用于更为复杂的应用程序。

STC8H

RTX51 Tiny 环境搭建

  1. 新建一个项目
  2. 打开keil安装目录,来到C51\RtxTiny2\SourceCode目录,拷贝Conf_tny.A51RTX51TNY.LIB到项目中。

RTX51bin

  1. 打开配置,来到Target中,将Operating system修改为RTX-51 Tny

RTX51IDE

  1. 新建好main.c, 代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// main.c
#include "RTX51TNY.H"
#include "STC8H.H"

// P5.3 闪烁
void sys_init() {
P5M1 &= ~0x08; P5M0 &= ~0x08;
}

// 这里函数名可随意, 建议不要使用start, 会和I2C.h里的Start冲突
void main_start() _task_ 0 {
sys_init();
// 创建任务 1
os_create_task(1);
// 结束任务 0
os_delete_task(0);
}

void task_1() _task_ 1 {
while(1) {
P53 = 1;
os_wait1(K_TMO);

P53 = 0;
os_wait1(K_TMO);
}
}
  • 不再有main函数
  • 代码入口为标记为 _task_ 0的函数。
  • _task_标记的函数,表示这个是独立的任务,多个task可以同时执行。

RTX51 注意事项

一、RTX51 对于系统硬件的要求

RTX51renwu

二、RTX51 任务的状态及定义

RTX51 区分 2 类任务: 快速任务标准任务。快速任务有很快的响应速度,每个快速任务使用 8051 一个单独的寄存器组,并且有自己的堆栈区域。RTX51 支持最大同时有 3 个快速任务。标准任务需要多一点的时间来进行任务切换,因此使用的内部 RAM 相对快速任务要少,所有的标准任务共用 1 个寄存器组和堆栈。当任务切换的时候,当前任务的寄存器状态和堆栈内容转移到外部存储器中。

在 RTX51 Full 中,可以通过特定的 API 或函数来创建任务,并在创建时指定任务的类型(快速或标准)。RTX51 Tiny 则不支持快速任务。

RTX51 FULL 支持任务最多达 64 个,但一般 RTX51 TINY 支持最大 16 个标准任务。

三、RTX51 自带延迟与 delay_ms() 延时的区别

在 RTX51 Tiny 中 共有三个等待延时函数分别是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
extern unsigned char os_wait            (unsigned char typ, 
unsigned char ticks,
unsigned int dummy);
extern unsigned char os_wait1 (unsigned char typ);
extern unsigned char os_wait2 (unsigned char typ,
unsigned char ticks);
// 参数如下:
/* constants for os_wait function:也就是等待函数的 typ */
#define K_SIG 0x01 /* 等待一个信号。*/
#define K_TMO 0x02 /* 等待由 ticks 指定的超时时间。*/
#define K_IVL 0x80 /* 等待由 ticks 指定的时间间隔。*/
/*
参数中:K_TMO、K_IVL 看解释十分相似,但其实区别很大:
当使用 K_TMO 时,任务从调用 os_wait 函数的当前时刻开始计时,等待指定的时间(以系统ticks 为单位)后恢复为就绪状态。这个时间段不包括任务在等待之前和之后执行的时间。
当使用 K_IVL 时,任务从上一次执行结束(或上一次调用 os_wait 并返回)的时刻开始计时,等待指定的时间(以系统ticks为单位)后再次执行。这个时间段包括任务自身的执行时间。
*/

os_wait

暂停当前任务,等待一个或多个事件;例如一个时间间隔、超时或来自其他任务或中断的信号。typ 参数指定要等待的事件或事件组合,可以是上述参数中的常量之一:

typ 可以通过竖线(|)字符进行逻辑或操作。例如,K_TMO | K_SIG 表示任务等待超时或信号。

  • **typ**:这是一个指定等待类型的参数。RTX51 中可能定义了多种等待类型,如等待事件、消息、信号量等。具体的类型值取决于 RTX51 的具体实现和文档。
  • **ticks**:这是等待的时间长度,以操作系统的“tick”为单位。一个 tick 的长度取决于 RTX51 的配置,通常与系统的时钟频率有关。
  • **dummy**:这个参数在大多数实现中可能并不真正使用,而是为了保持函数签名的兼容性或预留未来的扩展。在一些版本中,这个参数可能已经被移除或替换为更有用的参数。

os_wait1

暂停当前任务并等待事件发生。os_wait1 函数是 os_wait 函数的一个子集,只支持 K_SIG 这个值,表示等待一个信号。

os_wait2

同 os_wait 基本一致

当 K_SIG 和 K_IVL 组合使用时,必须使用 os_reset_interval 函数来消除定时器延迟问题。

以 os_wait2 为例 与 delay_ms() 区别在:

在 RTOS 中,如果 delay_ms() 被用于多个任务,它可能会导致任务调度的不公平或不可预测性,因为任务在等待期间会阻塞其他任务的执行

如果多个任务都使用 delay_ms() 等待 100ms,那么每个任务都会独立地进入延时状态,并阻塞其他任务的执行(除非RTOS有特别的机制来处理这种情况)。

举个例子:

  1. 假设我有 三个任务分别为 func1、func2、func3,三个任务都设置 delay_ms 分别为 150ms、100ms、50ms,那么当这三个任务执行时,他们真正的等待时间就会变成 150 x 3 = 450ms、300ms、150ms,因为他们

  2. 假设我有 三个任务分别为 func1、func2、func3三个任务,其中 func1 设置 delay_ms,其他都设置 K_TMO 分别为 150ms、100ms、50ms,那么当这三个任务执行时,他们真正的等待时间就会变成 150 x 2 = 300ms、200ms、100ms,因为他们

在 RTX51 Tiny 中,当多个任务处于休眠状态时,它们会共享同一个时间片。这意味着,当系统调度时,如果所有处于休眠状态的任务都没有被唤醒,调度器不会为它们分配不同的时间片。实际上,只有在任务被唤醒并准备好执行时,调度器才会考虑这些任务。

因此,在多个任务休眠的情况下,系统不会为每个休眠任务分配独立的时间片。它们会在系统处于闲置状态时共用资源,直到有任务需要执行或有事件发生以唤醒其中的某个任务。

四、K_TMO 与 K_IVL 的区别

当使用 K_TMO 时,任务从调用 os_wait 函数的当前时刻开始计时,等待指定的时间(以系统ticks 为单位)后恢复为就绪状态。这个时间段不包括任务在等待之前和之后执行的时间。
当使用 K_IVL 时,任务从上一次执行结束(或上一次调用 os_wait 并返回)的时刻开始计时,等待指定的时间(以系统ticks为单位)后再次执行。这个时间段包括任务自身的执行时间。

K_SIG 信号等待

问题

一、报错:WARNING L7: MODULE NAME NOT UNIQUE MODULE: .\Objects\Conf_tny.obj (?RTX51_TINY_KERNAL)

RTX51Bug1

将 Conf_tny.A51 放在 RTX51TNY.LIB 前面即可