Select Git revision
Forked from
Per Lindgren / D7050E
Source project has a limited visibility.
bare4.rs 1.98 KiB
//! bare4.rs
//! Simple bare metal application
//!
#![feature(used)]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rt;
// Peripheral addresses as constants
const PERIPH_BASE: u32 = 0x40000000;
const AHB1PERIPH_BASE: u32 = PERIPH_BASE + 0x00020000;
const RCC_BASE: u32 = AHB1PERIPH_BASE + 0x3800;
const RCC_AHB1ENR: u32 = RCC_BASE + 0x30;
const GBPIA_BASE: u32 = AHB1PERIPH_BASE + 0x0000;
const GPIOA_MODER: u32 = GBPIA_BASE + 0x00;
const GPIOA_BSRR: u32 = GBPIA_BASE + 0x18;
// see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
// rcc, chapter 6
// gpio, chapter 8
#[inline(always)]
fn read_u32(addr: u32) -> u32 {
unsafe { core::ptr::read_volatile(addr as *const _) }
}
#[inline(always)]
fn write_u32(addr: u32, val: u32) {
unsafe {
core::ptr::write_volatile(addr as *mut _, val);
}
}
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
let r = read_u32(RCC_AHB1ENR); // read
write_u32(RCC_AHB1ENR, r | 1); // set enable
// configure PA5 as output, RM0368 8.4.1
let r = read_u32(GPIOA_MODER) & !(0b11 << (5 * 2)); // read and mask
write_u32(GPIOA_MODER, 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
write_u32(GPIOA_BSRR, 1 << 5); // set bit, output hight (turn on led)
wait(10_000);
// set PA5 low, RM0368 8.4.7
write_u32(GPIOA_BSRR, 1 << (5 + 16)); // 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();
}