Skip to content
Open
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
87 changes: 80 additions & 7 deletions hal/va416x0.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,80 @@ void ext_flash_unlock(void)
VOR_SYSCONFIG->ROM_PROT |= SYSCONFIG_ROM_PROT_WREN_Msk;
}

/* The VA416xx code RAM (IRAM, 0x00000000-0x0003FFFF) silently drops 8/16-bit
* stores when WREN=1 - only word-aligned 32-bit stores stick (the ECC
* machinery computes parity per word and rejects sub-word writes without
* fault). A generic byte-wise memcpy/memset on the IRAM shadow appears
* to succeed but leaves the destination unchanged. These helpers copy/fill
* with 32-bit stores so the IRAM shadow update actually takes effect.
*
* Partition addresses (boot/update/swap) are sector-aligned (0x800) and the
* swap engine moves whole sector-sized blocks, so in practice the IRAM
* shadow path is always word-aligned. The unaligned head/tail fallbacks
* exist for defense-in-depth. */
static void iram_write(void *dst, const void *src, int len)
Comment thread
dgarske marked this conversation as resolved.
{
uintptr_t d = (uintptr_t)dst;
uintptr_t s = (uintptr_t)src;
/* Word-aligned bulk copy. The destination is marked volatile so the
* compiler cannot lower a 32-bit assignment into byte/halfword stores
* (which would be silently dropped by the IRAM ECC machinery). */
if (((d | s) & (uintptr_t)3u) == 0u) {
volatile uint32_t *wd = (volatile uint32_t *)dst;
const uint32_t *ws = (const uint32_t *)src;
while (len >= 4) {
*wd++ = *ws++;
len -= 4;
}
/* Fall through with byte tail (typically zero on this target) */
dst = (void *)wd;
src = ws;
}
/* Byte tail/unaligned: do read-modify-write of the containing word
* (sub-word stores are dropped by the hardware). */
while (len > 0) {
uintptr_t addr = (uintptr_t)dst & ~(uintptr_t)3u;
uint32_t off = (uint32_t)((uintptr_t)dst & (uintptr_t)3u);
uint32_t word = *(volatile uint32_t *)addr;
uint8_t *wp = (uint8_t *)&word;
while (len > 0 && off < 4u) {
wp[off++] = *(const uint8_t *)src;
src = (const uint8_t *)src + 1;
dst = (uint8_t *)dst + 1;
len--;
}
*(volatile uint32_t *)addr = word;
}
}

static void iram_fill(void *dst, uint8_t val, int len)
Comment thread
dgarske marked this conversation as resolved.
{
uint32_t pattern = ((uint32_t)val << 24) | ((uint32_t)val << 16) |
((uint32_t)val << 8) | (uint32_t)val;
uintptr_t d = (uintptr_t)dst;
/* Word-aligned bulk fill via volatile to guarantee 32-bit stores. */
if ((d & (uintptr_t)3u) == 0u) {
volatile uint32_t *wd = (volatile uint32_t *)dst;
while (len >= 4) {
*wd++ = pattern;
len -= 4;
Comment thread
dgarske marked this conversation as resolved.
}
dst = (void *)wd;
}
while (len > 0) {
uintptr_t addr = (uintptr_t)dst & ~(uintptr_t)3u;
uint32_t off = (uint32_t)((uintptr_t)dst & (uintptr_t)3u);
uint32_t word = *(volatile uint32_t *)addr;
uint8_t *wp = (uint8_t *)&word;
while (len > 0 && off < 4u) {
wp[off++] = val;
dst = (uint8_t *)dst + 1;
len--;
}
*(volatile uint32_t *)addr = word;
}
}

int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
{
hal_status_t status;
Expand All @@ -370,8 +444,8 @@ int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
#endif
status = FRAM_Write(ROM_SPI_BANK, address, (uint8_t*)data, len);
if (status == hal_status_ok) {
/* update the shadow IRAM */
memcpy((void*)address, data, len);
/* update the shadow IRAM (word-aligned stores; see iram_write) */
iram_write((void*)address, data, len);
}
else {
return -(int)status; /* convert to negative error code */
Expand All @@ -388,8 +462,8 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len)
#endif
status = FRAM_Read(ROM_SPI_BANK, address, data, len);
if (status == hal_status_ok) {
/* update the shadow IRAM */
memcpy((void*)address, data, len);
/* update the shadow IRAM (word-aligned stores; see iram_write) */
iram_write((void*)address, data, len);
}
else {
return -(int)status; /* convert to negative error code */
Expand All @@ -405,8 +479,8 @@ int ext_flash_erase(uintptr_t address, int len)
#endif
status = FRAM_Erase(ROM_SPI_BANK, address, len);
if (status == hal_status_ok) {
/* update the shadow IRAM */
memset((void*)address, 0xFF, len);
/* update the shadow IRAM (word-aligned stores; see iram_fill) */
iram_fill((void*)address, 0xFF, len);
}
else {
return -(int)status; /* convert to negative error code */
Expand Down Expand Up @@ -539,7 +613,6 @@ void hal_init(void)
#ifdef TEST_EXT_FLASH
test_ext_flash();
#endif

}

void hal_prepare_boot(void)
Expand Down
Loading