322: rj/itcm r=jordens a=jordens

* close #315
* would profit from cortex-m-rtic 0.6 elevating the attributes to the actual ISR thus removing the veneer

Co-authored-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
bors[bot] 2021-05-28 14:34:28 +00:00 committed by GitHub
commit 9587088de2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 88 additions and 23 deletions

15
Cargo.lock generated
View File

@ -145,18 +145,15 @@ dependencies = [
[[package]] [[package]]
name = "cortex-m-rt" name = "cortex-m-rt"
version = "0.6.13" version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/rust-embedded/cortex-m-rt.git?rev=a2e3ad5#a2e3ad54478c6b98e519a1b0946395d790c0b6c7"
checksum = "980c9d0233a909f355ed297ef122f257942de5e0a2cb1c39f60684b65bcb90fb"
dependencies = [ dependencies = [
"cortex-m-rt-macros", "cortex-m-rt-macros",
"r0",
] ]
[[package]] [[package]]
name = "cortex-m-rt-macros" name = "cortex-m-rt-macros"
version = "0.1.8" version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/rust-embedded/cortex-m-rt.git?rev=a2e3ad5#a2e3ad54478c6b98e519a1b0946395d790c0b6c7"
checksum = "4717562afbba06e760d34451919f5c3bf3ac15c7bb897e8b04862a7428378647"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -588,12 +585,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "r0"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.3" version = "0.8.3"

View File

@ -46,10 +46,12 @@ miniconf = "0.1.0"
shared-bus = {version = "0.2.2", features = ["cortex-m"] } shared-bus = {version = "0.2.2", features = ["cortex-m"] }
serde-json-core = "0.3" serde-json-core = "0.3"
# rtt-target bump
[dependencies.rtt-logger] [dependencies.rtt-logger]
git = "https://github.com/quartiq/rtt-logger.git" git = "https://github.com/quartiq/rtt-logger.git"
rev = "70b0eb5" rev = "70b0eb5"
# rewrite
[dependencies.mcp23017] [dependencies.mcp23017]
git = "https://github.com/lucazulian/mcp23017.git" git = "https://github.com/lucazulian/mcp23017.git"
rev = "523d71d" rev = "523d71d"
@ -58,6 +60,11 @@ rev = "523d71d"
features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"] features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"]
version = "0.9.0" 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] [patch.crates-io.miniconf]
git = "https://github.com/quartiq/miniconf.git" git = "https://github.com/quartiq/miniconf.git"
rev = "c6f2b28" rev = "c6f2b28"

3
build.rs Normal file
View File

@ -0,0 +1,3 @@
fn main() {
println!("cargo:rerun-if-changed=memory.x");
}

View File

@ -13,10 +13,6 @@ MEMORY
} }
SECTIONS { SECTIONS {
.itcm : ALIGN(8) {
*(.itcm .itcm.*);
. = ALIGN(8);
} > ITCM
.axisram (NOLOAD) : ALIGN(8) { .axisram (NOLOAD) : ALIGN(8) {
*(.axisram .axisram.*); *(.axisram .axisram.*);
. = ALIGN(8); . = ALIGN(8);
@ -33,4 +29,18 @@ SECTIONS {
*(.sram3 .sram3.*); *(.sram3 .sram3.*);
. = ALIGN(4); . = ALIGN(4);
} > SRAM3 } > 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");

View File

@ -120,6 +120,8 @@ const APP: () = {
/// Because the ADC and DAC operate at the same rate, these two constraints actually implement /// 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. /// 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)] #[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) { fn process(c: process::Context) {
let adc_samples = [ let adc_samples = [
c.resources.adcs.0.acquire_buffer(), c.resources.adcs.0.acquire_buffer(),

View File

@ -157,6 +157,8 @@ const APP: () = {
/// It outputs either I/Q or power/phase on DAC0/DAC1. Data is normalized to full scale. /// 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. /// 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)] #[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) { fn process(c: process::Context) {
let adc_samples = [ let adc_samples = [
c.resources.adcs.0.acquire_buffer(), c.resources.adcs.0.acquire_buffer(),

View File

@ -105,6 +105,52 @@ 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.
///
/// 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);
cortex_m::asm::dsb();
cortex_m::asm::isb();
}
/// Configure the stabilizer hardware for operation. /// Configure the stabilizer hardware for operation.
/// ///
/// # Args /// # Args
@ -157,9 +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");
} }
// Before being able to call any code in ITCM, load that code from flash.
load_itcm();
// Set up the system timer for RTIC scheduling. // Set up the system timer for RTIC scheduling.
{ {
let tim15 = let tim15 =
@ -872,6 +921,7 @@ pub fn setup(
#[cfg(feature = "pounder_v1_1")] #[cfg(feature = "pounder_v1_1")]
let pounder_stamper = { let pounder_stamper = {
log::info!("Assuming 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
@ -934,13 +984,13 @@ pub fn setup(
digital_inputs, digital_inputs,
}; };
// Enable the instruction cache.
core.SCB.enable_icache();
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap()); // info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
// info!("Built on {}", build_info::BUILT_TIME_UTC); // info!("Built on {}", build_info::BUILT_TIME_UTC);
// info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET); // info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET);
log::info!("setup() complete"); log::info!("setup() complete");
// Enable the instruction cache.
core.SCB.enable_icache();
(stabilizer, pounder) (stabilizer, pounder)
} }

View File

@ -90,11 +90,11 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
} }
#[cortex_m_rt::exception] #[cortex_m_rt::exception]
fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! { unsafe fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef); panic!("HardFault at {:#?}", ef);
} }
#[cortex_m_rt::exception] #[cortex_m_rt::exception]
fn DefaultHandler(irqn: i16) { unsafe fn DefaultHandler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn); panic!("Unhandled exception (IRQn = {})", irqn);
} }