/src/peripherals.rs
use cortex_m::peripheral::MPU;
use atsam3xa_hal::prelude::*;
use crate::console::Console;
use crate::console::serial::SerialTerminal;
use crate::mpu::{self, MemoryRegion, MemoryPermission};
use crate::timer;
use crate::video;
pub struct Peripherals {
pub led: atsam3xa_hal::pio::Pin,
pub watchdog: atsam3xa_hal::watchdog::WDT,
}
impl Peripherals {
pub fn new() -> Peripherals {
let mut mp = cortex_m::peripheral::Peripherals::take().unwrap();
let pp = atsam3xa::Peripherals::take().unwrap();
// Initialize flash wait states
pp.EFC0.constrain().set_wait_states(4);
pp.EFC1.constrain().set_wait_states(4);
// Initialize clocks
let pmc = pp.PMC.constrain();
pmc.init_clocks();
pmc.enable_peripheral_clock(PeripheralID::PIOB);
pmc.enable_peripheral_clock(PeripheralID::UART);
let pio_a = pp.PIOA.constrain();
let pio_b = pp.PIOB.constrain();
let led = pio_b.get_pin(27);
led.output_mode();
let uart = pp.UART.constrain(&pio_a, 115200, ParityType::NO);
mp.NVIC.enable(atsam3xa::Interrupt::UART);
unsafe { mp.NVIC.set_priority(atsam3xa::Interrupt::UART, 7 << 4) };
uart.enable_interrupts();
Console::new(SerialTerminal::new(uart));
let watchdog = pp.WDT.constrain();
Self::mpu_setup(mp.MPU);
timer::start(atsam3xa_hal::timer::Timer::syst(mp.SYST));
// Only enable video gen on release - debug mode code is too slow
#[cfg(release)]
video::gen::start(pp.TC0, &mut mp.NVIC, &pmc, &pio_b);
Peripherals {
led,
watchdog,
}
}
pub fn mpu_setup(mpu: MPU) {
mpu::init(mpu);
mpu::add_regions(&[
// ROM
MemoryRegion {
start: 0x00000000,
length: 0x20000000,
permissions: MemoryPermission::RO,
xn: false,
},
// Peripherals
MemoryRegion {
start: 0x40000000,
length: 0x20000000,
permissions: MemoryPermission::RW,
xn: true,
},
// KGRAM
MemoryRegion {
start: 0x20080000,
length: 0x4000,
permissions: MemoryPermission::RW,
xn: true,
},
]);
// Enable MPU
mpu::enable();
}
}