I created a state machine for GPIO based on exmaple from the Rust Embedded Book:
pub struct Pin<FN> {
number: u8,
registers: &'static mut Registers,
function: FN
}
impl<FN> Pin<FN> {
fn select_function<F>(self, function: F, fsel: u32) -> Pin<F> {
let v = fsel << (self.number % 10) * 3;
let r = &self.registers.gpfsel[(self.number / 10) as usize];
r.modify(|x| x | v);
Pin {
number: self.number,
registers: self.registers,
function
}
}
fn into_default(self) -> Pin<Default> {
Pin {
number: self.number,
registers: self.registers,
function: Default
}
}
}
impl Pin<Default> {
pub fn take(number: u8) -> Option<Self> {
if PIN_ENABLED.set_bit(number) {
None
} else {
Some(Pin {
number,
registers: unsafe {
&mut *(BASE_ADDR as *mut Registers)
},
function: Default
})
}
}
pub fn into_output(self) -> Pin<Output> {
self.select_function(Output, 1)
}
}
impl Pin<Output> {
pub fn set(&self) {
let v = 1u32 << (self.number % 32);
let r = &self.registers.gpset[(self.number / 32) as usize];
r.write(v);
}
pub fn clear(&self) {
let v = 1u32 << (self.number % 32);
let r = &self.registers.gpclr[(self.number / 32) as usize];
r.write(v);
}
pub fn level(&self) -> bool {
let r = &self.registers.gplev[(self.number / 32) as usize];
r.read() & 1u32 << (self.number % 32) != 0
}
}
Well, I'm still not pretty sure I know exactly what I'm doing, but as far as I understand it, in select_function()
I use self
so that the function takes ownership and self
goes out of scope on return, and an instance of new type is created. But do I need to implement Drop for the Pin<FN>
type so that it's dropped when goes out of scope?