macro_rules! read_reg { ( $periph:path, $instance:expr, $reg:ident $([$offset:expr])*, $( $field:ident ),+ $(,)? ) => { ... }; ( $periph:path, $instance:expr, $reg:ident $([$offset:expr])*, $field:ident $($cmp:tt)* ) => { ... }; ( $periph:path, $instance:expr, $reg:ident $([$offset:expr])* ) => { ... }; }
Expand description
Read the value from a RORegister, RWRegister, UnsafeRORegister, or UnsafeRWRegister.
§Examples
// Safely acquire the peripheral instance (will panic if already acquired)
let gpioa = stm32ral::gpio::GPIOA::take().unwrap();
// Read the whole register.
let val = read_reg!(stm32ral::gpio, gpioa, IDR);
// Read one field from the register.
let val = read_reg!(stm32ral::gpio, gpioa, IDR, IDR2);
// Read multiple fields from the register.
let (val1, val2, val3) = read_reg!(stm32ral::gpio, gpioa, IDR, IDR0, IDR1, IDR2);
// Check if one field is equal to a specific value, with the field's named values in scope.
while read_reg!(stm32ral::gpio, gpioa, IDR, IDR2 == High) {}
// Unsafe access without requiring you to first `take()` the instance
let val = unsafe { read_reg!(stm32ral::gpio, GPIOA, IDR) };
To support register arrays, each macro form also supports one or more array indices after the
register. For example, read_reg!(stm32ral::gpio, gpioa, ODR[2]);
reads from the third
register of an ODR
register array.
§Usage
Like write_reg!
, this macro can be used multiple ways, either reading the entire register or
reading a one or more fields from it and potentially performing a comparison with one field.
In all cases, the first arguments are:
- the path to the peripheral module:
stm32ral::gpio
, - a reference to the instance of that peripheral: ‘gpioa’ (anything which dereferences to
RegisterBlock
, such asInstance
,&Instance
,&RegisterBlock
, or*const RegisterBlock
), - the register (and offset, for arrays) you wish to access:
IDR
(a field on theRegisterBlock
).
In the whole-register usage, the macro simply returns the register’s value:
// Read the entire value of GPIOA.IDR into `val`.
let val = read_reg!(stm32ral::gpio, gpioa, IDR);
For reading individual fields, the macro masks and shifts appropriately:
// Read just the value of the field GPIOA.IDR2 into `val`.
let val = read_reg!(stm32ral::gpio, gpioa, IDR, IDR2);
// As above, but expanded for exposition:
let val = ((*gpioa).IDR.read() & stm32ral::gpio::IDR::IDR2::mask)
>> stm32ral::gpio::IDR::IDR2::offset;
// Read multiple fields
let (val1, val2) = read_reg!(stm32ral::gpio, gpioa, IDR, IDR2, IDR3);
// As above, but expanded for exposition:
let (val1, val2) = { let val = (*gpioa).IDR.read();
((val & stm32ral::gpio::IDR::IDR2::mask) >> stm32ral::gpio::IDR::IDR2::offset,
(val & stm32ral::gpio::IDR::IDR3::mask) >> stm32ral::gpio::IDR::IDR3::offset,
)};
For comparing a single field, the macro masks and shifts and then performs the comparison:
// Loop while PA2 is High.
while read_reg!(stm32ral::gpio, gpioa, IDR, IDR2 == High) {}
// Only proceed if the clock is not the HSI.
if read_reg!(stm32ral::rcc, rcc, CFGR, SWS != HSI) { }
// Equivalent expansion:
if (((*rcc).CFGR.read() & stm32ral::rcc::CFGR::SWS::mask)
>> stm32ral::rcc::CFGR::SWS::offset) != stm32ral::rcc::CFGR::SWS::R::HSI { }
§Safety
This macro will require an unsafe function or block when used with an UnsafeRWRegister or UnsafeRORegister, but not if used with RWRegister, or RORegister.
When run in an unsafe context, peripheral instances are directly accessible without requiring
having called take()
beforehand:
let val = unsafe { read_reg!(stm32ral::gpio, GPIOA, MODER) };
This works because GPIOA
is a *const RegisterBlock
in the stm32ral::gpio
module;
and the macro brings such constants into scope and then dereferences the provided reference.