Expand description
A crate for working with volatile locations, particularly Memory Mapped IO (MMIO).
§Types
The crate’s core type is VolAddress<T, R, W>.
Tis the element type stored at the address. It is expected that your element type will be something that the CPU can read and write with a single instruction. Generally this will be a single integer, float, data pointer, function pointer, or arepr(transparent)wrapper around one of the other types just listed.Rshould be Safe, Unsafe, or(). WhenRisSafethen you can safely read from the address. WhenRisUnsafethen you can unsafely read from the address. IfRis any other type then you cannot read from the address at all. While any possible type can be used here, if reading isn’t intended you should use()as the canonical null type.Wworks likeRin terms of what types you should use with it, but it controls writing instead of reading.
The VolAddress type uses the “unsafe creation, then safe use” style. This
allows us to use the fewest unsafe blocks overall. Once a VolAddress has
been unsafely declared, each individual operation using them is generally
going to be safe. Some addresses might be unsafe to use even after creation,
but this is relatively rare.
Here are some example declarations. Note that the address values used are for illustation purposes only, and will vary for each device.
// 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) };§Multiple Locations
Often we have many identically typed values at a regular pattern in memory. These are handled with two very similar types.
VolBlock<T, R, W, const C: usize> is for when there’s many values tightly packed, with no space in between. Use this type when you want to emulate how an array works.
VolSeries<T, R, W, const C: usize, const S: usize> is for when you have many values strided out at regular intervals, but they have extra space in between each element.
In both cases, there’s two basic ways to work with the data:
- Using
len,index, andget, you can produce individualVolAddressvalues similar to how a slice can produce references into the slice’s data range. - Using
iteroriter_rangeyou can produce an in iterator that will go over the variousVolAddressvalues during the iteration.
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));§No Lifetimes
Note that VolAddress, VolBlock, and VolSeries are all Copy data
types, without any lifetime parameter. It is assumed that the MMIO memory
map of your device is a fixed part of the device, and that the types from
this crate will be used to create const declarations that describe that
single memory map which is unchanging during the entire program. If the
memory mapping of your device can change then you must account for this in
your declarations.
Structs§
- Safe
- Lets you put “Safe” into a generic type parameter.
- Unsafe
- Lets you put “Unsafe” into a generic type parameter.
- VolAddress
- A volatile address.
- VolBlock
- A volatile memory block.
- VolBlock
Iter - An iterator over a volatile block.
- VolGrid2d
- A 2D version of
VolBlock, with a const genericWIDTHandHEIGHT. - VolGrid2d
Strided - Models having many “frames” of
VolGrid2dwithin a chunk of memory. - VolRegion
- A dynamically sized span of volatile memory.
- VolSeries
- A volatile memory “series”.
- VolSeries
Iter - An iterator over a volatile series.