diff --git a/hal/stm32g0.c b/hal/stm32g0.c index aea0fc8b..03d83380 100644 --- a/hal/stm32g0.c +++ b/hal/stm32g0.c @@ -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 { diff --git a/hal/stm32g4.c b/hal/stm32g4.c index a880c0ad..3372607f 100644 --- a/hal/stm32g4.c +++ b/hal/stm32g4.c @@ -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 { diff --git a/tools/unit-tests/unit-stm32g4-write.c b/tools/unit-tests/unit-stm32g4-write.c index c6eb00ae..2d51e6df 100644 --- a/tools/unit-tests/unit-stm32g4-write.c +++ b/tools/unit-tests/unit-stm32g4-write.c @@ -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;