itcm: add some comments, make it safe
This commit is contained in:
parent
441c81d135
commit
c5d3837745
|
@ -105,8 +105,17 @@ pub struct PounderDevices {
|
||||||
/// Static storage for the ethernet DMA descriptor ring.
|
/// Static storage for the ethernet DMA descriptor ring.
|
||||||
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
||||||
|
|
||||||
/// Setup ITCM and load its code from flash
|
/// Setup ITCM and load its code from flash.
|
||||||
unsafe fn setup_itcm() {
|
///
|
||||||
|
/// For portability and maintainability this is implemented in Rust.
|
||||||
|
/// Since this is implemented in Rust the compiler may assume that bss and data are set
|
||||||
|
/// up already. There is no easy way to ensure this implementation will never need bss
|
||||||
|
/// or data. Hence we can't safely run this as the cortex-m-rt `pre_init` hook before
|
||||||
|
/// bss/data is setup.
|
||||||
|
///
|
||||||
|
/// Calling (through IRQ or directly) any code in ITCM before having called
|
||||||
|
/// this method is undefined.
|
||||||
|
fn load_itcm() {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
static mut __sitcm: u32;
|
static mut __sitcm: u32;
|
||||||
static mut __eitcm: u32;
|
static mut __eitcm: u32;
|
||||||
|
@ -114,18 +123,29 @@ unsafe fn setup_itcm() {
|
||||||
}
|
}
|
||||||
use core::{ptr, slice, sync::atomic};
|
use core::{ptr, slice, sync::atomic};
|
||||||
|
|
||||||
// ITCM is enabled on reset on our CPU but might not be on others.
|
// NOTE(unsafe): Assuming the address symbols from the linker as well as
|
||||||
// Keep for completeness.
|
// the source instruction data are all valid, this is safe as it only
|
||||||
const ITCMCR: *mut u32 = 0xE000_EF90usize as _;
|
// copies linker-prepared data to where the code expects it to be.
|
||||||
ptr::write_volatile(ITCMCR, ptr::read_volatile(ITCMCR) | 1);
|
// Calling it multiple times is safe as well.
|
||||||
atomic::fence(atomic::Ordering::SeqCst);
|
|
||||||
|
|
||||||
let len =
|
unsafe {
|
||||||
(&__eitcm as *const u32).offset_from(&__sitcm as *const _) as usize;
|
// ITCM is enabled on reset on our CPU but might not be on others.
|
||||||
let dst = slice::from_raw_parts_mut(&mut __sitcm as *mut _, len);
|
// Keep for completeness.
|
||||||
let src = slice::from_raw_parts(&__siitcm as *const _, len);
|
const ITCMCR: *mut u32 = 0xE000_EF90usize as _;
|
||||||
dst.copy_from_slice(src);
|
ptr::write_volatile(ITCMCR, ptr::read_volatile(ITCMCR) | 1);
|
||||||
|
|
||||||
|
// Ensure ITCM is enabled before loading.
|
||||||
|
atomic::fence(atomic::Ordering::SeqCst);
|
||||||
|
|
||||||
|
let len =
|
||||||
|
(&__eitcm as *const u32).offset_from(&__sitcm as *const _) as usize;
|
||||||
|
let dst = slice::from_raw_parts_mut(&mut __sitcm as *mut _, len);
|
||||||
|
let src = slice::from_raw_parts(&__siitcm as *const _, len);
|
||||||
|
// Load code into ITCM.
|
||||||
|
dst.copy_from_slice(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure ITCM is loaded before potentially executing any instructions from it.
|
||||||
atomic::fence(atomic::Ordering::SeqCst);
|
atomic::fence(atomic::Ordering::SeqCst);
|
||||||
cortex_m::asm::dsb();
|
cortex_m::asm::dsb();
|
||||||
cortex_m::asm::isb();
|
cortex_m::asm::isb();
|
||||||
|
@ -183,12 +203,12 @@ pub fn setup(
|
||||||
log::set_logger(&LOGGER)
|
log::set_logger(&LOGGER)
|
||||||
.map(|()| log::set_max_level(log::LevelFilter::Trace))
|
.map(|()| log::set_max_level(log::LevelFilter::Trace))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
log::info!("starting...");
|
log::info!("Starting");
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
// Before being able to call any code in ITCM, load that code from flash.
|
||||||
setup_itcm();
|
log::info!("Loading ITCM");
|
||||||
}
|
load_itcm();
|
||||||
|
|
||||||
// Set up the system timer for RTIC scheduling.
|
// Set up the system timer for RTIC scheduling.
|
||||||
{
|
{
|
||||||
|
@ -902,6 +922,7 @@ pub fn setup(
|
||||||
|
|
||||||
#[cfg(feature = "pounder_v1_1")]
|
#[cfg(feature = "pounder_v1_1")]
|
||||||
let pounder_stamper = {
|
let pounder_stamper = {
|
||||||
|
logger::info!("Pounder v1.1 or later");
|
||||||
let etr_pin = gpioa.pa0.into_alternate_af3();
|
let etr_pin = gpioa.pa0.into_alternate_af3();
|
||||||
|
|
||||||
// The frequency in the constructor is dont-care, as we will modify the period + clock
|
// The frequency in the constructor is dont-care, as we will modify the period + clock
|
||||||
|
|
Loading…
Reference in New Issue