diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hal/clock.rs | 10 | ||||
-rw-r--r-- | src/hal/common.rs | 25 | ||||
-rw-r--r-- | src/hal/gpio.rs | 148 | ||||
-rw-r--r-- | src/hal/mod.rs | 4 | ||||
-rw-r--r-- | src/hal/rcc.rs | 167 | ||||
-rw-r--r-- | src/hal/usart.rs | 16 | ||||
-rw-r--r-- | src/main.rs | 29 |
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] |