Passing reference to memory-mapped register to function

Let's say I have a standard memory-mapped registers block

#[repr(C)]
struct Registers {
    regset: ReadWrite<u32>,
    regclr: ReadWrite<u32>,
}

And I have finite state machine with some state defined as

pub struct Pin<FN> {
    number: u8,
    registers: &'static mut Registers,
    function: FN
}

impl Pin<Output> {
    pub fn set(&self) {
        let v = 1u32 << (self.number % 32);
        let r = &self.registers.regset[(self.number / 32) as usize];
        r.write(v);
    }

    pub fn clear(&self) {
        let v = 1u32 << (self.number % 32);
        let r = &self.registers.regclr[(self.number / 32) as usize];
        r.write(v);
    }
}

What I want to do is to define a change_state proc which will take reference to appropriate register as input param, so that I could do something like:

pub fn change_state(&self, reg: ???) {
    let v = 1u32 << (self.number % 32);
    let r = reg[(self.number / 32) as usize];
    reg.write(v);
}

pub fn set(&self) {
    change_state(&self.registers.regset);
}

But I don't quiet understand what type reg param should have and why. Could you explain how to correctly do this, please? Thanks in advance!

Side question: is it a good or bad practice to do such things?

Memory-mapped registers require access with volatile semantics, because the compiler must be aware that each access potentially has external side-effects. See the section of Rust Embedded's book on Memory Mapped Registers.

2 Likes