summaryrefslogtreecommitdiff
path: root/src/hal/gpio.rs
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2022-12-13 16:45:49 -0700
committerJosh Rahm <joshuarahm@gmail.com>2022-12-13 16:45:49 -0700
commit540e0316aa425a8fbd126d31350dbe51fca92791 (patch)
treeabc938b9b9f21b7d2357a18272d84c263d767142 /src/hal/gpio.rs
parent8bb2d168044213ce9bd31a19efb6bab90f5c9722 (diff)
downloadstm32l4-rust-master.tar.gz
stm32l4-rust-master.tar.bz2
stm32l4-rust-master.zip
Experimental Gpio.HEADmaster
This rapidly blinks the sysled on the stm32. This shows the ability to manipulate memory mapped registers.
Diffstat (limited to 'src/hal/gpio.rs')
-rw-r--r--src/hal/gpio.rs148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/hal/gpio.rs b/src/hal/gpio.rs
new file mode 100644
index 0000000..d25a7db
--- /dev/null
+++ b/src/hal/gpio.rs
@@ -0,0 +1,148 @@
+/** 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,
+ };
+}