F-13655: index the flash double-word fast path from the current offset

With an unaligned start address the byte-wise prefix leaves i % 4 != 0,
so dst[i >> 2] programmed the double word below the intended address
and left the tail bytes of the unit unprogrammed. Derive src/dst from
address + i, matching the already-fixed else branch.

Verification: new unit-stm32g4-write test_write_unaligned_start fails
pre-fix (memcmp mismatch), 5/5 post-fix; full make -C tools/unit-tests
run green.
pull/910/head
Daniele Lacamera 2026-09-24 02:47:16 +02:00
parent f0e2c49150
commit 6025f3540f
3 changed files with 28 additions and 8 deletions

View File

@ -142,11 +142,11 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
flash_clear_errors();
if ((len - i >= 8) && ((((address + i) & 0x07) == 0) &&
((((uint32_t)data) + i) & 0x07) == 0)) {
src = (uint32_t *)data;
dst = (uint32_t *)address;
src = (uint32_t *)(data + i);
dst = (uint32_t *)(address + i);
flash_wait_complete();
dst[i >> 2] = src[i >> 2];
dst[(i >> 2) + 1] = src[(i >> 2) + 1];
dst[0] = src[0];
dst[1] = src[1];
flash_wait_complete();
i+=8;
} else {

View File

@ -56,11 +56,11 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
flash_clear_errors();
if ((len - i >= 8) && ((((address + i) & 0x07) == 0) &&
((((uint32_t)data) + i) & 0x07) == 0)) {
src = (uint32_t *)data;
dst = (uint32_t *)address;
src = (uint32_t *)(data + i);
dst = (uint32_t *)(address + i);
flash_wait_complete();
dst[i >> 2] = src[i >> 2];
dst[(i >> 2) + 1] = src[(i >> 2) + 1];
dst[0] = src[0];
dst[1] = src[1];
flash_wait_complete();
i += 8;
} else {

View File

@ -179,6 +179,25 @@ START_TEST(test_write_64_full_units)
}
END_TEST
/* A write starting at an address with mod-8 residue 1: the byte-wise
* prefix leaves i = 7, where the fast path fires with i % 4 != 0.
* Pre-fix the double word was programmed 3 bytes below the intended
* address and the last 3 bytes of the unit were never programmed. */
START_TEST(test_write_unaligned_start)
{
int i;
ck_assert_int_eq(hal_flash_write((uint32_t)(uintptr_t)(g_flash_mem + 1),
g_data + 1, 16), 0);
ck_assert_int_eq(memcmp(g_flash_mem + 1, g_data + 1, 16), 0);
ck_assert_uint_eq(g_flash_mem[0], 0x12);
for (i = 17; i < FLASH_MEM_SZ; i++)
ck_assert_uint_eq(g_flash_mem[i], 0x12);
ck_assert_int_eq(canary_in_flash(), 0);
}
END_TEST
Suite *stm32g4_write_suite(void)
{
Suite *s = suite_create("stm32g4-write");
@ -189,6 +208,7 @@ Suite *stm32g4_write_suite(void)
tcase_add_test(tc, test_write_58_partial_word_padded);
tcase_add_test(tc, test_write_3_single_word_padded);
tcase_add_test(tc, test_write_64_full_units);
tcase_add_test(tc, test_write_unaligned_start);
suite_add_tcase(s, tc);
return s;