/** Base addresses for the Gpio ports. */ static GPIOA_BASE: u32 = 0x48000000; static GPIOB_BASE: u32 = 0x48000400; static GPIOC_BASE: u32 = 0x48000800; static GPIOH_BASE: u32 = 0x48001C00; use crate::hal::common::{regget, regset}; use crate::hal::rcc::{get_rcc, GpioPortN}; #[derive(Clone, Copy)] pub enum GpioMode { Input = 0, Output = 1, Alternate = 2, Analog = 3, } #[derive(Clone, Copy)] pub enum GpioOutputType { PushPull = 0, OpenDrain = 1, } pub enum GpioSpeed { Low = 0, Medium = 1, High = 2, VeryHigh = 3, } pub enum GpioPullDir { None = 0, Up = 1, Down = 2, } /* Struct representation of a GPIO Port. */ #[repr(C)] struct GpioPortMem { /* Mode of each GPIO pin for this GPIO port. */ mode_r: u32, /* Output type for each gpio pin in this port. */ otype_r: u32, /* GPIO port output speed. */ ospeed_r: u32, /* GPIO port pull-up/pull-down register */ pupd_r: u32, /* GPIO port input data register. */ id_r: u32, /* GPIO port output data register. */ od_r: u32, /* GPIO port bit set/reset register. */ bsr_r: u32, /* GPIO port configuration lock register. */ lck_r: u32, /* Alternate function low-register. */ af_rl: u32, /* Alternate function high-register. */ af_rh: u32, /* GPIO port bit register. */ br_r: u32, /* Analog switch control register. */ asc_r: u32, } #[derive(Clone, Copy)] pub struct GpioPort { mem: *mut GpioPortMem, } pub struct GpioPin { port: GpioPort, pin_number: u8, } impl GpioPort { pub fn pin(self: &mut GpioPort, n: u8) -> GpioPin { return GpioPin { port: *self, pin_number: n, }; } } impl GpioPin { pub unsafe fn set_mode(self: &mut GpioPin, mode: GpioMode) -> () { let mode_ptr: *mut u32 = &mut (*self.port.mem).mode_r; regset(mode_ptr, 3 << self.pin_number * 2, mode as u32); } pub unsafe fn set_pull_dir(self: &mut GpioPin, pull_dir: GpioPullDir) { let pull_dir_ptr: *mut u32 = &mut (*self.port.mem).pupd_r; regset(pull_dir_ptr, 3 << self.pin_number * 2, pull_dir_ptr as u32); } pub unsafe fn set_output_type(self: &mut GpioPin, otype: GpioOutputType) -> () { let otype_ptr: *mut u32 = &mut (*self.port.mem).otype_r; regset(otype_ptr, 1 << self.pin_number, otype as u32); } pub unsafe fn set_output_speed(self: &mut GpioPin, ospeed: GpioSpeed) -> () { let ospeed_ptr: *mut u32 = &mut (*self.port.mem).ospeed_r; regset(ospeed_ptr, 3 << self.pin_number * 2, ospeed as u32); } pub unsafe fn get(self: &mut GpioPin) -> bool { let id_r: *mut u32 = &mut (*self.port.mem).id_r; regget(id_r, 1 << self.pin_number) != 0 } pub unsafe fn set_high(self: &mut GpioPin) { self.set(true); } pub unsafe fn set_low(self: &mut GpioPin) { self.set(false); } pub unsafe fn set(self: &mut GpioPin, on: bool) -> () { let od_r: *mut u32 = &mut (*self.port.mem).od_r; regset(od_r, 1 << self.pin_number, on as u32); } } pub fn get_gpio_port_a() -> GpioPort { get_rcc().enable_gpio_port(GpioPortN::A); return GpioPort { mem: GPIOA_BASE as *mut GpioPortMem, }; } pub fn get_gpio_port_b() -> GpioPort { get_rcc().enable_gpio_port(GpioPortN::B); return GpioPort { mem: GPIOB_BASE as *mut GpioPortMem, }; }