Deref on a register (ARM embedded) cortex-m

Hi.

I've been studying cortex-m crate code. Mostly the ITM struct. What I can't understand is how is it possible for code:

#![no_main]
#![no_std]

use panic_itm as _;
use stm32f1xx_hal as _;

use cortex_m::{iprintln, Peripherals};
use cortex_m_rt::entry;

#[entry]
fn main() -> ! {
    let mut p = Peripherals::take().unwrap();
    let stim = &mut p.ITM.stim[0];

    iprintln!(stim, "Hello, world!");

    loop {}
}

To even compile and work. ITM struct foes not have any fields. RegisterBlock is created while accessing any field in ITM struct ?. Looks like a black magic for me.

Yep, when you write ITM.field, the Deref impl is called and a RegisterBlock is created. Note that creating this RegisterBlock just involves creating a pointer and turning it into a reference, so this “creation” is not exactly an expensive operation: It's as cheap as typing an integer somewhere in your code.

Thx for information. One thing is still missing for me. RegisterBlock has stim field which is an array of

Stim has a register field which is nowhere created. This is confusing for me.

The Deref impl creates the RegisterBlock by casting the value 0xE000_0000 to a pointer. This means that when using fields of RegisterBlock, you're just accessing whatever happens to be there.

Since the stim field is a fixed-size array, it is stored in-line, and not somewhere else like you have with Vec. This means that the contents of the stim field is just whatever values happen to be in memory at address 0xE000_0000.

Ok. I think I need to read more https://doc.rust-lang.org/1.30.0/book/second-edition/ch15-00-smart-pointers.html

Thx for patience and explanation.