Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

Establish a 32 byte reservation at the start of ITCM where instructions are
never placed. This reduces the total capacity of ITCM by 32 bytes on nearly
all MCUs, except the 1180.

## [0.1.7] 2025-06-14

Introduce `RuntimeBuilder::in_flash` for creating images that can be launched
Expand Down
81 changes: 63 additions & 18 deletions src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,19 +696,7 @@ 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::Imxrt1040
| Family::Imxrt1050
| Family::Imxrt1060
| Family::Imxrt1064
| Family::Imxrt1160
| Family::Imxrt1170 => 0x00000000,
Family::Imxrt1180 => 0x10000000 - itcm_size,
};
let (itcm_start, itcm_size) = family.itcm_start_size(flexram_banks.itcm);
writeln!(
output,
"ITCM (RWX) : ORIGIN = {itcm_start:#X}, LENGTH = {itcm_size:#X}"
Expand Down Expand Up @@ -798,6 +786,8 @@ pub enum Family {
Imxrt1180,
}

/// Adding a new MCU? You'll probably need to update
/// these methods.
impl Family {
/// Family identifier.
///
Expand Down Expand Up @@ -954,6 +944,34 @@ impl Family {
}
}

/// Returns the start and size of the ITCM memory region.
const fn itcm_start_size(self, itcm_banks: u32) -> (u32, u32) {
let mut itcm_size = itcm_banks * self.flexram_bank_size();
let itcm_start = match self {
Family::Imxrt1010
| Family::Imxrt1015
| Family::Imxrt1020
| Family::Imxrt1040
| Family::Imxrt1050
| Family::Imxrt1060
| Family::Imxrt1064
| Family::Imxrt1160
| Family::Imxrt1170 => {
// Establish a reservation for null pointers.
// Note that this reservation is the minimum
// size of an MPU region.
itcm_size = itcm_size.saturating_sub(32);
32
}
Family::Imxrt1180 => 0x10000000 - itcm_size,
};
(itcm_start, itcm_size)
}
}

/// If you're adding a new MCU family, you probably
/// don't need to change these methods.
impl Family {
/// Returns the starting address for the given `flexspi` instance.
///
/// If a FlexSPI instance isn't available for this family, the return
Expand Down Expand Up @@ -1071,7 +1089,7 @@ mod tests {
use super::{Family, FlexRamBanks, RuntimeBuilder};
use std::{error, io};

const ALL_FAMILIES: &[Family] = &[
const MOST_FAMILIES: &[Family] = &[
Family::Imxrt1010,
Family::Imxrt1015,
Family::Imxrt1020,
Expand All @@ -1080,6 +1098,7 @@ mod tests {
Family::Imxrt1060,
Family::Imxrt1064,
Family::Imxrt1170,
// Imxrt1180 wasn't ever tested here.
];
type Error = Box<dyn error::Error>;

Expand Down Expand Up @@ -1171,7 +1190,7 @@ mod tests {
];

for (banks, expected) in TABLE {
let actual = banks.config(Family::Imxrt1010);
let actual = banks.config_gpr();
assert!(
actual == *expected,
"\nActual: {actual:#034b}\nExpected: {expected:#034b}\nBanks: {banks:?}"
Expand All @@ -1181,7 +1200,7 @@ mod tests {

#[test]
fn runtime_builder_default_from_flexspi() -> Result<(), Error> {
for family in ALL_FAMILIES {
for family in MOST_FAMILIES {
RuntimeBuilder::from_flexspi(*family, 16 * 1024 * 1024)
.write_linker_script(&mut io::sink())?;
}
Expand All @@ -1201,7 +1220,7 @@ mod tests {
dtcm: 32,
ocram: 32,
};
for family in ALL_FAMILIES {
for family in MOST_FAMILIES {
let res = RuntimeBuilder::from_flexspi(*family, 16 * 1024)
.flexram_banks(banks)
.write_linker_script(&mut io::sink());
Expand All @@ -1226,7 +1245,7 @@ mod tests {
placement!(heap),
];

for family in ALL_FAMILIES {
for family in MOST_FAMILIES {
for placement in placements {
let mut bldr = RuntimeBuilder::from_flexspi(*family, 16 * 1024);
placement.0(&mut bldr);
Expand All @@ -1235,4 +1254,30 @@ mod tests {
}
}
}

#[test]
fn itcm_start_size() {
// Most parts have an ITCM that could touch address 0.
// However, the implementation reserves an MPU region
// at address 0.
for family in MOST_FAMILIES {
for itcm_banks in 0..=family.flexram_bank_count() {
let (start, size) = family.itcm_start_size(itcm_banks);
assert_eq!(start, 32);
assert_eq!(
size,
(family.flexram_bank_size() * itcm_banks).saturating_sub(32)
);
}
}

// The 1180's ITCM never touches address 0 when the ITCM banks
// are properly configured.
let family = Family::Imxrt1180;
for itcm_banks in 0..=family.flexram_bank_count() {
let (start, size) = family.itcm_start_size(itcm_banks);
assert_ne!(start, 0);
assert_eq!(size, family.flexram_bank_size() * itcm_banks);
}
}
}
2 changes: 1 addition & 1 deletion tests/inspect_elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ struct Section {
}

const DTCM: u64 = 0x2000_0000;
const ITCM: u64 = 0x0000_0000;
const ITCM: u64 = 0x0000_0020;

const fn aligned(value: u64, alignment: u64) -> u64 {
(value + (alignment - 1)) & !(alignment - 1)
Expand Down