aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/host.rs88
-rw-r--r--src/host/imxrt-boot-header-1180.x104
-rw-r--r--src/host/imxrt-boot-header.x2
-rw-r--r--src/host/imxrt-link.x15
-rw-r--r--src/target.rs10
6 files changed, 207 insertions, 14 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf9949a..b345574 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,8 @@
## [Unreleased]
+Add initial support for RT1180.
+
## [0.1.4] 2024-04-05
Add configurations to `RuntimeBuilder`:
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