要进行真正意义上的嵌入式开发,总是需要对某个地址进行读写操作。C 语言上的操作比较简单。
volatile unsigned int *addr = 0x20000010;
unsigned int value = *addr;
*addr = 2;
Rust 也提供了类似的方法
[#!no_std]
use core::ptr;
let addr = 0x20000010 as *const u32;
unsafe {
let value = ptr::read_volatile(addr);
ptr::write_volatile(addr, 2);
}
Rust 的包管理系统给应用提供了很好的分层机制。
Board crate 板极
-----------------
Hal crate 试图定义一些通用操作,类似 CMSIS
-----------------
PAC crate 外设, 比如 UART,可以用 SVD 文件描述
-----------------
CPU crate CPU 寄存器,比如 systick
于是对于一个系统寄存器的读写就通过层层封装。
cortex_m (CPU crate)
|
|-> peripheral module (systick, nvic, ...)
|
|-> volatile_register::{RO, RW}
|
|-> vcell (volatile cell)
|
|-> core::ptr{read_volatile, write_volatile}
这是一个对 systick 模块的配置。
use cortex_m::peripheral::{syst, Peripherals};
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let mut systick = peripherals.SYST;
systick.set_clock_source(syst::SystClkSource::Core);
systick.set_reload(1_000);
systick.clear_current();
systick.enable_counter();
while !systick.has_wrapped() {
// Loop
}
loop {}
}