diff options
| author | Ian McIntyre <ianpmcintyre@gmail.com> | 2023-03-13 06:50:57 -0400 |
|---|---|---|
| committer | Ian McIntyre <me@mciantyre.dev> | 2025-11-11 08:24:38 -0500 |
| commit | 6f5633761528e484e8d0963c7ac59403f7210093 (patch) | |
| tree | f0a5f5ac03cc0a477491332adbe33bb2278faa4a | |
| parent | 74d463340a87ff38a96c03a380bbed7c3ee56ba4 (diff) | |
Prototype API to build runtime in RAM
Just a proof-of-concept. The new inspect_elf test seems to show that
we're building the correct image. We need another commit in order to
help the program run in FlexRAM.
| -rw-r--r-- | board/Cargo.toml | 6 | ||||
| -rw-r--r-- | board/build.rs | 7 | ||||
| -rw-r--r-- | board/src/imxrt1010evk.rs | 2 | ||||
| -rw-r--r-- | board/src/lib.rs | 2 | ||||
| -rw-r--r-- | src/host.rs | 21 | ||||
| -rw-r--r-- | tests/inspect_elf.rs | 107 |
6 files changed, 143 insertions, 2 deletions
diff --git a/board/Cargo.toml b/board/Cargo.toml index 836230c..449b807 100644 --- a/board/Cargo.toml +++ b/board/Cargo.toml @@ -40,6 +40,12 @@ imxrt1010evk = [ "dep:rtt-target", "dep:panic-rtt-target", ] +imxrt1010evk-ram = [ + "imxrt-ral/imxrt1011", + # No FCB required. + "dep:rtt-target", + "dep:panic-rtt-target", +] imxrt1170evk-cm7 = [ "imxrt-ral/imxrt1176_cm7", "dep:imxrt1170evk-fcb", diff --git a/board/build.rs b/board/build.rs index 4531667..e44a11d 100644 --- a/board/build.rs +++ b/board/build.rs @@ -60,6 +60,13 @@ fn main() { .heap_size_env_override("BOARD_HEAP") .build() .unwrap(), + "imxrt1010evk_ram" => { + imxrt_rt::RuntimeBuilder::from_ram(imxrt_rt::Family::Imxrt1010) + .heap_size(1024) + .build() + .unwrap(); + println!("cargo:rustc-cfg=from_ram"); + } _ => continue, } break; diff --git a/board/src/imxrt1010evk.rs b/board/src/imxrt1010evk.rs index 9a596e9..9bcf120 100644 --- a/board/src/imxrt1010evk.rs +++ b/board/src/imxrt1010evk.rs @@ -2,7 +2,7 @@ use crate::ral; -#[cfg(target_arch = "arm")] +#[cfg(all(target_arch = "arm", not(feature = "imxrt1010evk-ram")))] use imxrt1010evk_fcb as _; #[cfg(target_arch = "arm")] use panic_rtt_target as _; diff --git a/board/src/lib.rs b/board/src/lib.rs index ebc76ad..f4912be 100644 --- a/board/src/lib.rs +++ b/board/src/lib.rs @@ -10,7 +10,7 @@ cfg_if::cfg_if! { mod teensy4; pub use teensy4::*; - } else if #[cfg(feature = "imxrt1010evk")] { + } else if #[cfg(any(feature = "imxrt1010evk", feature = "imxrt1010evk-ram"))] { mod shared { pub mod imxrt10xx; } use shared::imxrt10xx::prepare_pit; diff --git a/src/host.rs b/src/host.rs index 6a01f9d..56a9d0f 100644 --- a/src/host.rs +++ b/src/host.rs @@ -401,6 +401,27 @@ impl RuntimeBuilder { linker_script_name: DEFAULT_LINKER_SCRIPT_NAME.into(), } } + + /// Create a runtime that executes from RAM. + pub fn from_ram(family: Family) -> Self { + Self { + family, + flexram_banks: family.default_flexram_banks(), + text: Memory::Itcm, + rodata: Memory::Ocram, + data: Memory::Ocram, + vectors: Memory::Dtcm, + bss: Memory::Ocram, + uninit: Memory::Ocram, + stack: Memory::Dtcm, + stack_size: EnvOverride::new(8 * 1024), + heap: Memory::Dtcm, + heap_size: EnvOverride::new(0), + flash_opts: None, + linker_script_name: DEFAULT_LINKER_SCRIPT_NAME.into(), + } + } + /// Set the FlexRAM bank allocation. /// /// Use this to customize the sizes of DTCM, ITCM, and OCRAM. diff --git a/tests/inspect_elf.rs b/tests/inspect_elf.rs index f0ca005..9c20111 100644 --- a/tests/inspect_elf.rs +++ b/tests/inspect_elf.rs @@ -197,6 +197,8 @@ struct Section { size: u64, } +// No top-level constant for OCRAM, since placement varies +// across 1000 and 1100 MCUs. const DTCM: u64 = 0x2000_0000; const ITCM: u64 = 0x0000_0020; @@ -328,6 +330,111 @@ fn imxrt1010evk() { ); } +#[test] +#[ignore = "building an example can take time"] +fn imxrt1010evk_ram() { + let path = cargo_build("imxrt1010evk-ram").expect("Unable to build example"); + let contents = fs::read(path).expect("Could not read ELF file"); + let elf = Elf::parse(&contents).expect("Could not parse ELF"); + + let binary = ImxrtBinary::new(&elf, &contents); + + let stack = binary.section(".stack").unwrap(); + assert_eq!( + Section { + address: DTCM, + size: 8 * 1024 + }, + stack, + "stack not at ORIGIN(DTCM), or not 8 KiB large" + ); + assert_eq!(binary.section_lma(".stack"), stack.address); + + let vector_table = binary.section(".vector_table").unwrap(); + assert_eq!( + Section { + address: stack.address + stack.size, + size: 16 * 4 + 240 * 4 + }, + vector_table, + "vector table not at expected VMA behind the stack" + ); + assert!( + vector_table.address.is_multiple_of(1024), + "vector table is not 1024-byte aligned" + ); + assert_eq!( + binary.section_lma(".vector_table"), + stack.address + stack.size, + "vector_table LMA == VMA for RAM boot", + ); + + let xip = binary.section(".xip").unwrap(); + let text = binary.section(".text").unwrap(); + assert_eq!(text.address, aligned(ITCM + xip.size, 4), "text"); + assert_eq!( + binary.section_lma(".text"), + aligned(ITCM + xip.size, 4), + "text LMA == VMA for RAM boot" + ); + + let rodata = binary.section(".rodata").unwrap(); + assert_eq!(rodata.address, 0x2020_0000, "rodata VMA in OCRAM"); + assert_eq!( + rodata.address, + binary.section_lma(".rodata"), + "rodata LMA == VMA for RAM boot" + ); + + let data = binary.section(".data").unwrap(); + assert_eq!( + data.address, + rodata.address + aligned(rodata.size, 4), + "data VMA in OCRAM behind rodata" + ); + assert_eq!( + data.size, 4, + "blink-rtic expected to have a single static mut u32" + ); + assert_eq!( + binary.section_lma(".data"), + rodata.address + aligned(rodata.size, 4), + "data LMA == VMA for RAM boot" + ); + + let bss = binary.section(".bss").unwrap(); + assert_eq!( + bss.address, + data.address + aligned(data.size, 4), + "bss in OCRAM behind data" + ); + assert_eq!(binary.section_lma(".bss"), bss.address, "bss is NOLOAD"); + + let uninit = binary.section(".uninit").unwrap(); + assert_eq!( + uninit.address, + bss.address + aligned(bss.size, 4), + "uninit in OCRAM behind bss" + ); + assert_eq!( + binary.section_lma(".uninit"), + uninit.address, + "uninit is NOLOAD" + ); + + let heap = binary.section(".heap").unwrap(); + assert_eq!( + Section { + address: vector_table.address + vector_table.size, + size: 1024 + }, + heap, + "1 KiB heap in DTCM behind vector table" + ); + assert_eq!(heap.size, 1024); + assert_eq!(binary.section_lma(".heap"), heap.address, "Heap is NOLOAD"); +} + fn baseline_teensy4(binary: &ImxrtBinary, dcd_at_runtime: u32, stack_size: u64, heap_size: u64) { assert_eq!( Fcb { |
