macro_rules! write_reg { ( $periph:path, $instance:expr, $reg:ident, $( $field:ident : $value:expr ),+ ) => { ... }; ( $periph:path, $instance:expr, $reg:ident, $value:expr ) => { ... }; }
Expand description
Write to a RWRegister or UnsafeRWRegister.
§Examples
// Safely acquire the peripheral instance (will panic if already acquired)
let gpioa = stm32ral::gpio::GPIOA::take().unwrap();
// Write some value to the register.
write_reg!(stm32ral::gpio, gpioa, ODR, 1<<3);
// Write values to specific fields. Unspecified fields are written to 0.
write_reg!(stm32ral::gpio, gpioa, MODER, MODER3: Output, MODER4: Analog);
// Unsafe access without requiring you to first `take()` the instance
unsafe { write_reg!(stm32ral::gpio, GPIOA, MODER, MODER3: Output, MODER4: Analog) };
§Usage
Like modify_reg!
, this macro can be used in two ways, either with a single value to write to
the whole register, or with multiple fields each with their own value.
In both 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 you wish you access:
MODER
(a field on theRegisterBlock
).
In the single-value usage, the final argument is just the value to write:
// Turn on PA3 (and turn everything else off).
write_reg!(stm32ral::gpio, gpioa, ODR, 1<<3);
Otherwise, the remaining arguments are each Field: Value
pairs:
// Set PA3 to Output, PA4 to Analog, and everything else to 0 (which is Input).
write_reg!(stm32ral::gpio, gpioa, MODER, MODER3: 0b01, MODER4: 0b11);
For fields with annotated values, you can also specify a named value:
// As above, but with named values.
write_reg!(stm32ral::gpio, gpioa, MODER, MODER3: Output, MODER4: Analog);
This macro expands to calling (*$instance).$register.write(value)
,
where in the second usage, the value is computed as the bitwise OR of
each field value, which are masked and shifted appropriately for the given field.
The named values are brought into scope by use $peripheral::$register::$field::*
for
each field. The same constants could just be specified manually:
// As above, but being explicit about named values.
write_reg!(stm32ral::gpio, gpioa, MODER, MODER3: stm32ral::gpio::MODER::MODER3::RW::Output,
MODER4: stm32ral::gpio::MODER::MODER4::RW::Analog);
The fully expanded form is equivalent to:
// As above, but expanded.
(*gpioa).MODER.write(
((stm32ral::gpio::MODER::MODER3::RW::Output << stm32ral::gpio::MODER::MODER3::offset)
& stm32ral::gpio::MODER::MODER3::mask)
|
((stm32ral::gpio::MODER::MODER4::RW::Analog << stm32ral::gpio::MODER::MODER4::offset)
& stm32ral::gpio::MODER::MODER4::mask)
);
§Safety
This macro will require an unsafe function or block when used with an UnsafeRWRegister, but not if used with RWRegister.
When run in an unsafe context, peripheral instances are directly accessible without requiring
having called take()
beforehand:
unsafe { write_reg!(stm32ral::gpio, GPIOA, MODER, MODER3: Output, MODER4: Analog) };
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.