Skip to content

Commit 7a2ed47

Browse files
committed
imx95_m7: do not issue D-cache clean by address while the cache is disabled
1 parent b8254ba commit 7a2ed47

3 files changed

Lines changed: 37 additions & 0 deletions

File tree

‎config/examples/imx95-m7.config‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@ TARGET?=imx95_m7
33
SIGN?=ECC256
44
HASH?=SHA256
55
DEBUG?=0
6+
# Per-step timing in ms, from the DWT cycle counter. DEBUG_HARDFAULT is
7+
# required alongside it on this target, and not for debugging: BOOT_BENCHMARK
8+
# on its own produces an image that panics before its first console write,
9+
# deterministically (3 of 3 cold boots), and enabling the fault handler makes
10+
# the fault stop happening. It is not image size - padding the failing build to
11+
# the working build's exact byte size still panics - and hal_init codegen is
12+
# identical between the two, so the trigger is layout-sensitive and not yet
13+
# root-caused. hal_status() independently stamps DWT_CYCCNT into the status
14+
# block at hal_init and at hal_prepare_boot, so the total verified-boot time is
15+
# readable even with both of these off.
16+
BOOT_BENCHMARK?=1
17+
CFLAGS_EXTRA+=-DDEBUG_HARDFAULT
618
VTOR?=1
719
CORTEX_M0?=0
820
NO_ASM?=0

‎hal/imx95_m7.c‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,17 @@ void hal_init(void)
303303
hal_status(HAL_STATUS_INIT);
304304
}
305305

306+
#if defined(WOLFBOOT_UPDATE_DISK) || defined(BOOT_BENCHMARK)
307+
/* Microseconds from the DWT cycle counter hal_init() starts. The counter is
308+
* 32-bit and wraps about every 5.4 s at 800 MHz, which bounds any single
309+
* measurement rather than the boot as a whole - each BENCHMARK_END subtracts
310+
* two reads, so a wrap only matters for an interval longer than that. */
311+
uint64_t hal_get_timer_us(void)
312+
{
313+
return (uint64_t)DWT_CYCCNT / (IMX95_M7_CORE_HZ / 1000000UL);
314+
}
315+
#endif
316+
306317
void hal_prepare_boot(void)
307318
{
308319
hal_status(HAL_STATUS_PREBOOT);

‎hal/imx95_m7.h‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@ static inline void imx95_dcache_clean(const void *addr, uint32_t len)
115115

116116
if (len == 0)
117117
return;
118+
/* Nothing to clean while the cache is off - every store already reached
119+
* memory. It is also unsafe: the M7 does maintenance by address even with
120+
* the cache disabled, and out of a cold reset the cache RAMs hold random
121+
* tags and dirty bits until hal_cache_enable() invalidates them, so a hit
122+
* writes garbage to a random address and the bus error comes back as an
123+
* imprecise BusFault. */
124+
if ((SCB_CCR & CCR_DC) == 0UL)
125+
return;
118126
line = ((uint32_t)(uintptr_t)addr) & ~(IMX95_CACHE_LINE - 1UL);
119127
end = (uint32_t)(uintptr_t)addr + len;
120128
for (; line < end; line += IMX95_CACHE_LINE) {
@@ -147,6 +155,12 @@ static inline void imx95_dwt_init(void)
147155
DWT_CTRL |= DWT_CYCCNTENA;
148156
}
149157

158+
/* The M7 core clock on this part. Only used to turn cycle counts into
159+
* milliseconds for the boot benchmark; override for a different clock. */
160+
#ifndef IMX95_M7_CORE_HZ
161+
#define IMX95_M7_CORE_HZ 800000000UL
162+
#endif
163+
150164
/* Bounded spin. Wrap-safe for any delay shorter than a full 32-bit period
151165
* (~5.4 s at 800 MHz) because the comparison is done on the difference. */
152166
static inline void imx95_delay_cycles(uint32_t cycles)

0 commit comments

Comments
 (0)