mirror of https://github.com/wolfSSL/wolfBoot.git
F-7382: clip QSPI page program transfers at the device page boundary
spi_flash_write() chunked purely by length, issuing up to a full FLASH_PAGE_SIZE page program at address + page*FLASH_PAGE_SIZE. NOR flash page program wraps within the device's own page, so a transfer starting mid-page (e.g. 0x10F0 with 256 bytes) programmed the tail of the page and then wrapped the rest back over the start of the same page, corrupting already-programmed data and leaving the intended range unwritten. Drive the loop from the running address and clip each transfer to the bytes remaining in the current page, matching src/spi_flash.c.pull/851/head
parent
ab7b79cd16
commit
a799a98c70
|
|
@ -419,8 +419,8 @@ int spi_flash_write(uint32_t address, const void *data, int len)
|
|||
{
|
||||
int ret = 0;
|
||||
int remaining = len;
|
||||
uint32_t xferSz, page, pages;
|
||||
uintptr_t addr;
|
||||
uint32_t xferSz;
|
||||
uintptr_t addr = address;
|
||||
uint8_t* ptr = (uint8_t*)data;
|
||||
|
||||
#ifdef DEBUG_QSPI
|
||||
|
|
@ -437,21 +437,19 @@ int spi_flash_write(uint32_t address, const void *data, int len)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* write by page */
|
||||
pages = ((len + (FLASH_PAGE_SIZE-1)) / FLASH_PAGE_SIZE);
|
||||
for (page = 0; page < pages; page++) {
|
||||
/* write by page: the device's page program wraps within its own page, so
|
||||
* each transfer must terminate at the next page boundary */
|
||||
while (remaining > 0) {
|
||||
ret = qspi_write_enable();
|
||||
if (ret != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
xferSz = (uint32_t)remaining;
|
||||
if (xferSz > FLASH_PAGE_SIZE) {
|
||||
xferSz = FLASH_PAGE_SIZE;
|
||||
xferSz = FLASH_PAGE_SIZE - ((uint32_t)addr % FLASH_PAGE_SIZE);
|
||||
if (xferSz > (uint32_t)remaining) {
|
||||
xferSz = (uint32_t)remaining;
|
||||
}
|
||||
|
||||
addr = address + (page * FLASH_PAGE_SIZE);
|
||||
|
||||
/* ------ Write Flash (page at a time) ------ */
|
||||
ret = qspi_transfer(QSPI_MODE_WRITE, FLASH_WRITE_CMD,
|
||||
addr, QSPI_ADDR_SZ, QSPI_DATA_MODE_SPI, /* Address */
|
||||
|
|
@ -463,7 +461,7 @@ int spi_flash_write(uint32_t address, const void *data, int len)
|
|||
#ifdef DEBUG_QSPI
|
||||
wolfBoot_printf("QSPI Flash Sector Write: "
|
||||
"Ret %d, Cmd 0x%x, Len %d, %p -> 0x%x\n",
|
||||
ret, FLASH_WRITE_CMD, xferSz, ptr, address);
|
||||
ret, FLASH_WRITE_CMD, xferSz, ptr, (uint32_t)addr);
|
||||
#endif
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
|
@ -475,6 +473,7 @@ int spi_flash_write(uint32_t address, const void *data, int len)
|
|||
/* write disable is automatic */
|
||||
remaining -= (int)xferSz;
|
||||
ptr += xferSz;
|
||||
addr += xferSz;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -113,6 +113,32 @@ START_TEST(test_qspi_write_splits_last_page_to_remaining_bytes)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_qspi_write_clips_first_page_at_page_boundary)
|
||||
{
|
||||
uint8_t buf[FLASH_PAGE_SIZE + 32];
|
||||
uint32_t off = FLASH_PAGE_SIZE - 16;
|
||||
int ret;
|
||||
|
||||
memset(buf, 0x5A, sizeof(buf));
|
||||
|
||||
/* Start 16 bytes before a page boundary: the device's page program wraps
|
||||
* within its own page, so the first transfer must stop at the boundary. */
|
||||
ret = spi_flash_write(0x1000 + off, buf, sizeof(buf));
|
||||
|
||||
ck_assert_int_eq(ret, 0);
|
||||
ck_assert_int_eq(program_call_count, 3);
|
||||
ck_assert_uint_eq(program_addrs[0], 0x1000 + off);
|
||||
ck_assert_uint_eq(program_sizes[0], 16);
|
||||
ck_assert_ptr_eq(program_ptrs[0], buf);
|
||||
ck_assert_uint_eq(program_addrs[1], 0x1000 + FLASH_PAGE_SIZE);
|
||||
ck_assert_uint_eq(program_sizes[1], FLASH_PAGE_SIZE);
|
||||
ck_assert_ptr_eq(program_ptrs[1], buf + 16);
|
||||
ck_assert_uint_eq(program_addrs[2], 0x1000 + (FLASH_PAGE_SIZE * 2));
|
||||
ck_assert_uint_eq(program_sizes[2], 16);
|
||||
ck_assert_ptr_eq(program_ptrs[2], buf + 16 + FLASH_PAGE_SIZE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_qspi_write_stops_after_midloop_write_enable_failure)
|
||||
{
|
||||
uint8_t buf[FLASH_PAGE_SIZE * 3];
|
||||
|
|
@ -176,6 +202,7 @@ static Suite *qspi_flash_suite(void)
|
|||
tc = tcase_create("Write");
|
||||
tcase_add_checked_fixture(tc, setup, NULL);
|
||||
tcase_add_test(tc, test_qspi_write_splits_last_page_to_remaining_bytes);
|
||||
tcase_add_test(tc, test_qspi_write_clips_first_page_at_page_boundary);
|
||||
tcase_add_test(tc, test_qspi_write_stops_after_midloop_write_enable_failure);
|
||||
tcase_add_test(tc, test_qspi_read_rejects_address_at_device_size);
|
||||
tcase_add_test(tc, test_qspi_read_rejects_transfer_extending_past_device_size);
|
||||
|
|
|
|||
Loading…
Reference in New Issue