aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan McIntyre <me@mciantyre.dev>2025-03-12 21:50:39 -0400
committerIan McIntyre <me@mciantyre.dev>2025-03-13 20:14:25 -0400
commit4ecbed698241e637a13048a199d29c142445c360 (patch)
tree5bafdd61d301a8222f00b37a9ffa00f9bff76c6a
parent49385f56eab2dcdbe89cd156ba4e8be95b14e99e (diff)
Place .xip sections into flash
We added the `.xip` section to ensure that the reset handler and pre-init functions would be placed in flash. This commit lets users place other content into that section. `.xip` is intended for instructions. The runtime builder will place these instructions into the same load region as `.text`. However, there's no pre-`main` relocation. Aligning the `.xip` and the `.text` section produces more predictable behavior between GNU's ld and LLVM's lld.
-rw-r--r--CHANGELOG.md6
-rw-r--r--examples/blink-rtic.rs9
-rw-r--r--src/host/imxrt-link.x5
-rw-r--r--tests/inspect_elf.rs37
4 files changed, 46 insertions, 11 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd6fb98..2920663 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
## [Unreleased]
+Place sections starting with `.xip` into the same load region of `.text`.
+Unlike `.text`, the contents in `.xip` will not be relocated.
+
+Four byte align both the `.xip` and `.text` sections for more predictable
+behaviors across linkers.
+
## [0.1.6] 2025-03-01
Add new MCU targets:
diff --git a/examples/blink-rtic.rs b/examples/blink-rtic.rs
index 04446e3..e463f33 100644
--- a/examples/blink-rtic.rs
+++ b/examples/blink-rtic.rs
@@ -12,6 +12,13 @@ use imxrt_rt as _;
/// This is checked in an automated test.
static mut DATA: u32 = 5;
+#[unsafe(link_section = ".xip")]
+#[unsafe(no_mangle)]
+#[inline(never)]
+fn increment_data() {
+ unsafe { crate::DATA = crate::DATA.wrapping_add(1) };
+}
+
#[rtic::app(device = board::rtic_support, peripherals = false)]
mod app {
const PIT_PERIOD_US: u32 = 1_000_000;
@@ -35,7 +42,7 @@ mod app {
#[task(binds = PIT, local = [led, pit])]
fn pit(cx: pit::Context) {
- unsafe { crate::DATA += 1 };
+ crate::increment_data();
cx.local.led.toggle();
cx.local.pit.clear_interrupts();
}
diff --git a/src/host/imxrt-link.x b/src/host/imxrt-link.x
index a389325..dfe7355 100644
--- a/src/host/imxrt-link.x
+++ b/src/host/imxrt-link.x
@@ -70,14 +70,15 @@ SECTIONS
__sivector_table = LOADADDR(.vector_table);
/* This section guarantees VMA = LMA to allow the execute-in-place entry point to be inside the image. */
- .xip :
+ .xip : ALIGN(4)
{
/* Included here if not otherwise included in the boot header. */
*(.Reset);
*(.__pre_init);
+ *(.xip .xip.*);
} > REGION_LOAD_TEXT
- .text :
+ .text : ALIGN(4)
{
FILL(0xff);
__stext = .;
diff --git a/tests/inspect_elf.rs b/tests/inspect_elf.rs
index cdb3245..e9211eb 100644
--- a/tests/inspect_elf.rs
+++ b/tests/inspect_elf.rs
@@ -239,18 +239,19 @@ fn imxrt1010evk() {
);
assert_eq!(binary.section_lma(".vector_table"), 0x6000_2000);
+ let xip = binary.section(".xip").unwrap();
let text = binary.section(".text").unwrap();
assert_eq!(text.address, ITCM, "text");
assert_eq!(
binary.section_lma(".text"),
- 0x6000_2000 + vector_table.size,
+ aligned(0x6000_2000 + vector_table.size + xip.size, 4),
"text VMA expected behind vector table"
);
let rodata = binary.section(".rodata").unwrap();
assert_eq!(
rodata.address,
- 0x6000_2000 + vector_table.size + aligned(text.size, 4),
+ aligned(0x6000_2000 + vector_table.size + text.size + xip.size, 4),
"rodata LMA & VMA expected behind text"
);
assert_eq!(rodata.address, binary.section_lma(".rodata"));
@@ -298,6 +299,12 @@ fn imxrt1010evk() {
);
assert_eq!(heap.size, 1024);
assert_eq!(binary.section_lma(".heap"), heap.address, "Heap is NOLOAD");
+
+ let increment_data_xip = binary.symbol_value("increment_data").unwrap();
+ assert!(
+ 0x6000_0000 < increment_data_xip && increment_data_xip < 0x7000_0000,
+ "increment_data is not XiP"
+ );
}
fn baseline_teensy4(binary: &ImxrtBinary, dcd_at_runtime: u32, stack_size: u64, heap_size: u64) {
@@ -334,6 +341,7 @@ fn baseline_teensy4(binary: &ImxrtBinary, dcd_at_runtime: u32, stack_size: u64,
assert_eq!(binary.section_lma(".stack"), stack.address);
let vector_table = binary.section(".vector_table").unwrap();
+ let xip = binary.section(".xip").unwrap();
assert_eq!(
Section {
address: stack.address + stack.size,
@@ -349,14 +357,14 @@ fn baseline_teensy4(binary: &ImxrtBinary, dcd_at_runtime: u32, stack_size: u64,
assert_eq!(binary.section_lma(".vector_table"), 0x6000_2000);
let text = binary.section(".text").unwrap();
- assert_eq!(
- text.address,
- binary.section_lma(".vector_table") + vector_table.size,
- "text"
+ let expected_text_address = aligned(
+ binary.section_lma(".vector_table") + vector_table.size + xip.size,
+ 4,
);
+ assert_eq!(text.address, expected_text_address, "text");
assert_eq!(
binary.section_lma(".text"),
- 0x6000_2000 + vector_table.size,
+ aligned(0x6000_2000 + vector_table.size + xip.size, 4),
"text VMA expected behind vector table"
);
@@ -414,6 +422,12 @@ fn baseline_teensy4(binary: &ImxrtBinary, dcd_at_runtime: u32, stack_size: u64,
"{heap_size} byte heap in DTCM behind uninit"
);
assert_eq!(binary.section_lma(".heap"), heap.address, "Heap is NOLOAD");
+
+ let increment_data_xip = binary.symbol_value("increment_data").unwrap();
+ assert!(
+ 0x6000_0000 < increment_data_xip && increment_data_xip < 0x7000_0000,
+ "increment_data is not XiP"
+ );
}
#[test]
@@ -562,11 +576,12 @@ fn imxrt1170evk_cm7() {
);
assert_eq!(binary.section_lma(".vector_table"), 0x3000_2000);
+ let xip = binary.section(".xip").unwrap();
let text = binary.section(".text").unwrap();
assert_eq!(text.address, ITCM, "text");
assert_eq!(
binary.section_lma(".text"),
- 0x3000_2000 + vector_table.size,
+ aligned(0x3000_2000 + vector_table.size + xip.size, 4),
"text VMA expected behind vector table"
);
@@ -622,4 +637,10 @@ fn imxrt1170evk_cm7() {
"0 byte heap in DTCM behind rodata table"
);
assert_eq!(binary.section_lma(".heap"), heap.address, "Heap is NOLOAD");
+
+ let increment_data_xip = binary.symbol_value("increment_data").unwrap();
+ assert!(
+ 0x3000_0000 < increment_data_xip && increment_data_xip < 0x4000_0000,
+ "increment_data is not XiP"
+ );
}