简体   繁体   中英

Peripheral Initialisation of GPIO Output with stm32f1xx_hal on bluepill development board

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?

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?

This looks mostly correct. Passing by value works faster, but it will destroy the variable. Which means you wouldn't be able to use it otherwise.

Also you only return the led in the function. How would you handle adding more peripherals?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM