Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rj/itcm #322

Merged
merged 18 commits into from
May 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ miniconf = "0.1.0"
shared-bus = {version = "0.2.2", features = ["cortex-m"] }
serde-json-core = "0.3"

# rtt-target bump
[dependencies.rtt-logger]
git = "https://github.com/quartiq/rtt-logger.git"
rev = "70b0eb5"

# rewrite
[dependencies.mcp23017]
git = "https://github.com/lucazulian/mcp23017.git"
rev = "523d71d"
Expand All @@ -58,6 +60,11 @@ rev = "523d71d"
features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"]
version = "0.9.0"

# link.x section start/end
[patch.crates-io.cortex-m-rt]
git = "https://github.com/rust-embedded/cortex-m-rt.git"
rev = "a2e3ad5"

[patch.crates-io.miniconf]
git = "https://github.com/quartiq/miniconf.git"
rev = "c6f2b28"
Expand Down
3 changes: 3 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("cargo:rerun-if-changed=memory.x");
}
20 changes: 15 additions & 5 deletions memory.x
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ MEMORY
}

SECTIONS {
.itcm : ALIGN(8) {
*(.itcm .itcm.*);
. = ALIGN(8);
} > ITCM
.axisram (NOLOAD) : ALIGN(8) {
*(.axisram .axisram.*);
. = ALIGN(8);
Expand All @@ -33,4 +29,18 @@ SECTIONS {
*(.sram3 .sram3.*);
. = ALIGN(4);
} > SRAM3
} INSERT AFTER .bss;
.itcm : ALIGN(8) {
. = ALIGN(8);
__sitcm = .;
*(.itcm .itcm.*);
. = ALIGN(8);
__eitcm = .;
} > ITCM AT>FLASH
__siitcm = LOADADDR(.itcm);
} INSERT AFTER .uninit;

ASSERT(__sitcm % 8 == 0 && __eitcm % 8 == 0, "
BUG(cortex-m-rt): .itcm is not 8-byte aligned");

ASSERT(__siitcm % 4 == 0, "
BUG(cortex-m-rt): the LMA of .itcm is not 4-byte aligned");
2 changes: 2 additions & 0 deletions src/bin/dual-iir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ const APP: () = {
/// Because the ADC and DAC operate at the same rate, these two constraints actually implement
/// the same time bounds, meeting one also means the other is also met.
#[task(binds=DMA1_STR4, resources=[adcs, digital_inputs, dacs, iir_state, settings, telemetry], priority=2)]
#[inline(never)]
#[link_section = ".itcm.process"]
fn process(c: process::Context) {
let adc_samples = [
c.resources.adcs.0.acquire_buffer(),
Expand Down
2 changes: 2 additions & 0 deletions src/bin/lockin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ const APP: () = {
/// It outputs either I/Q or power/phase on DAC0/DAC1. Data is normalized to full scale.
/// PLL bandwidth, filter bandwidth, slope, and x/y or power/phase post-filters are available.
#[task(binds=DMA1_STR4, resources=[adcs, dacs, lockin, timestamper, pll, settings, telemetry], priority=2)]
#[inline(never)]
#[link_section = ".itcm.process"]
fn process(c: process::Context) {
let adc_samples = [
c.resources.adcs.0.acquire_buffer(),
Expand Down
58 changes: 54 additions & 4 deletions src/hardware/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,52 @@ pub struct PounderDevices {
/// Static storage for the ethernet DMA descriptor ring.
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();

/// Setup ITCM and load its code from flash.
///
/// 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" {
static mut __sitcm: u32;
static mut __eitcm: u32;
static mut __siitcm: u32;
}
use core::{ptr, slice, sync::atomic};

// NOTE(unsafe): Assuming the address symbols from the linker as well as
// the source instruction data are all valid, this is safe as it only
// copies linker-prepared data to where the code expects it to be.
// Calling it multiple times is safe as well.

unsafe {
// ITCM is enabled on reset on our CPU but might not be on others.
// Keep for completeness.
const ITCMCR: *mut u32 = 0xE000_EF90usize as _;
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);
jordens marked this conversation as resolved.
Show resolved Hide resolved
cortex_m::asm::dsb();
cortex_m::asm::isb();
}

/// Configure the stabilizer hardware for operation.
///
/// # Args
Expand Down Expand Up @@ -157,9 +203,12 @@ pub fn setup(
log::set_logger(&LOGGER)
.map(|()| log::set_max_level(log::LevelFilter::Trace))
.unwrap();
log::info!("starting...");
log::info!("Starting");
}

// Before being able to call any code in ITCM, load that code from flash.
load_itcm();

// Set up the system timer for RTIC scheduling.
{
let tim15 =
Expand Down Expand Up @@ -872,6 +921,7 @@ pub fn setup(

#[cfg(feature = "pounder_v1_1")]
let pounder_stamper = {
log::info!("Assuming Pounder v1.1 or later");
let etr_pin = gpioa.pa0.into_alternate_af3();

// The frequency in the constructor is dont-care, as we will modify the period + clock
Expand Down Expand Up @@ -934,13 +984,13 @@ pub fn setup(
digital_inputs,
};

// Enable the instruction cache.
core.SCB.enable_icache();

// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
// info!("Built on {}", build_info::BUILT_TIME_UTC);
// info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET);
log::info!("setup() complete");

// Enable the instruction cache.
core.SCB.enable_icache();

(stabilizer, pounder)
}
4 changes: 2 additions & 2 deletions src/hardware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
}

#[cortex_m_rt::exception]
fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
unsafe fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}

#[cortex_m_rt::exception]
fn DefaultHandler(irqn: i16) {
unsafe fn DefaultHandler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}