Peripheral Initialisation of GPIO Output with stm32f1xx_hal on bluepill development board

410 Views Asked by At

I would like to initialize a basic output GPIO pin on my blue pill board. I am using Rust and the stm32f1xx_hal crate. I want to create a struct Peripherals which holds the handle to the output in the following way:

use cortex_m_rt;

use stm32f1xx_hal::{
  pac, 
  prelude::*,
  gpio,
  afio,
  serial::{Serial, Config},
};

use crate::pac::{USART1};

type GpioOutput = gpio::gpioc::PC13<gpio::Output<gpio::PushPull>>;

pub struct Peripherals{
  led: Option<GpioOutput>
}

impl Peripherals {
  fn init() -> Peripherals {

    let dp = pac::Peripherals::take().unwrap();
    let cp = cortex_m::Peripherals::take().unwrap();

    // set clock frequency to internal 8mhz oscillator
    let mut rcc = dp.RCC.constrain();
    let mut flash = dp.FLASH.constrain();
    let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(&mut flash.acr);

    // access PGIOC registers
    let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);

    return Peripherals{
      led: Peripherals::init_led(&mut gpioc)
    }
  }

  fn init_led(gpioc: &mut gpio::gpioc::Parts) -> Option<GpioOutput> {
    let led = &gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
    return Some(led);
  }
}

This code does not work, since init_led returns Option<&GpioOutput>. Now I am wondering if it makes sense to use a lifetime parameter in the Peripherals struct and store a reference to the GpioOutput within the struct. Or is it more sensible to store the unreferenced value - and how would I implement either of these options?

The only solution which seems to work is moving the init_led code to the scope of the init function:

return Peripherals{
  led: Some(gpioc.pc13.into_push_pull_output(&mut gpioc.crh))
}

But i would like to seperate that code within its own function. How can i do that?

1

There are 1 best solutions below

0
Lut Ze On

Ok, i figured out a way in case someone else is having the same problem:

  pub fn init() -> Peripherals {

    let dp = pac::Peripherals::take().unwrap();
    let cp = cortex_m::Peripherals::take().unwrap();

    // set clock frequency to internal 8mhz oscillator
    let rcc = dp.RCC.constrain();

    let mut flash = dp.FLASH.constrain();

    // access PGIOC and PGIOB registers and prepare the alternate function I/O registers
    let mut apb2 = rcc.apb2;
    let gpioc = dp.GPIOC.split(&mut apb2);

    let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(&mut flash.acr);

    return Peripherals{
      led: Peripherals::init_led(gpioc)
    }
  }

  fn init_led(mut gpioc: stm32f1xx_hal::gpio::gpioc::Parts) -> Option<GpioOutput> {
    let led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
    return Some(led);
  }

I am just wondering if this is the correct way to do it or will it create extra overhead, because i am passing gpioc by value instead of by reference in the init_led function?