diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/host.rs | 88 | ||||
| -rw-r--r-- | src/host/imxrt-boot-header-1180.x | 104 | ||||
| -rw-r--r-- | src/host/imxrt-boot-header.x | 2 | ||||
| -rw-r--r-- | src/host/imxrt-link.x | 15 | ||||
| -rw-r--r-- | src/target.rs | 10 |
5 files changed, 205 insertions, 14 deletions
diff --git a/src/host.rs b/src/host.rs index dbe023f..de6afa3 100644 --- a/src/host.rs +++ b/src/host.rs @@ -66,7 +66,8 @@ impl FlexSpi { | Family::Imxrt1020 | Family::Imxrt1050 | Family::Imxrt1060 - | Family::Imxrt1170 => FlexSpi::FlexSpi1, + | Family::Imxrt1170 + | Family::Imxrt1180 => FlexSpi::FlexSpi1, } } fn start_address(self, family: Family) -> Option<u32> { @@ -91,6 +92,8 @@ impl FlexSpi { // 11xx support (FlexSpi::FlexSpi1, Family::Imxrt1170) => Some(0x3000_0000), (FlexSpi::FlexSpi2, Family::Imxrt1170) => Some(0x6000_0000), + (FlexSpi::FlexSpi1, Family::Imxrt1180) => Some(0x2800_0000), + (FlexSpi::FlexSpi2, Family::Imxrt1180) => Some(0x0400_0000), } } fn supported_for_family(self, family: Family) -> bool { @@ -498,7 +501,16 @@ 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 = include_bytes!("host/imxrt-boot-header.x"); + let boot_header_x = match self.family { + Family::Imxrt1010 + | Family::Imxrt1015 + | Family::Imxrt1020 + | Family::Imxrt1050 + | Family::Imxrt1060 + | Family::Imxrt1064 + | 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)?; @@ -543,7 +555,7 @@ impl RuntimeBuilder { writeln!( writer, "__flexram_config = {:#010X};", - self.flexram_banks.config() + self.flexram_banks.config(self.family) )?; // The target runtime looks at this value to predicate some pre-init instructions. // Could be helpful for binary identification, but it's an undocumented feature. @@ -619,10 +631,20 @@ fn write_flexram_memories( flexram_banks: &FlexRamBanks, ) -> io::Result<()> { if flexram_banks.itcm > 0 { + let itcm_size = flexram_banks.itcm * family.flexram_bank_size(); + let itcm_start = match family { + Family::Imxrt1010 + | Family::Imxrt1015 + | Family::Imxrt1020 + | Family::Imxrt1050 + | Family::Imxrt1060 + | Family::Imxrt1064 + | Family::Imxrt1170 => 0x00000000, + Family::Imxrt1180 => 0x10000000 - itcm_size, + }; writeln!( output, - "ITCM (RWX) : ORIGIN = 0x00000000, LENGTH = {:#X}", - flexram_banks.itcm * family.flexram_bank_size(), + "ITCM (RWX) : ORIGIN = {itcm_start:#X}, LENGTH = {itcm_size:#X}" )?; } if flexram_banks.dtcm > 0 { @@ -708,6 +730,7 @@ pub enum Family { Imxrt1060, Imxrt1064, Imxrt1170, + Imxrt1180, } impl Family { @@ -725,6 +748,7 @@ impl Family { Family::Imxrt1060 => 1060, Family::Imxrt1064 => 1064, Family::Imxrt1170 => 1170, + Family::Imxrt1180 => 1180, } } /// How many FlexRAM banks are available? @@ -735,11 +759,21 @@ impl Family { Family::Imxrt1050 | Family::Imxrt1060 | Family::Imxrt1064 => 16, // No ECC support; treating all banks as equal. Family::Imxrt1170 => 16, + Family::Imxrt1180 => 2, } } /// How large (bytes) is each FlexRAM bank? const fn flexram_bank_size(self) -> u32 { - 32 * 1024 + match self { + Family::Imxrt1010 + | Family::Imxrt1015 + | Family::Imxrt1020 + | Family::Imxrt1050 + | Family::Imxrt1060 + | Family::Imxrt1064 + | Family::Imxrt1170 => 32 * 1024, + Family::Imxrt1180 => 128 * 1024, + } } /// How many OCRAM banks does the boot ROM need? const fn bootrom_ocram_banks(self) -> u32 { @@ -748,13 +782,13 @@ impl Family { // 9.5.1. memory maps point at OCRAM2. Family::Imxrt1060 | Family::Imxrt1064 => 0, // Boot ROM uses dedicated OCRAM1. - Family::Imxrt1170 => 0, + Family::Imxrt1170 | Family::Imxrt1180 => 0, } } /// Where's the FlexSPI configuration bank located? fn fcb_offset(self) -> usize { match self { - Family::Imxrt1010 | Family::Imxrt1170 => 0x400, + Family::Imxrt1010 | Family::Imxrt1170 | Family::Imxrt1180 => 0x400, Family::Imxrt1015 | Family::Imxrt1020 | Family::Imxrt1050 @@ -770,6 +804,8 @@ impl Family { match self { // 256 KiB offset from the OCRAM M4 backdoor. Family::Imxrt1170 => 0x2024_0000, + // Skip the first 16 KiB, "cannot be safely used by application images". + Family::Imxrt1180 => 0x2048_4000, // Either starts the FlexRAM OCRAM banks, or the // dedicated OCRAM regions (for supported devices). Family::Imxrt1010 @@ -792,6 +828,8 @@ impl Family { // - Two dedicated OCRAM ECC regions that aren't used for ECC // - One FlexRAM OCRAM ECC region that's strictly OCRAM, without ECC Family::Imxrt1170 => (2 * 512 + 2 * 64 + 128) * 1024, + // OCRAM1 (512k), OCRAM2 (256k), 16k reserved as a ROM patch area + Family::Imxrt1180 => (512 + 256 - 16) * 1024, } } @@ -820,6 +858,11 @@ impl Family { itcm: 8, dtcm: 8, }, + Family::Imxrt1180 => FlexRamBanks { + ocram: 0, + itcm: 1, + dtcm: 1, + }, } } } @@ -861,7 +904,21 @@ impl FlexRamBanks { } /// Produces the FlexRAM configuration. - fn config(&self) -> u32 { + fn config(&self, family: Family) -> u32 { + match family { + Family::Imxrt1010 + | Family::Imxrt1015 + | Family::Imxrt1020 + | Family::Imxrt1050 + | Family::Imxrt1060 + | Family::Imxrt1064 + | Family::Imxrt1170 => self.config_gpr(), + Family::Imxrt1180 => self.config_1180(), + } + } + + /// Produces the FlexRAM configuration for families using GPR17. + fn config_gpr(&self) -> u32 { assert!( self.bank_count() <= 16, "Something is wrong; this should have been checked earlier." @@ -888,6 +945,17 @@ impl FlexRamBanks { (OCRAM & ocram_mask) | (DTCM & dtcm_mask) | (ITCM & itcm_mask) } + + fn config_1180(&self) -> u32 { + match (self.itcm, self.dtcm, self.ocram) { + (1, 1, 0) => 0b00_u32, + (2, 0, 0) => 0b10, + (0, 2, 0) => 0b01, + _ => panic!("Unsupported FlexRAM configuration"), + } + .checked_shl(2) + .unwrap() + } } #[cfg(test)] @@ -996,7 +1064,7 @@ mod tests { ]; for (banks, expected) in TABLE { - let actual = banks.config(); + let actual = banks.config(Family::Imxrt1010); assert!( actual == *expected, "\nActual: {actual:#034b}\nExpected: {expected:#034b}\nBanks: {banks:?}" diff --git a/src/host/imxrt-boot-header-1180.x b/src/host/imxrt-boot-header-1180.x new file mode 100644 index 0000000..101725a --- /dev/null +++ b/src/host/imxrt-boot-header-1180.x @@ -0,0 +1,104 @@ +/* ===--- Begin imxrt-boot-header-1180.x ---=== + * This extra content is injected into the linker script depending on the + * runtime configuration. + */ + +__image_size = SIZEOF(.vector_table) + SIZEOF(.text) + SIZEOF(.xip) + SIZEOF(.rodata) + SIZEOF(.data); + +EXTERN(FLEXSPI_CONFIGURATION_BLOCK); + +/* # Sections */ +SECTIONS +{ + /* Boot header for serial NOR FlexSPI XIP. + * + * It's 'XIP' in that it starts executing instructions + * from flash immediately out of reset. The runtime then + * manually copies instructions (data, etc.), and we jump + * to that. After that jump, we're no longer XIP. + * + * The i.MX RT boot ROM also supports a way to copy the + * application image by changing the boot data configuration. + * Specifically, point the 'Image offset' to somewhere other + * than the start of flash, and specify how many bytes to copy. + * The boot ROM copies the image, then jumps to the entry point. + * It is currently not tested or used, mainly for consistency + * with the other iMXRT families. + */ + .boot1 ORIGIN(FLASH): + { + FILL(0x00); + /* ------------------ + * Memory configuration block + * ------------------ + * + * The size and layout is different for different boot devices. Currently, + * only NOR flash is supported. + */ + . += __fcb_offset; /* Can change based on boot source */ + KEEP(*(.fcb)); + . = ORIGIN(FLASH) + 0x1000; + + /* ------------------ + * Container 1 + * ------------------ + */ + __container1_start = .; + LONG(0x87000000 | (__container1_len << 8)); /* Tag, length, version */ + LONG(0); /* Flags */ + LONG(0x01000000); /* 1 image, fuse version 0, SW version 0 */ + LONG(__signature_block_start - __container1_start); /* Signature block offset */ + + /* Image array, image 0 */ + LONG(0xa000); /* Image offset */ + LONG(__image_size); /* Image size */ + QUAD(LOADADDR(.vector_table)); /* Load address (execute in place) */ + QUAD(Reset); /* Entry point */ + LONG(0x213); /* Flags: Unencrypted, SHA512 hashed, executable image for Cortex-M33 */ + LONG(0); /* Reserved (image meta data) */ + } > FLASH + + /* Put the hash in a separate section for easier replacement in a post-build step */ + .image_hash : + { + QUAD(0); /* Hash 512 bytes */ + QUAD(0); + QUAD(0); + QUAD(0); + QUAD(0); + QUAD(0); + QUAD(0); + QUAD(0); + } > FLASH + + .boot2 : + { + FILL(0x00); + QUAD(0); /* IV 256 bytes, zero for unencrypted image */ + QUAD(0); + QUAD(0); + QUAD(0); + + /* ------------------ + * Signature block + * ------------------ + */ + __signature_block_start = .; + LONG(0x90000000 | (__signature_block_len << 8)); /* Tag, length, version */ + LONG(0); /* SRK Table offset, Certificate Offset */ + LONG(0); /* Signature offset, Blob offset */ + LONG(0); /* Reserved */ + __signature_block_end = .; + __signature_block_len = __signature_block_end - __signature_block_start; + __container1_end = .; + __container1_len = __container1_end - __container1_start; + + /* DCD is replaced by XMCD. Satisfy assertions intended for other families. */ + __dcd_start = .; + __dcd_end = .; + + . = ORIGIN(FLASH) + 0x2000; /* Pad to 8k alignment for the container/images boundary */ + } > FLASH +} + +/* ===--- End imxrt-boot-header-1180.x ---=== */ diff --git a/src/host/imxrt-boot-header.x b/src/host/imxrt-boot-header.x index 615fc65..3f33603 100644 --- a/src/host/imxrt-boot-header.x +++ b/src/host/imxrt-boot-header.x @@ -8,7 +8,7 @@ * Note that it depends on the section layout! Need to represent contiguous * sections starting from the boot header. */ -__image_size = SIZEOF(.boot) + SIZEOF(.vector_table) + SIZEOF(.text) + SIZEOF(.rodata); +__image_size = SIZEOF(.boot) + SIZEOF(.vector_table) + SIZEOF(.xip) + SIZEOF(.text) + SIZEOF(.rodata); /* END TODO */ EXTERN(FLEXSPI_CONFIGURATION_BLOCK); diff --git a/src/host/imxrt-link.x b/src/host/imxrt-link.x index 6c28f99..a389325 100644 --- a/src/host/imxrt-link.x +++ b/src/host/imxrt-link.x @@ -48,6 +48,7 @@ SECTIONS .vector_table : ALIGN(1024) { + FILL(0xff); __vector_table = .; __svector_table = .; @@ -68,13 +69,19 @@ SECTIONS } > REGION_VTABLE AT> REGION_LOAD_VTABLE __sivector_table = LOADADDR(.vector_table); + /* This section guarantees VMA = LMA to allow the execute-in-place entry point to be inside the image. */ + .xip : + { + /* Included here if not otherwise included in the boot header. */ + *(.Reset); + *(.__pre_init); + } > REGION_LOAD_TEXT + .text : { + FILL(0xff); __stext = .; *(.text .text.*); - /* Included in .text if not otherwise included in the boot header. */ - *(.Reset); - *(.__pre_init); /* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`, so must be placed close to it. */ *(.HardFaultTrampoline); @@ -86,6 +93,7 @@ SECTIONS .rodata : ALIGN(4) { + FILL(0xff); . = ALIGN(4); __srodata = .; *(.rodata .rodata.*); @@ -100,6 +108,7 @@ SECTIONS .data : ALIGN(4) { + FILL(0xff); . = ALIGN(4); __sdata = .; *(.data .data.*); diff --git a/src/target.rs b/src/target.rs index 3a61584..765862d 100644 --- a/src/target.rs +++ b/src/target.rs @@ -41,6 +41,9 @@ global_asm! {r#" __pre_init: ldr r0, =__imxrt_family @ Need to know which chip family we're initializing. + ldr r1, =1180 + cmp r0, r1 @ Is this an 1180? + beq flexram_1180 ldr r1, =1170 cmp r0, r1 @ Is this an 1170? @@ -66,7 +69,14 @@ __pre_init: ldr r1, [r0, #64] @ r1 = *(IMXRT_IOMUXC_GPR + 16) orr r1, r1, #1<<2 @ r1 |= 1 << 2 str r1, [r0, #64] @ *(IMXRT_IOMUXC_GPR + 16) = r1 + b copy_from_flash + flexram_1180: + ldr r0, =0x444F0060 @ M33_CONFIG + ldr r1, =__flexram_config + str r1, [r0, #0] + + copy_from_flash: # Conditionally copy text. ldr r0, =__stext ldr r2, =__sitext |
