Spooky action at a distance
OUT
is not the only register that can control the pins of Port E. The OUTSET
register also lets
you change the value of the pins, as can OUTCLR
. However, ODRSET
and OUTCLR
don't let you
retrieve the current output status of Port E.
OUTSET
is documented in:
Subsection 6.8.2.2. OUTSET - Page 145
Let's look at below program. The key to this program is fn print_out
. This function prints the
current value in OUT
to the RTT
console (examples/spooky.rs
):
#![no_main] #![no_std] use core::ptr; #[allow(unused_imports)] use registers::{entry, rprintln}; // Print the current contents of P0.OUT fn print_out() { const P0_OUT: u32 = 0x5000_0504; let out = unsafe { ptr::read_volatile(P0_OUT as *const u32) }; rprintln!("P0.OUT = {:#08x}", out); } #[entry] fn main() -> ! { registers::init(); unsafe { // A bunch of magic addresses! const P0_OUTSET: u32 = 0x5000_0508; const P0_OUTCLR: u32 = 0x5000_050C; // Print the initial contents of OUT print_out(); // Turn on the top LED row ptr::write_volatile(P0_OUTSET as *mut u32, 1 << 21); print_out(); // Turn on the bottom LED row ptr::write_volatile(P0_OUTSET as *mut u32, 1 << 19); print_out(); // Turn off the top LED row ptr::write_volatile(P0_OUTCLR as *mut u32, 1 << 21); print_out(); // Turn off the bottom LED row ptr::write_volatile(P0_OUTCLR as *mut u32, 1 << 19); print_out(); } loop {} }
You'll see this if you run this program:
$ cargo embed
# cargo-embed's console
(..)
15:13:24.055: P0.OUT = 0x000000
15:13:24.055: P0.OUT = 0x200000
15:13:24.055: P0.OUT = 0x280000
15:13:24.055: P0.OUT = 0x080000
15:13:24.055: P0.OUT = 0x000000
Side effects! Although we are reading the same address multiple times without actually modifying it,
we still see its value change every time OUTSET
or OUTCLR
is written to.