hal: always define hal_cache_invalidate(), implement it on F4 and G4

The weak no-op sat inside NVM_FLASH_WRITEONCE, so pkcs11_store.c failed to
link on the nrf5340/nrf54l TrustZone configs. STM32F4 and STM32G4 enable the
flash instruction/data caches and never reset them, so give them a real one.
pull/873/head
Daniele Lacamera 2026-09-10 18:42:54 +02:00
parent 42e6dba558
commit 9b06b907f8
4 changed files with 62 additions and 4 deletions

View File

@ -196,9 +196,35 @@ void RAMFUNCTION hal_flash_unlock(void)
FLASH_KEYR = FLASH_KEY2;
}
/* RM0090 3.5.1: the instruction and data caches keep lines fetched before an
* erase/program, so a read-back through the flash memory map can return
* pre-erase bytes. The reset bits are only writable while the corresponding
* cache is disabled, hence the disable/reset/re-enable dance. */
void RAMFUNCTION hal_cache_invalidate(void)
{
uint32_t acr = FLASH_ACR;
if (acr & FLASH_ACR_ENABLE_INST_CACHE) {
FLASH_ACR &= ~FLASH_ACR_ENABLE_INST_CACHE;
FLASH_ACR |= FLASH_ACR_RESET_INST_CACHE;
FLASH_ACR &= ~FLASH_ACR_RESET_INST_CACHE;
FLASH_ACR |= FLASH_ACR_ENABLE_INST_CACHE;
}
if (acr & FLASH_ACR_ENABLE_DATA_CACHE) {
FLASH_ACR &= ~FLASH_ACR_ENABLE_DATA_CACHE;
FLASH_ACR |= FLASH_ACR_RESET_DATA_CACHE;
FLASH_ACR &= ~FLASH_ACR_RESET_DATA_CACHE;
FLASH_ACR |= FLASH_ACR_ENABLE_DATA_CACHE;
}
}
void RAMFUNCTION hal_flash_lock(void)
{
FLASH_CR |= FLASH_CR_LOCK;
/* Drop the stale cache lines at the end of the write/erase batch: every
* sequence in wolfBoot ends with a lock, so one invalidate per batch
* covers every consumer that reads flash back. */
hal_cache_invalidate();
}

View File

@ -98,11 +98,37 @@ void RAMFUNCTION hal_flash_unlock(void)
}
}
/* RM0440 3.3.3: the instruction and data caches keep lines fetched before an
* erase/program, so a read-back through the flash memory map can return
* pre-erase bytes. The reset bits are only writable while the corresponding
* cache is disabled, hence the disable/reset/re-enable dance. */
void RAMFUNCTION hal_cache_invalidate(void)
{
uint32_t acr = FLASH_ACR;
if (acr & FLASH_ACR_ICEN) {
FLASH_ACR &= ~FLASH_ACR_ICEN;
FLASH_ACR |= FLASH_ACR_ICRST;
FLASH_ACR &= ~FLASH_ACR_ICRST;
FLASH_ACR |= FLASH_ACR_ICEN;
}
if (acr & FLASH_ACR_DCEN) {
FLASH_ACR &= ~FLASH_ACR_DCEN;
FLASH_ACR |= FLASH_ACR_DCRST;
FLASH_ACR &= ~FLASH_ACR_DCRST;
FLASH_ACR |= FLASH_ACR_DCEN;
}
}
void RAMFUNCTION hal_flash_lock(void)
{
flash_wait_complete();
if ((FLASH_CR & FLASH_CR_LOCK) == 0)
FLASH_CR |= FLASH_CR_LOCK;
/* Drop the stale cache lines at the end of the write/erase batch: every
* sequence in wolfBoot ends with a lock, so one invalidate per batch
* covers every consumer that reads flash back. */
hal_cache_invalidate();
}

View File

@ -102,6 +102,8 @@
#define FLASH_ACR_PRFTEN (1 << 8)
#define FLASH_ACR_ICEN (1 << 9)
#define FLASH_ACR_DCEN (1 << 10)
#define FLASH_ACR_ICRST (1 << 11)
#define FLASH_ACR_DCRST (1 << 12)
#define FLASH_ACR_LATENCY_4WS (0x4)
/* G4 has a single BSY at bit 16 (no BSY1/BSY2 like G0). */

View File

@ -244,6 +244,14 @@ static const uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL;
#define FLAGS_UPDATE_EXT() PARTN_IS_EXT(PART_UPDATE)
#endif
/* Weak no-op default: targets whose flash reads are not cached need not
* implement this. It lives outside NVM_FLASH_WRITEONCE because callers such
* as src/pkcs11_store.c are built independently of that option. */
void WEAKFUNCTION hal_cache_invalidate(void)
{
/* if cache flushing is required implement in hal */
}
#ifdef NVM_FLASH_WRITEONCE
/* Some internal FLASH memory models don't allow
* multiple writes after erase in the same page/area.
@ -282,10 +290,6 @@ static uint8_t get_base_offset(uint8_t *base, uintptr_t off)
return *(uint8_t*)((uintptr_t)base - off); /* ignore array bounds error */
}
void WEAKFUNCTION hal_cache_invalidate(void)
{
/* if cache flushing is required implement in hal */
}
#ifdef __CCRX__
#pragma section FRAM
#endif