Skip to main content

Module register

Module register 

Source
Expand description

Macro to define register layout and accessors.

The register! macro provides an intuitive and readable syntax for defining a dedicated type for each register and accessing it using Io. Each such type comes with its own field accessors that can return an error if a field’s value is invalid.

Note: most of the items in this module are public so they can be referenced by the macro, but most are not to be used directly by users. Outside of the register! macro itself, the only items you might want to import from this module are WithBase and Array.

§Simple example

use kernel::io::register;

register! {
    /// Basic information about the chip.
    pub BOOT_0(u32) @ 0x00000100 {
        /// Vendor ID.
        15:8 vendor_id;
        /// Major revision of the chip.
        7:4 major_revision;
        /// Minor revision of the chip.
        3:0 minor_revision;
    }
}

This defines a 32-bit BOOT_0 type which can be read from or written to offset 0x100 of an Io region, with the described bitfields. For instance, minor_revision consists of the 4 least significant bits of the type.

Fields are instances of Bounded and can be read by calling their getter method, which is named after them. They also have setter methods prefixed with with_ for runtime values and with_const_ for constant values. All setters return the updated register value.

Fields can also be transparently converted from/to an arbitrary type by using the => and ?=> syntaxes.

If present, doc comments above register or fields definitions are added to the relevant item they document (the register type itself, or the field’s setter and getter methods).

Note that multiple registers can be defined in a single register! invocation. This can be useful to group related registers together.

Here is how the register defined above can be used in code:

use kernel::{
    io::{
        register,
        Io,
        IoLoc,
    },
    num::Bounded,
};

// Read from the register's defined offset (0x100).
let boot0 = io.read(BOOT_0);
pr_info!("chip revision: {}.{}", boot0.major_revision().get(), boot0.minor_revision().get());

// Update some fields and write the new value back.
let new_boot0 = boot0
    // Constant values.
    .with_const_major_revision::<3>()
    .with_const_minor_revision::<10>()
    // Runtime value.
    .with_vendor_id(obtain_vendor_id());
io.write_reg(new_boot0);

// Or, build a new value from zero and write it:
io.write_reg(BOOT_0::zeroed()
    .with_const_major_revision::<3>()
    .with_const_minor_revision::<10>()
    .with_vendor_id(obtain_vendor_id())
);

// Or, read and update the register in a single step.
io.update(BOOT_0, |r| r
    .with_const_major_revision::<3>()
    .with_const_minor_revision::<10>()
    .with_vendor_id(obtain_vendor_id())
);

// Constant values can also be built using the const setters.
const V: BOOT_0 = pin_init::zeroed::<BOOT_0>()
    .with_const_major_revision::<3>()
    .with_const_minor_revision::<10>();

For more extensive documentation about how to define registers, see the register! macro.

Structs§

FixedRegisterLoc
Location of a fixed register.
RegisterArrayLoc
Location of an array register.
RelativeRegisterArrayLoc
Location of a relative array register.
RelativeRegisterLoc
Location of a relative register.

Traits§

Array
Trait providing location builders for RegisterArrays.
FixedRegister
Trait implemented by registers with a fixed offset.
LocatedRegister
Trait implemented by items that contain both a register value and the absolute I/O location at which to write it.
Register
Trait implemented by all registers.
RegisterArray
Trait implemented by arrays of registers.
RegisterBase
Trait providing a base address to be added to the offset of a relative register to obtain its actual offset.
RelativeRegister
Trait implemented by relative registers.
RelativeRegisterArray
Trait implemented by arrays of relative registers.
WithBase
Trait implemented by all registers that are relative to a base.