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嵌入式开发

Download history 29/week @ 2024-04-29 39/week @ 2024-05-06 213/week @ 2024-05-13 74/week @ 2024-05-20 82/week @ 2024-05-27 89/week @ 2024-06-03 60/week @ 2024-06-10 59/week @ 2024-06-17 200/week @ 2024-06-24 15/week @ 2024-07-01 37/week @ 2024-07-08 52/week @ 2024-07-15 11/week @ 2024-07-22 62/week @ 2024-07-29 4/week @ 2024-08-05 17/week @ 2024-08-12

每月下载量97次
4 个crate中使用 4 (3直接)

Zlib OR Apache-2.0 OR MIT

60KB
1K SLoC

License:Zlib License:Apache2 License:MIT

crates.io docs.rs

voladdress

一个使易失性内存操作易于处理的crate。

主要用于内存映射I/O (MMIO)。


lib.rs:

一个用于处理易失性位置的crate,特别是内存映射I/O (MMIO)。

类型

crate的核心类型是 [VolAddress<T, R, W>]。

  • T 是存储在地址处的元素类型。预期您的元素类型将是可以用单条指令由CPU读取和写入的类型。这通常将是一个单个整数、浮点数、数据指针、函数指针或上述类型之一的一个 repr(transparent) 包装器。
  • R 应为 [Safe],[Unsafe] 或 ()。当 RSafe 时,您可以安全地从地址读取。当 RUnsafe 时,您可以不安全地从地址读取。如果 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>]用于当您有在规律间隔上步进的许多值,但它们之间有额外空间时。

在这两种情况下,处理数据有两种基本方式

  • 使用lenindexget,您可以生成单个类似于切片可以生成切片数据范围内的引用的VolAddress值。
  • 使用iteriter_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));

无生命周期

请注意,VolAddressVolBlockVolSeries都是Copy数据类型,没有生命周期参数。假设您的设备的MMIO内存映射是设备的一个固定部分,并且从这个crate中使用的类型将用于创建描述整个程序期间不变的单一内存映射的const声明。如果您的设备的内存映射可能发生变化,那么您必须在您的声明中考虑这一点。

无运行时依赖