#operating-system #rtos #kernel #static #experimental #real-time #compile-time

nightly no-std r3

R3-OS: 深度嵌入式系统的实验性静态组件化实时操作系统

9个版本

0.2.4 2022年11月16日
0.2.3 2022年8月16日
0.2.2 2022年3月30日
0.1.3 2021年10月29日
0.1.0 2020年11月2日

#194 in 嵌入式开发


2 crates 中使用

MIT/Apache

525KB
8K SLoC

R3 Real-Time Operating System

深度嵌入式系统的实验性静态组件化实时操作系统

在Repl.it上试用

R3-OS(或简称R3)是一个实验性的静态实时操作系统,它利用Rust的编译时函数评估机制进行静态配置(创建内核对象和内存分配),并使用const traits将内核接口与实现解耦。

  • 所有内核对象都是静态定义的,以实现更快的启动时间、编译时检查、可预测的执行、减少RAM消耗、无运行时分配失败和额外的安全性。
  • 内核及其配置器不需要外部构建工具或专门的宏,保持了透明性和crate之间的可组合性。
  • 内核API不依赖于任何特定的内核实现。内核作为独立的crate提供,应用程序可以选择其中一个并使用特性系统实例化。
  • 利用Rust的类型安全进行内核对象的访问控制。安全代码无法访问它不拥有的对象。

R3 API

  • 任务是生成应用程序线程的标准方式。它们是封装相关线程执行状态的内核对象,可以由应用程序代码或自动在启动时激活。任务具有动态优先级,可以阻塞以释放处理器给低优先级任务。

  • R3提供统一的接口来控制中断线并注册中断处理程序。某些内核(例如,原始内核的Arm M-Profile端口)支持未管理的中断线,在内核处理系统调用时不会被屏蔽,因此提供更优越的实时性能。

  • R3支持常见的同步原语,如互斥锁信号量事件组。互斥锁可以使用优先级天花板协议来避免无界优先级反转和互斥死锁。任务可以自行挂起

  • 内核计时机制驱动微秒级的软件计时器和系统全局时钟。系统时钟可以回滚或快进以补偿漂移。

  • 绑定 是一种静态定义的存储,具有运行时初始化和配置时借用检查。它们可以绑定到任务和其他对象,以提供安全的可变访问。

  • 进程内核配置便于 组件化。实用库包括安全容器类型,如 MutexRecursiveMutex,它们基于低级同步原语构建。

内核

R3 原始内核作为一个独立的包提供,r3_kernel

  • 传统的单核无时钟实时内核,具有抢占式调度

  • 实现了一个基于软件的调度器,支持可定制的任务优先级数量(在32位目标上最多2¹⁵级,尽管实现高度优化以支持较少的优先级)和无限数量的任务。

  • 提供了一种具有对数时间复杂度的可伸缩内核定时机制。此实现对大中断处理延迟具有鲁棒性。

  • 支持 Arm M-Profile(迄今为止所有版本)、Armv7-A(无FPU)、RISC-V 以及在主机系统上运行的 模拟器端口

示例

#![feature(const_refs_to_cell)]
#![feature(const_trait_impl)]
#![feature(naked_functions)]
#![feature(const_mut_refs)]
#![feature(asm_const)]
#![no_std]
#![no_main]

// ----------------------------------------------------------------

// Instantiate the Armv7-M port
use r3_port_arm_m as port;

type System = r3_kernel::System<SystemTraits>;
port::use_port!(unsafe struct SystemTraits);
port::use_rt!(unsafe SystemTraits);
port::use_systick_tickful!(unsafe impl PortTimer for SystemTraits);

impl port::ThreadingOptions for SystemTraits {}

impl port::SysTickOptions for SystemTraits {
    // STMF401 default clock configuration
    // SysTick = AHB/8, AHB = HSI (internal 16-MHz RC oscillator)
    const FREQUENCY: u64 = 2_000_000;
}

// ----------------------------------------------------------------

use r3::{bind::bind, kernel::StaticTask, prelude::*};

struct Objects {
    task: StaticTask<System>,
}

// Instantiate the kernel, allocate object IDs
const COTTAGE: Objects = r3_kernel::build!(SystemTraits, configure_app => Objects);

/// Root configuration
const fn configure_app(b: &mut r3_kernel::Cfg<SystemTraits>) -> Objects {
    System::configure_systick(b);

    // Runtime-initialized static storage
    let count = bind((), || 1u32).finish(b);

    Objects {
        // Create a task, giving the ownership of `count`
        task: StaticTask::define()
            .start_with_bind((count.borrow_mut(),), task_body)
            .priority(2)
            .active(true)
            .finish(b),
    }
}

fn task_body(count: &mut u32) {
    // ...
}

探索 examples 目录中的示例项目。

先决条件

您需要一个 Nightly Rust 编译器。该项目高度依赖于不稳定的功能,因此可能与较新版本的编译器版本兼容或不兼容。查看文件 rust-toolchain.toml 以确定该项目当前测试的编译器版本。

您还需要为目标架构安装 Rust 的交叉编译支持。如果没有安装,您将看到类似于以下错误的编译错误

error[E0463]: can't find crate for `core`
  |
  = note: the `thumbv7m-none-eabi` target may not be installed

在这种情况下,您需要运行 rustup target add thumbv7m-none-eabi

依赖关系

~2.3–4MB
~79K SLoC