summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hal/clock.rs10
-rw-r--r--src/hal/common.rs25
-rw-r--r--src/hal/gpio.rs148
-rw-r--r--src/hal/mod.rs4
-rw-r--r--src/hal/rcc.rs167
-rw-r--r--src/hal/usart.rs16
-rw-r--r--src/main.rs29
7 files changed, 396 insertions, 3 deletions
diff --git a/src/hal/clock.rs b/src/hal/clock.rs
new file mode 100644
index 0000000..5c97a91
--- /dev/null
+++ b/src/hal/clock.rs
@@ -0,0 +1,10 @@
+struct Pwr {
+ cr : u32,
+ csr : u32,
+}
+
+extern "C" {
+ static mut __Pwr_base : u32;
+}
+
+static PWR: *mut Pwr = __Pwr_base as *mut Pwr;
diff --git a/src/hal/common.rs b/src/hal/common.rs
new file mode 100644
index 0000000..9b07c4e
--- /dev/null
+++ b/src/hal/common.rs
@@ -0,0 +1,25 @@
+/*
+ * Sets bits in the register pointed to by 'reg'.
+ *
+ * reg: raw pointer to the register to manipulate.
+ * mask: the bits to change in the register. The binary of mask should follow
+ * the regex 0*1*0* (i.e. all the 1's should be contiguous).
+ * val: The value to write to the bits referenced by 'mask'
+ */
+pub fn regset(reg: *mut u32, mask: u32, val: u32) -> () {
+ unsafe {
+ reg.write_volatile((reg.read_volatile() & !mask) | (val << mask.trailing_zeros()));
+ }
+}
+
+/*
+ * Returns bits in the register pointed to by 'reg'.
+ *
+ * reg: raw pointer to the register to read
+ * mask: the bits to retrieve.
+ */
+pub fn regget(reg: *mut u32, mask: u32) -> u32 {
+ unsafe {
+ (reg.read_volatile() & mask) >> mask.trailing_zeros()
+ }
+}
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,
+ };
+}
diff --git a/src/hal/mod.rs b/src/hal/mod.rs
new file mode 100644
index 0000000..658bffc
--- /dev/null
+++ b/src/hal/mod.rs
@@ -0,0 +1,4 @@
+pub mod usart;
+pub mod gpio;
+pub mod common;
+pub mod rcc;
diff --git a/src/hal/rcc.rs b/src/hal/rcc.rs
new file mode 100644
index 0000000..1041100
--- /dev/null
+++ b/src/hal/rcc.rs
@@ -0,0 +1,167 @@
+use crate::hal::common::{regset, regget};
+
+#[repr(C)]
+pub struct RccMem {
+ c_r: u32, /* Clock control register. 0x00 */
+ icsc_r: u32, /* Internal clock srcs calibration register. 0x04 */
+ cfg_r: u32, /* clock confguration register. 0x08 */
+ pllcfg_r: u32, /* PLL Configuration register. 0x0c */
+ pllsai1cfg_r: u32, /* PLLSAI1 configuration register. 0x10 */
+
+ reserved_1: u32, /* Not used. offset 0x14. */
+
+ cie_r: u32, /* Clock interrupt enable register. 0x18 */
+ cif_r: u32, /* Clock interrupt flag regiseter. 0x1c */
+ cic_r: u32, /* Clock interrupt clear register. 0x20 */
+
+ reserved_2: u32, /* Not used. offset 0x24. */
+
+ ahb1rst_r: u32, /* AHB Peripheral 1 reset register. 0x28 */
+ ahb2rst_r: u32, /* AHB Peripheral 2 reset register. 0x2c */
+ ahb3rst_r: u32, /* AHB Peripheral 3 reset register. 0x30 */
+
+ reserved_3: u32, /* Not used. offset 0x34. */
+
+ // #define rcc_lptim1rst (1 << 31) // Low Power Timer 1 reset
+ // #define rcc_opamprst (1 << 30) // OPAMP interface reset
+ // #define rcc_dac1rst (1 << 29) // DAC1 interface reset
+ // #define rcc_pwrrst (1 << 28) // Power interface reset
+ // #define rcc_can2rst \
+ // (1 << 26) // CAN2 reset (this bit is reserved for STM32L47x/L48x devices)
+ // #define rcc_can1rst (1 << 25) // CAN1 reset
+ // #define rcc_crsrst \
+ // (1 << 24) // CRS reset (this bit is reserved for STM32L47x/L48x devices)
+ // #define rcc_i2c3rst (1 << 23) // I2C3 reset
+ // #define rcc_i2c2rst (1 << 22) // I2C2 reset
+ // #define rcc_i2c1rst (1 << 21) // I2C1 reset
+ // #define rcc_uart5rst (1 << 20) // UART5 reset
+ // #define rcc_uart4rst (1 << 19) // UART4 reset
+ // #define rcc_usart3rst (1 << 18) // USART3 reset
+ // #define rcc_usart2rst (1 << 17) // USART2 reset
+ // #define rcc_reserved (1 << 16) // must be kept at reset value.
+ // #define rcc_spi3rst (1 << 15) // SPI3 reset
+ // #define rcc_spi2rst (1 << 14) // SPI2 reset
+ // #define rcc_lcdrst \
+ // (1 << 9) // interface reset (this bit is reserved for STM32L471/L4x5 devices)
+ // #define rcc_tim7rst (1 << 5) // timer reset
+ // #define rcc_tim6rst (1 << 4) // timer reset
+ // #define rcc_tim5rst (1 << 3) // timer reset
+ // #define rcc_tim4rst (1 << 2) // timer reset
+ // #define rcc_tim3rst (1 << 1) // timer reset
+ // #define rcc_tim2rst (1 << 0) // timer reset
+ apb1rst1_r: u32, /* APB Peripheral reset register 1. 0x38 */
+ apb1rst2_r: u32, /* APB Peripheral reset register 2. 0x3C */
+ apb2rst_r: u32, /* APB Peripheral reset register. 0x40 */
+
+ reserved_4: u32, /* Not used. offset 0x44. */
+
+ // #define rcc_dma1en (1 << 0) /* DMA1 clock enable. */
+ // #define rcc_dma2en (1 << 1) /* DMA2 clock enable. */
+ // #define rcc_flashen (1 << 8) /* Flash memory interface clock enable. */
+ // #define rcc_crcen (1 << 12) /* CRC clock enable. */
+ // #define rcc_tscen (1 << 16) /* Touch sensing controller clock enable. */
+ // #define rcc_dmad2en (1 << 17) /* DMA2D clock enabled. */
+ ahb1en_r: u32, /* AHB1 Peripheral enable register. 0x48 */
+
+ // #define rcc_gpioen(port) (1 << (port))
+ // #define rcc_otgfsen (1 << 12)
+ // #define rcc_adcen (1 << 13)
+ // #define rcc_dcmien (1 << 14)
+ // #define rcc_assen (1 << 16)
+ // #define rcc_hashen (1 << 17)
+ // #define rcc_rngen (1 << 18)
+ ahb2en_r: u32, /* AHB2 Peripheral enable register. 0x4C */
+ ahb3en_r: u32, /* AHB3 Peripheral enable register. 0x50 */
+
+ reserved_5: u32, /* Not used. offset 0x54. */
+
+ // #define rcc_lptim1en (1 << 31) /* Low power timer 1 clock enable */
+ // #define rcc_opampen (1 << 30) /* OPAMP interface clock enable */
+ // #define rcc_dac1en (1 << 29) /* DAC1 interface clock enable */
+ // #define rcc_pwren (1 << 28) /* Power interface clock enable */
+ // #define rcc_can2en (1 << 26) /* CAN2 clock enable (this bit is reserved for STM32L47x/L48x devices) */
+ // #define rcc_can1en (1 << 25) /* CAN1 clock enable */
+ // #define rcc_crsen (1 << 24) /* Clock Recovery System clock enable (this bit is reserved for STM32L47x/L48x */
+ // #define rcc_i2c3en (1 << 23) /* I2C3 clock enable */
+ // #define rcc_i2c2en (1 << 22) /* I2C2 clock enable */
+ // #define rcc_i2c1en (1 << 21) /* I2C1 clock enable */
+ // #define rcc_uart5en (1 << 20) /* UART5 clock enable */
+ // #define rcc_uart4en (1 << 19) /* UART4 clock enable */
+ // #define rcc_usart3en (1 << 18) /* USART3 clock enable */
+ // #define rcc_usart2en (1 << 17) /* USART2 clock enable */
+ // #define rcc_spi3en (1 << 15) /* SPI3 clock enable */
+ // #define rcc_spi2en (1 << 14) /* SPI2 clock enable */
+ // #define rcc_wwdgen (1 << 11) /* Window watchdog clock enable */
+ // #define rcc_rtcapben (1 << 10) /* RTC APB clock enable (this bit is reserved for STM32L47x/L48x devices) */
+ // #define rcc_lcden (1 << 9) /* LCD clock enable (this bit is reserved for STM32L471/L4x5 devices) */
+ // #define rcc_tim7en (1 << 5) /* TIM7 timer clock enable */
+ // #define rcc_tim6en (1 << 4) /* TIM6 timer clock enable */
+ // #define rcc_tim5en (1 << 3) /* TIM5 timer clock enable */
+ // #define rcc_tim4en (1 << 2) /* TIM4 timer clock enable */
+ // #define rcc_tim3en (1 << 1) /* TIM3 timer clock enable */
+ // #define rcc_tim2en (1 << 0) /* TIM2 timer clock enable */
+ apb1en1_r: u32, /* APB1 Peripheral enable register 1. 0x58 */
+
+ // #define lptim2en (1 << 5) /*Low power timer 2 clock enable */
+ // #define swpmi1en (1 << 2) /* Single wire protocol clock enable */
+ // #define i2c4en (1 << 1) /* I2C4 clock enable (this bit is reserved for STM32L47x/L48x devices) */
+ // #define lpuart1en (1 << 0) /* Low power UART 1 clock enable */
+ apb1en2_r: u32, /* APB1 Peripheral enable register 2. 0x5C */
+
+ // #define rcc_syscfgen (1 << 0)
+ // #define rcc_fwen (1 << 7)
+ // #define rcc_sdmmc1en (1 << 10)
+ // #define rcc_tim1en (1 << 11)
+ // #define rcc_spi1en (1 << 12)
+ // #define rcc_tim8en (1 << 13)
+ // #define rcc_usart1en (1 << 14)
+ // #define rcc_tim15en (1 << 16)
+ // #define rcc_tim16en (1 << 17)
+ // #define rcc_tim17en (1 << 18)
+ // #define rcc_sai1en (1 << 21)
+ // #define rcc_sai2en (1 << 22)
+ // #define rcc_dfsdm1en (1 << 24)
+ apb2en_r: u32, /* APB2 Peripheral enable register. 0x60 */
+
+ reserved_6: u32, /* Not used. offset 0x64. */
+
+ ahb1smen_r: u32, /* 0x68 */
+ ahb2smen_r: u32, /* 0x6c */
+ ahb3smen_r: u32, /* 0x70 */
+
+ reserved_7: u32,
+
+ apb1smen_r1: u32, /* 0x78 */
+ apb1smen_r2: u32, /* 0x7c */
+ apb2smen_r: u32, /* 0x80 */
+
+ reserved_8: u32,
+
+ ccip_r: u32, /* 0x88 */
+}
+
+static RCC_BASE: u32 = 0x40021000;
+
+pub struct Rcc {
+ mem: *mut RccMem,
+}
+
+#[derive(Clone, Copy)]
+pub enum GpioPortN {
+ A = 0,
+ B = 1,
+}
+
+impl Rcc {
+ pub fn enable_gpio_port(self: &mut Rcc, port: GpioPortN) -> () {
+ unsafe {
+ regset(&mut (*self.mem).ahb2en_r, 1 << (port as u32), 1);
+ }
+ }
+}
+
+pub fn get_rcc() -> Rcc {
+ Rcc {
+ mem: RCC_BASE as *mut RccMem,
+ }
+}
diff --git a/src/hal/usart.rs b/src/hal/usart.rs
new file mode 100644
index 0000000..b60dd82
--- /dev/null
+++ b/src/hal/usart.rs
@@ -0,0 +1,16 @@
+#[repr(C)]
+struct Usart {
+ c_r1 : u32,
+ c_r2 : u32,
+ c_r3 : u32,
+
+ br_r : u32,
+ gtp_r : u32,
+ rto_r : u32,
+ rq_r : u32,
+
+ is_r : u32,
+ ic_r : u32,
+ rd_r : u32,
+ td_r : u32,
+}
diff --git a/src/main.rs b/src/main.rs
index 146f601..997e532 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,14 +2,37 @@
#![no_std]
use core::panic::PanicInfo;
+use hal::gpio::get_gpio_port_b;
+use crate::hal::gpio;
+
+mod hal;
mod init;
#[link_section = ".inits.999"]
#[no_mangle]
-pub static __MAIN: fn() -> () = main;
-pub fn main() -> () {
- loop {};
+pub static __MAIN: unsafe fn() -> () = main;
+pub unsafe fn main() -> () {
+ let mut pin = get_gpio_port_b().pin(3);
+ pin.set_mode(gpio::GpioMode::Output);
+ pin.set_output_type(gpio::GpioOutputType::PushPull);
+ pin.set_output_speed(gpio::GpioSpeed::Medium);
+ pin.set_pull_dir(gpio::GpioPullDir::Down);
+
+ pin.set_high();
+ loop {
+ delay();
+ pin.set_low();
+ delay();
+ pin.set_high();
+ }
+}
+
+fn delay() {
+ let mut cnt = 0;
+ while cnt < 10000 {
+ cnt += 1;
+ }
}
#[panic_handler]