ok, I'm not familiar with the stm32 hardware resources, but let me try to guess from your code.
as I said, the gpioe::Parts
type should only be used during intialization and functional configuration, and you do it by move
pins from it. for example, you should do something like this in the initialization code:
struct MyEncoder {
pin1: PE6<Input<Pullup>>,
pin2: PC15<Input<Pullup>>,
//....
}
fn configure_encoder(
pin1: PE6<Input<Floating>>,
pin2: PC15<Input<Floating>>,
//...
) -> MyEncoder {
todo!()
}
fn main() {
let periph = pac::Peripherals::take().unwrap();
let gpioe = periph.GPIOE.split();
let gpioc = periph.GPIOC.split();
//...
let encoder = configure_encoder(
gpioe.pe6.into_pull_up_input(&mut gpioe.crl),
gpioc.pc15.into_pull_up_input(&mut gpioc.crh),
//...
);
}
then you can write your encoder driver with the custom type MyEncoder
:
pub fn read_data(encoder: &mut MyEncoder) -> u8 {
let mut value = 8u8;
if encoder.pin1.is_high() { value |= 0x80; }
if encoder.pin1.is_high() { value |= 0x40; }
//...
value
}
technically you don't have to define a struct, you can always use these individual pins directly, but it's tedious and error prone to spell out 8 pins every time you call them:
pub fn configure_encoder(
pin1: PE6<Input<Floating>>,
pin2: PC15<Input<Floating>>,
//...
) -> (
PE6<Input<Pullup>>,
PC15<Input<Pullup>>
//...
) {
todo!()
}
pub fn read_encoder_data(
pin1: &mut PE6<Input<Pullup>>,
pin2: &mut PC15<Input<Pullup>>,
//...
) -> u8 {
//...
}
they key point is, you can turn from a Pin<P, N, Mode1>
to Pin<P, N, Mode2>
, but only once, then the Mode1
pin disappears, and you have a Mode2
pin. this is called linear type. so when you configure the pins, you should take them by value (i.e. move) and return pins with different types. but for the operational function, you should take them by exclusive reference (i.e. mut reference) so the compiler can check it's not possible to access them concurrently.
it's a bit complicated than your typical embeded C programs, but once you write the type write, a vast portion of common mistakes when using C is now checked by the compiler and guaranteed to work.