Select Git revision
openocd.gdb
bare5.rs 8.23 KiB
//! bare4.rs
//! Simple bare metal application
//!
#![feature(used)]
#![feature(custom_attribute)]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rt;
// #[macro_use]
// extern crate cortex_m_debug;
mod stm32f40x {
use core::{cell, ptr};
// C like API...
const PERIPH_BASE: u32 = 0x40000000;
const AHB1PERIPH_BASE: u32 = PERIPH_BASE + 0x00020000;
const RCC_BASE: u32 = AHB1PERIPH_BASE + 0x3800;
const GPIOA_BASE: u32 = AHB1PERIPH_BASE;
pub struct VolatileCell<T> {
value: cell::UnsafeCell<T>,
}
impl<T> VolatileCell<T> {
#[inline(always)]
pub fn read(&self) -> T
where
T: Copy,
{
unsafe { ptr::read_volatile(self.value.get()) }
}
#[inline(always)]
pub fn write(&self, value: T)
where
T: Copy,
{
unsafe { ptr::write_volatile(self.value.get(), value) }
}
}
#[repr(C)]
#[allow(non_snake_case)]
#[rustfmt_skip]
pub struct RCC {
pub CR: VolatileCell<u32>, // < RCC clock control register, Address offset: 0x00 */
pub PLLCFGR: VolatileCell<u32>, // < RCC PLL configuration register, Address offset: 0x04 */
pub CFGR: VolatileCell<u32>, // < RCC clock configuration register, Address offset: 0x08 */
pub CIR: VolatileCell<u32>, // < RCC clock interrupt register, Address offset: 0x0C */
pub AHB1RSTR: VolatileCell<u32>, // < RCC AHB1 peripheral reset register, Address offset: 0x10 */
pub AHB2RSTR: VolatileCell<u32>, // < RCC AHB2 peripheral reset register, Address offset: 0x14 */
pub AHB3RSTR: VolatileCell<u32>, // < RCC AHB3 peripheral reset register, Address offset: 0x18 */
pub RESERVED0: VolatileCell<u32>, // < Reserved, 0x1C */
pub APB1RSTR: VolatileCell<u32>, // < RCC APB1 peripheral reset register, Address offset: 0x20 */
pub APB2RSTR: VolatileCell<u32>, // < RCC APB2 peripheral reset register, Address offset: 0x24 */
pub RESERVED1: [VolatileCell<u32>; 2], // < Reserved, 0x28-0x2C */
pub AHB1ENR: VolatileCell<u32>, // < RCC AHB1 peripheral clock register, Address offset: 0x30 */
pub AHB2ENR: VolatileCell<u32>, // < RCC AHB2 peripheral clock register, Address offset: 0x34 */
pub AHB3ENR: VolatileCell<u32>, // < RCC AHB3 peripheral clock register, Address offset: 0x38 */
pub RESERVED2: VolatileCell<u32>, // < Reserved, 0x3C */
pub APB1ENR: VolatileCell<u32>, // < RCC APB1 peripheral clock enable register, Address offset: 0x40 */
pub APB2ENR: VolatileCell<u32>, // < RCC APB2 peripheral clock enable register, Address offset: 0x44 */
pub RESERVED3: [VolatileCell<u32>; 2], // < Reserved, 0x48-0x4C */
pub AHB1LPENR: VolatileCell<u32>, // < RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */
pub AHB2LPENR: VolatileCell<u32>, // < RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */
pub AHB3LPENR: VolatileCell<u32>, // < RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */
pub RESERVED4: VolatileCell<u32>, // < Reserved, 0x5C */
pub APB1LPENR: VolatileCell<u32>, // < RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */
pub APB2LPENR: VolatileCell<u32>, // < RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */
pub RESERVED5: [VolatileCell<u32>; 2], // < Reserved, 0x68-0x6C */
pub BDCR: VolatileCell<u32>, // < RCC Backup domain control register, Address offset: 0x70 */
pub CSR: VolatileCell<u32>, // < RCC clock control & status register, Address offset: 0x74 */
pub RESERVED6: [VolatileCell<u32>; 2], // < Reserved, 0x78-0x7C */
pub SSCGR: VolatileCell<u32>, // < RCC spread spectrum clock generation register, Address offset: 0x80 */
pub PLLI2SCFGR: VolatileCell<u32>, // < RCC PLLI2S configuration register, Address offset: 0x84 */
}
impl RCC {
pub fn get() -> *mut RCC {
RCC_BASE as *mut RCC
}
}
#[repr(C)]
#[allow(non_snake_case)]
#[rustfmt_skip]
pub struct GPIOA {
pub OTYPER: VolatileCell<u32>, // < GPIO port output type register, Address offset: 0x04 */
pub OSPEEDR: VolatileCell<u32>, // < GPIO port output speed register, Address offset: 0x08 */
pub PUPDR: VolatileCell<u32>, // < GPIO port pull-up/pull-down register, Address offset: 0x0C */
pub MODER: VolatileCell<u32>, // < GPIO port mode register, Address offset: 0x00 */
pub IDR: VolatileCell<u32>, // < GPIO port input data register, Address offset: 0x10 */
pub ODR: VolatileCell<u32>, // < GPIO port output data register, Address offset: 0x14 */
pub BSRRL: VolatileCell<u16>, // < GPIO port bit set/reset low register, Address offset: 0x18 */
pub BSRRH: VolatileCell<u16>, // < GPIO port bit set/reset high register, Address offset: 0x1A */
pub LCKR: VolatileCell<u32>, // < GPIO port configuration lock register, Address offset: 0x1C */
pub AFR: [VolatileCell<u32>], // < GPIO alternate function registers, Address offset: 0x20-0x24 */
}
// impl GPIOA {
// pub fn get() -> *mut GPIOA {
// GPIOA_BASE as *mut GPIOA
// }
// }
impl GPIOA {
pub fn get() -> *mut GPIOA {
GPIOA_BASE as *mut GPIOA
}
}
}
use stm32f40x::*;
// see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
// rcc, chapter 6
// gpio, chapter 8
fn wait(i: u32) {
for _ in 0..i {
cortex_m::asm::nop(); // no operation (cannot be optimized out)
}
}
fn main() {
// // power on GPIOA, RM0368 6.3.11
// p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
let rcc = RCC::get(); // get the reference to the Rcc in memory
unsafe {
let r = (*rcc).AHB1ENR.read(); // read
(*rcc).AHB1ENR.write(r | 1 << (0)); // set enable
}
// configure PA5 as output, RM0368 8.4.1
// let gpioa = GPIOA::get();
// unsafe {
// let r = (*gpioa).MODER.read() & !(0b11 << (5 * 2)); // read and mask
// (*gpioa).MODER.write(r | 0b01 << (5 * 2)); // set output mode
// // and alter the data output through the BSRR register
// // this is more efficient as the read register (in modify)
// // is not needed.
// loop {
// // set PA5 high, RM0368 8.4.7
// (*gpioa).BSRRH.write(1 << 5); // set bit, output hight (turn on led)
// wait(10_000);
// // set PA5 low, RM0368 8.4.7
// (*gpioa).BSRRH.write(1 << 5); // clear bit, output low (turn off led)
// wait(10_000);
// }
// }
}
// As we are not using interrupts, we just register a dummy catch all handler
#[link_section = ".vector_table.interrupts"]
#[used]
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
extern "C" fn default_handler() {
cortex_m::asm::bkpt();
}