Volatile memory access for MMIO

  • Use pointer::read_volatile and pointer::write_volatile.
  • Never hold a reference to a location being accessed with these methods. Rust may read from (or write to, for &mut) a reference at any time.
  • Use &raw to get fields of structs without creating an intermediate reference.
const SOME_DEVICE_REGISTER: *mut u64 = 0x800_0000 as _;
// SAFETY: Some device is mapped at this address.
unsafe {
    SOME_DEVICE_REGISTER.write_volatile(0xff);
    SOME_DEVICE_REGISTER.write_volatile(0x80);
    assert_eq!(SOME_DEVICE_REGISTER.read_volatile(), 0xaa);
}
  • Volatile access: read or write operations may have side-effects, so prevent the compiler or hardware from reordering, duplicating or eliding them.
    • Usually if you write and then read, e.g. via a mutable reference, the compiler may assume that the value read is the same as the value just written, and not bother actually reading memory.
  • Some existing crates for volatile access to hardware do hold references, but this is unsound. Whenever a reference exist, the compiler may choose to dereference it.
  • Use &raw to get struct field pointers from a pointer to the struct.
  • For compatibility with old versions of Rust you can use the addr_of! macro instead.