[Rust_emb]开始实践

使用cargo-generate创建模版

首先安装cargo-generate

cargo install cargo-generate

生成一个项目

cargo generate --git https://github.com/knurling-rs/app-template
 Project Name: app
 Creating project called `app`...
 Done! New project created /tmp/app
cd app

配置文件

第一步在 .cargo/config.toml 中设置一个默认的编译目标。

# Pick ONE of these compilation targets
# target = "thumbv6m-none-eabi"    # Cortex-M0 and Cortex-M0+
# target = "thumbv7m-none-eabi"    # Cortex-M3
# target = "thumbv7em-none-eabi"   # Cortex-M4 and Cortex-M7 (no FPU)
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)

第二步是将内存区域信息输入到 memory.x 文件中。

/* Linker script for the STM32F303VCT6 */
MEMORY
{
  /* NOTE 1 K = 1 KiBi = 1024 bytes */
  FLASH : ORIGIN = 0x08000000, LENGTH = 256K
  RAM : ORIGIN = 0x20000000, LENGTH = 40K
}

注意:如果你在首次build特定构建目标后,出于某种原因更改了 memory.x 文件,那么在执行 cargo build 之前要先执行 cargo clean ,因为 cargo build 可能无法及时跟踪 memory.x 的更新。

在 bin/hello.rs 中检查内

与原文差异原因
说明
hprintln旧版 cortex-m 的打印宏,新版本已移除
defmt::println新版推荐使用的打印宏(通过 RTT 输出)

你的 Cargo.toml 已经包含 defmt-rtt,所以使用 defmt::println 是正确选择。

#![no_main]
#![no_std]

use app as _; // global logger + panicking-behavior + memory layout
use cortex_m_rt::entry;

#[entry]
fn main() -> ! {
    defmt::println!("Hello, world!");

    loop {}
}

Memory Mapped Registers 内存映射寄存器

内存映射寄存器(MMIO):把硬件设备“抽象成内存”,让 CPU 用普通的读写指令就能控制外设及通过“对特定地址的读写”来进行控制。

            ┌──────────────────────────────┐
            │         应用层 (App)          │
            │  main.rs / 业务逻辑 / RTOS    │
            └────────────▲─────────────────┘
                         │ 调用 API
            ┌────────────┴─────────────────┐
            │        HAL 层 (硬件抽象)      │
            │  stm32f3xx-hal               │
            │  GPIO / UART / SPI / I2C     │
            └────────────▲─────────────────┘
                         │ 调用寄存器
            ┌────────────┴─────────────────┐
            │      PAC 层 (寄存器映射)      │
            │  stm32f3 (svd2rust 生成)     │
            │  RCC / GPIOx / USARTx        │
            └────────────▲─────────────────┘
                         │ CPU控制 / 指令
            ┌────────────┴─────────────────┐
            │ Micro-architecture 层        │
            │ cortex-m / cortex-m-rt       │
            │ NVIC / SCB / asm / 启动逻辑  │
            └────────────▲─────────────────┘
                         │
            ┌────────────┴─────────────────┐
            │        硬件层 (MCU)          │
            │  Cortex-M4 + Flash + RAM     │
            └──────────────────────────────┘

Micro-architecture crate(CPU 层)

是底层对CPU的低级访问,是关于CPU基础行为定义

cortex-m crate

cortex-m-rt crate

Peripheral Access Crate (PAC)

地址 + 偏移 的类型安全封装

stm32f3 crate

HAL Crate

把对寄存器直接的操作抽象成为易于理解的API

stm32f3xx-hal crate

例子
let led = gpioa.pa5.into_push_pull_output();
led.set_high();

Board Crate

 比 HAL Crate 更进一步,通过预先配置各种外设和 GPIO 引脚以适应你使用的特定开发者套件或板,例如用于 STM32F3DISCOVERY 板的 stm32f3-discovery。

Semihosting半主机模式

个人感觉不实用可以用defmt 代替

Panicking

是Rust语言的核心,是内置在operation或index中的用来保证内存安全,当尝试越界时回返回panic。

当 panic 发生时,Rust 会回溯当前线程的调用栈(逐层退出函数并执行清理),除非你选择让程序在 panic 时直接终止(abort)。

因为嵌入式系统的需求差异很大(从可以崩溃到绝不能崩溃),所以 panic 的处理方式没有统一标准,但常见策略(停机、打印、重启等)已经被封装成 crate#[panic_handler],你只需要选择合适的 panic handler 即可。

panic-abort . 一个panic会导致执行中止指令直接停止。

panic-halt . 一个panic会导致程序或当前线程通过进入无限循环而停止。

panic-probe . panic信息通过RTT(内存通道)进行输出日志记录。

panic-itm . panic信息通过 ITM(ARM Cortex-M 特定外设)进行记录。

panic-semihosting . painc信息通过semihosting技术记录到主机上。

你可以在 crates.io 上搜索 panic-handler 关键词,或许能找到更多 crate。

Exceptions不想看了

异常和中断是处理器提供的一种硬件机制,用来处理异步事件(比如外设中断)和致命错误(比如非法指令)。当这些事件发生时,CPU 会抢占当前执行流程,跳转到对应的异常处理函数(handler)来处理。

Interrupts不想看了

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注