11个版本 (4个稳定版)
1.4.0 | 2024年5月15日 |
---|---|
1.3.0 | 2023年3月5日 |
1.2.3 | 2023年2月20日 |
1.2.2 | 2022年11月8日 |
0.2.3 | 2019年3月16日 |
#137 在 嵌入式开发
每月下载量97次
在 4 个crate中使用 4 (3直接)
60KB
1K SLoC
voladdress
一个使易失性内存操作易于处理的crate。
主要用于内存映射I/O (MMIO)。
lib.rs
:
一个用于处理易失性位置的crate,特别是内存映射I/O (MMIO)。
类型
crate的核心类型是 [VolAddress<T, R, W>]。
T
是存储在地址处的元素类型。预期您的元素类型将是可以用单条指令由CPU读取和写入的类型。这通常将是一个单个整数、浮点数、数据指针、函数指针或上述类型之一的一个repr(transparent)
包装器。R
应为 [Safe],[Unsafe] 或()
。当R
是Safe
时,您可以安全地从地址读取。当R
是Unsafe
时,您可以不安全地从地址读取。如果R
是任何其他类型,则您根本不能从地址读取。虽然可以使用任何可能的类型,但如果不需要读取,则应使用()
作为规范的无类型。W
在使用类型方面与R
类似,但它控制写入而不是读取。
VolAddress
类型使用“不安全创建,然后安全使用”的风格。这使我们能够使用最少的 unsafe
块。一旦声明了 VolAddress
,使用它们的每个单独操作通常将是安全的。某些地址在创建后可能仍然不安全使用,但这相对罕见。
以下是示例声明。请注意,这里使用的地址值仅用于说明目的,并且每个设备都会有差异。
// read-only
pub const VCOUNT: VolAddress<u16, Safe, ()> =
unsafe { VolAddress::new(0x0400_0006) };
// write-only
pub const BG0_XOFFSET: VolAddress<u16, (), Safe> =
unsafe { VolAddress::new(0x0400_0010) };
// read-write
pub const BLDALPHA_A: VolAddress<u8, Safe, Safe> =
unsafe { VolAddress::new(0x0400_0052) };
// this location has some illegal bit patterns, so it's unsafe
// to write to with any random `u16` you might have.
pub const RAW_DISPLAY_CONTROL: VolAddress<u16, Safe, Unsafe> =
unsafe { VolAddress::new(0x0400_0000) };
// If we use a transparent wrapper and getter/setters, we can
// prevent the illegal bit patterns, and now it's safe to write.
#[repr(transparent)]
pub struct DisplayCtrl(u16);
pub const DISPLAY_CONTROL: VolAddress<DisplayCtrl, Safe, Safe> =
unsafe { VolAddress::new(0x0400_0000) };
多个位置
我们通常在内存中以规律的模式拥有许多相同类型的值。这些值使用两种非常类似的数据类型进行处理。
[VolBlock<T, R, W, const C: usize>]
用于当有许多紧密排列的值而没有间隔空间时。当您想要模拟数组的工作方式时,请使用此类型。
[VolSeries<T, R, W, const C: usize, const S: usize>]
用于当您有在规律间隔上步进的许多值,但它们之间有额外空间时。
在这两种情况下,处理数据有两种基本方式
- 使用
len
、index
和get
,您可以生成单个类似于切片可以生成切片数据范围内的引用的VolAddress
值。 - 使用
iter
或iter_range
,您可以在迭代过程中生成一个遍历各种VolAddress
值的迭代器。
pub const BG_PALETTE: VolBlock<u16, Safe, Safe, 256> =
unsafe { VolBlock::new(0x0500_0000) };
pub const COLOR_RED: u16 = 0b11111;
BG_PALETTE.index(0).write(COLOR_RED);
pub const COLOR_GREEN: u16 = 0b11111_00000;
BG_PALETTE.iter_range(1..).for_each(|a| a.write(COLOR_GREEN));
pub const MY_ROM_PALETTE_DATA: [u16; 256] = [0xAB; 256];
BG_PALETTE
.iter()
.zip(MY_ROM_PALETTE_DATA.iter().copied())
.for_each(|(a, c)| a.write(c));
无生命周期
请注意,VolAddress
、VolBlock
和VolSeries
都是Copy
数据类型,没有生命周期参数。假设您的设备的MMIO内存映射是设备的一个固定部分,并且从这个crate中使用的类型将用于创建描述整个程序期间不变的单一内存映射的const
声明。如果您的设备的内存映射可能发生变化,那么您必须在您的声明中考虑这一点。