aboutsummaryrefslogtreecommitdiff
path: root/src/host.rs
diff options
context:
space:
mode:
authorSherif A Abdou <sherif_abdou@outlook.com>2025-02-03 10:22:32 -0500
committerIan McIntyre <me@mciantyre.dev>2025-03-21 20:04:24 -0400
commitb319d62052d6b553b135837ff8c35ee0c8d475bf (patch)
tree5f8d7a6ce24bd868d58dd2396caed1f3532c3316 /src/host.rs
parent4ecbed698241e637a13048a199d29c142445c360 (diff)
Added in_flash RuntimeBuilder constructor
Applications linked through this builder can be placed in a flash reservation. You'll need some other software to launch these programs, since they lack the boot header required by the NXP boot ROM.
Diffstat (limited to 'src/host.rs')
-rw-r--r--src/host.rs103
1 files changed, 86 insertions, 17 deletions
diff --git a/src/host.rs b/src/host.rs
index eb10b22..e8325a7 100644
--- a/src/host.rs
+++ b/src/host.rs
@@ -127,9 +127,26 @@ fn region_alias(output: &mut dyn Write, name: &str, placement: Memory) -> io::Re
#[derive(Debug, Clone, PartialEq, Eq)]
struct FlashOpts {
size: usize,
+ offset: u32,
flexspi: FlexSpi,
}
+impl FlashOpts {
+ /// Produce the flash address of the image within
+ /// FlexSPI memory.
+ fn flash_origin(&self, family: Family) -> Option<u32> {
+ self.flexspi
+ .start_address(family)
+ .map(|start_address| start_address + self.offset)
+ }
+
+ /// A bootable image (with the boot header) isn't offset
+ /// in flash.
+ fn is_boot_image(&self) -> bool {
+ self.offset == 0
+ }
+}
+
#[derive(Debug, Clone, PartialEq, Eq)]
struct EnvOverride {
default: usize,
@@ -342,6 +359,43 @@ impl RuntimeBuilder {
heap_size: EnvOverride::new(0),
flash_opts: Some(FlashOpts {
size: flash_size,
+ offset: 0,
+ flexspi: FlexSpi::family_default(family),
+ }),
+ linker_script_name: DEFAULT_LINKER_SCRIPT_NAME.into(),
+ }
+ }
+
+ /// Allocate a flash partition for this program to be booted by your software.
+ ///
+ /// `partition_size` is the size of the flash allocation, in bytes, for this
+ /// program. `partition_offset` describes the byte offset where the partition
+ /// starts. The offset is from the start of the FlexSPI memory region.
+ ///
+ /// The program constructed at this flash location cannot be booted by NXP's boot
+ /// ROM. You should bring your own software to execute this program. Note that
+ /// [the runtime behaviors](RuntimeBuilder) ensure that the vector table is placed
+ /// in flash at the given `partition_offset`.
+ ///
+ /// To compute a partition offset from two absolute flash addresses, use
+ /// [`Family::flexspi_start_addr`] to learn the FlexSPI starting address.
+ pub fn in_flash(family: Family, partition_size: usize, partition_offset: u32) -> 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: Some(FlashOpts {
+ size: partition_size,
+ offset: partition_offset,
flexspi: FlexSpi::family_default(family),
}),
linker_script_name: DEFAULT_LINKER_SCRIPT_NAME.into(),
@@ -508,19 +562,21 @@ impl RuntimeBuilder {
if let Some(flash_opts) = &self.flash_opts {
write_flash_memory_map(writer, self.family, flash_opts, &self.flexram_banks)?;
- let boot_header_x = match self.family {
- Family::Imxrt1010
- | Family::Imxrt1015
- | Family::Imxrt1020
- | Family::Imxrt1040
- | Family::Imxrt1050
- | Family::Imxrt1060
- | Family::Imxrt1064
- | Family::Imxrt1160
- | Family::Imxrt1170 => include_bytes!("host/imxrt-boot-header.x").as_slice(),
- Family::Imxrt1180 => include_bytes!("host/imxrt-boot-header-1180.x").as_slice(),
- };
- writer.write_all(boot_header_x)?;
+ if flash_opts.is_boot_image() {
+ let boot_header_x = match self.family {
+ Family::Imxrt1010
+ | Family::Imxrt1015
+ | Family::Imxrt1020
+ | Family::Imxrt1040
+ | Family::Imxrt1050
+ | Family::Imxrt1060
+ | Family::Imxrt1064
+ | Family::Imxrt1160
+ | Family::Imxrt1170 => include_bytes!("host/imxrt-boot-header.x").as_slice(),
+ Family::Imxrt1180 => include_bytes!("host/imxrt-boot-header-1180.x").as_slice(),
+ };
+ writer.write_all(boot_header_x)?;
+ }
} else {
write_ram_memory_map(writer, self.family, &self.flexram_banks)?;
}
@@ -695,10 +751,7 @@ fn write_flash_memory_map(
writeln!(
output,
"FLASH (RX) : ORIGIN = {:#X}, LENGTH = {:#X}",
- flash_opts
- .flexspi
- .start_address(family)
- .expect("Already checked"),
+ flash_opts.flash_origin(family).expect("Already checked"),
flash_opts.size
)?;
write_flexram_memories(output, family, flexram_banks)?;
@@ -901,6 +954,22 @@ impl Family {
},
}
}
+
+ /// Returns the starting address for the given `flexspi` instance.
+ ///
+ /// If a FlexSPI instance isn't available for this family, the return
+ /// is `None`. Otherwise, the return is the starting address in the
+ /// MCU's memory map.
+ ///
+ /// ```
+ /// use imxrt_rt::{Family::*, FlexSpi::*};
+ ///
+ /// assert_eq!(Imxrt1060.flexspi_start_addr(FlexSpi1), Some(0x6000_0000));
+ /// assert!(Imxrt1010.flexspi_start_addr(FlexSpi2).is_none());
+ /// ```
+ pub fn flexspi_start_addr(self, flexspi: FlexSpi) -> Option<u32> {
+ flexspi.start_address(self)
+ }
}
/// FlexRAM bank allocations.