FreeRTOS-rust 编译分析
目录介绍
FreeRTOS-rust
├── .cargo # 对 cargo 本身的配置
│ └── config.toml
├── Cargo.toml # 对当前工作空间的配置
├── freertos-cargo-build # 负责对 freertos 源码进行编译
│ ├── Cargo.toml # 对当前 package 进行配置
│ └── src
│ └── lib.rs
├── freertos-rust # 负责编译 freertos 的 rust 接口层
│ ├── Cargo.toml # 对当前 package 进行配置
│ ├── build.rs # package 编译前自动调用的脚本
│ └── src # 适配层源码
│ ├── allocator.rs
│ ├── base.rs
│ ├── critical.rs
│ ├── delays.rs
│ ├── event_group.rs
│ ├── freertos # freertos C 接口适配层和实现的钩子函数
│ │ ├── ports
│ │ │ └── arm
│ │ │ └── hooks.c
│ │ └── shim.c
│ ├── hooks.rs
│ ├── isr.rs
│ ├── lib.rs
│ ├── mutex.rs
│ ├── patterns
│ │ ├── compute_task.rs
│ │ ├── mod.rs
│ │ ├── processor.rs
│ │ └── pub_sub.rs
│ ├── portmacro.h
│ ├── prelude
│ │ ├── mod.rs
│ │ └── no_std.rs
│ ├── queue.rs
│ ├── semaphore.rs
│ ├── shim.rs
│ ├── task.rs
│ ├── timers.rs
│ ├── units.rs
│ └── utils.rs
├── freertos-rust-examples # freertos 应用示例
│ ├── Cargo.toml # 对当前 package 进行配置
│ ├── FreeRTOS-Kernel # freertos 内核C源码
| ├── freertos-addons # freertos 扩展库C++源码(无需关注)
│ ├── build.rs # package 编译前自动调用的脚本
│ └── examples # 各平台的rust freertos 应用开发示例
│ ├── linux
│ ├── nrf9160
│ ├── stm32-cortex-m3
│ ├── stm32-cortex-m4-blackpill
│ └── win
└── publish-all.sh
框架介绍
FreeRTOS-rust 的整体框架分为三大块 freertos-cargo-build、freertos-rust、freertos-rust-examples。
freertos-cargo-build 负责对项目中所有 C语言代码的编译,包括 FreeRTOS-Kernel 内核源码,freertos C 适配层接口以及 freertos 各种钩子函数实现,内部利用cc crate以及build.rs文件中提供的信息,将C语言代码打包为静态库。
freertos-rust 中包括了 freertos 的C适配层接口和钩子函数实现,以及转换为 rust 语言的对外接口,应用开发使用的 rust freertos 接口均来自这里。
freertos-rust-examples 中包括了 freertos 的C语言内核源码以及各平台的 rust 应用示例。
编译体系
FreeRTOS-rust 项目中 C语言部分和各 rust package 的编译都是通过 cargo 工具完成,主要参与的文件有 cargo 配置文件(config.toml),项目 workspace 和各个 package 配置文件(Cargo.toml),以及编译依赖脚本(build.rs 和 lib.rs)。
cargo 配置文件
目录:./FreeRTOS-rust/.cargo/config.toml
config.toml 中的配置是对 cargo 工具本身的配置,只会对当前项目生效,可以对项目配置一些默认的行为,例如此处设置了目标架构为 arm,目标 os 为 none,那么就可以在项目中使用 CARGO_CFG_TARGET_ARCH 和 CARGO_CFG_TARGET_OS 环境变量来进行条件判断。
# 配置 CARGO_CFG_TARGET_ARCH 宏为arm, CARGO_CFG_TARGET_OS 宏为none
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# 配置传递给 rust 编译器传递额外的编译参数
rustflags = [
# LLD (shipped with the Rust toolchain) is used as the default linker
"-C", "link-arg=-Tlink.x",
# if you run into problems with LLD switch to the GNU linker by commenting out
# this line
# "-C", "linker=arm-none-eabi-ld",
# if you need to link to pre-compiled C libraries provided by a C toolchain
# use GCC as the linker by commenting out both lines above and then
# uncommenting the three lines below
# "-C", "linker=arm-none-eabi-gcc",
# "-C", "link-arg=-Wl,-Tlink.x",
# "-C", "link-arg=-nostartfiles",
]
# 配置默认工具链版本
[rustup]
toolchain = "nightly"
# 设置编译的目标平台,也可以通过 cargo build --target <name> 传递,设置到 TARGET 环境变量
[build]
# Pick a target or use --target <name>
# target = "x86_64-pc-windows-gnu" # Windows GNU Toolchain
# target = "x86_64-pc-windows-msvc" # Windows MSVC Toolchain (no debugging)
# target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabihf" # Cortex-M4
workspace 配置文件
目录:./FreeRTOS-rust/ Cargo.toml
一个工作空间是由多个 package 组成的集合,共享同一个 Cargo.lock 文件、输出目录 target 和一些设置(例如 profiles : 编译器设置和优化)。工作空间由项目最外层的带有 [workspace] 项的 Cargo.toml 文件标识。
此处设置了工作空间成员的名称,每个成员下面必须要有自己的 Cargo.toml,并设置了整个工作空间在release 编译模式下的优化情况。
# 虚拟清单工作空间
[workspace]
# 工作空间成员
members = [
"freertos-rust",
"freertos-cargo-build",
"freertos-rust-examples"
]
# 设置工作空间release时的优化情况
[profile.release]
codegen-units = 1 # better optimizations
# debug = true # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations
# opt_level=3
package 配置文件
freertos-cargo-build 配置文件
这里的配置文件主要是设置当前 package 打包成静态库,静态库的默认名称为 freertos-cargo-build.rlib ,以便被其他 rust 代码调用进行 C代码编译。 并且配置C代码编译器依赖包 cc 和 walkdir。
[package]
name = "freertos-cargo-build"
description = """
Utility lib for building & using FreeRTOS in rust projects inside the build.rs.
"""
version = "0.1.1"
authors = ["Tobias Kaupat <tk@lobaro.de>"]
edition = "2018"
license = "MIT"
readme = "README.md"
repository = "https://github.com/lobaro/FreeRTOS-rust"
# 默认需要打包成 freertos-cargo-build.rlib 静态库
[lib]
# 配置package依赖的包
[dependencies]
cc = "1.0.52"
walkdir = "2.3.1"
freertos-cargo-build/src/lib.rs 的作用是收集项目中所有的 C文件和头文件目录,并实现 pub fn compile(&self) -> Result<(), Error> 函数,在函数中调用 cc::Build::new().try_compile(“freertos”) 进行 C语言静态库的生成,这样在其他 rust 文件中就可以调用 compile 来完成C语言文件的编译了。
freertos-rust 配置文件
这个配置文件中设置了 package 编译为库后的名称为 freertos_rust,编译入口文件在 src/lib.rs 中,并在编译入口文件中根据 [features] 的配置决定需要启用哪些模块。这里编译产生的库将会被 rust 应用所使用,以便使用 FreeRTOS 的功能。
[package]
name = "freertos-rust"
version = "0.1.2"
authors = ["Tobias Kaupat <tk@lobaro.de>"]
edition = "2018"
description = """
Create to use FreeRTOS in rust projects.
The freertos-cargo-build crate can be used to build and link FreeRTOS from source inside build.rs.
"""
keywords = ["FreeRTOS", "embedded", "demo", "library"]
license = "MIT"
readme = "README.md"
repository = "https://github.com/lobaro/FreeRTOS-rust"
links = "freertos"
# 设置静态库的名称为 freertos_rust.rlib, 编译入口文件在 src/lib.rs 中
[lib]
name = "freertos_rust"
path = "src/lib.rs"
# 配置启用的特性,也就是配置哪些模块生效
[features]
default = ["allocator", "sync", "time", "hooks", "interrupt", "delete_task"]
allocator = []
sync = ["interrupt"]
time = ["interrupt"]
hooks = []
interrupt = []
cpu_clock = []
delete_task = []
freertos-rust-examples 配置文件
此配置需要先设置编译依赖的源文件路径,所以在工作成员中 freertos-cargo-build 优先被编译,生成C编译器,用于后期 C代码的编译。然后设置一般依赖的源文件路径,所以 FreeRTOS 的 rust 适配层 freertos-rust 也被优先编译,作为静态库被后期的应用代码使用。其次就是设置对应平台的硬件依赖库。
[package]
name = "freertos-rust-examples"
version = "0.1.1"
authors = ["Tobias Kaupat <tk@lobaro.de>"]
edition = "2018"
description = """
Create to use FreeRTOS in rust projects. It contains binaries for demos on some architecutres.
"""
keywords = ["FreeRTOS", "embedded", "demo", "examples"]
repository = "https://github.com/lobaro/FreeRTOS-rust"
# 配置普通依赖的源码路径,所以freertos-rust也需要被优先编译
[dependencies]
freertos-rust = {path = "../freertos-rust"}
# 根据 config.toml 配置设置依赖包
[target.'cfg(target_arch = "arm")'.dependencies]
cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]}
cortex-m-rt = "0.7.3"
# 根据config.toml 配置或 --target <triple> 的配置设置依赖包
# Example: stm32-cortex-m3, [target.<triple>.dependencies] triple form cargo build --target thumbv7m-none-eabi
# or form .cargo/config.toml [build] target = "thumbv7m-none-eabi"
[target.thumbv7m-none-eabi.dependencies]
nb = "0.1.2"
embedded-hal = "0.2.3"
panic-halt = "0.2.0"
stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103"], default-features = false}
# 配置编译依赖的源码路径,所以在工作成员中 freertos-cargo-build 优先被编译
[build-dependencies]
freertos-cargo-build = {path = "../freertos-cargo-build"}
🌀路西法的个人博客拥有更多美文等你来读。