fix tc3xx HAL to properly handle flash writes across sector boundariese

pull/569/head
Brett Nicholas 2025-04-29 10:03:08 -06:00 committed by Daniele Lacamera
parent 8ae5ec27ff
commit 21a726ab46
1 changed files with 51 additions and 37 deletions

View File

@ -364,52 +364,66 @@ void hal_init(void)
*/ */
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t* data, int size) int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t* data, int size)
{ {
/* base address of containing sector (TODO what if size spans sectors?) const IfxFlash_FlashType type = getFlashTypeFromAddr(address);
*/ uint32_t currentAddress = address;
const uint32_t sectorAddress = GET_SECTOR_ADDR(address); int remainingSize = size;
const IfxFlash_FlashType type = getFlashTypeFromAddr(address); int bytesWrittenTotal = 0;
/* Determine the range of pages affected */
const uint32_t startPage = GET_PAGE_ADDR(address);
const uint32_t endPage = GET_PAGE_ADDR(address + size - 1);
uint32_t page;
/* Flag to check if sector read-modify-write is necessary */
int needsSectorRmw;
LED_ON(LED_PROG); LED_ON(LED_PROG);
/* Check if any page within the range is not erased */ /* Process the data sector by sector */
needsSectorRmw = 0; while (remainingSize > 0) {
for (page = startPage; page <= endPage; uint32_t currentSectorAddress = GET_SECTOR_ADDR(currentAddress);
page += IFXFLASH_PFLASH_PAGE_LENGTH) { uint32_t offsetInSector = currentAddress - currentSectorAddress;
if (!flashIsErased(page, IFXFLASH_PFLASH_PAGE_LENGTH, type)) { uint32_t bytesInThisSector = WOLFBOOT_SECTOR_SIZE - offsetInSector;
needsSectorRmw = 1;
break; /* Adjust bytes to write if this would overflow the current sector */
if (bytesInThisSector > remainingSize) {
bytesInThisSector = remainingSize;
} }
}
/* If a page within the range is erased, we need to read-modify-write the /* Determine the range of pages affected in this sector */
* whole sector */ const uint32_t startPage = GET_PAGE_ADDR(currentAddress);
if (needsSectorRmw) { const uint32_t endPage =
size_t offsetInSector; GET_PAGE_ADDR(currentAddress + bytesInThisSector - 1);
uint32_t page;
int needsSectorRmw = 0;
/* Read entire sector into RAM */ /* Check if any page within the range is not erased */
cacheSector(sectorAddress, type); for (page = startPage; page <= endPage;
page += IFXFLASH_PFLASH_PAGE_LENGTH) {
if (!flashIsErased(page, IFXFLASH_PFLASH_PAGE_LENGTH, type)) {
needsSectorRmw = 1;
break;
}
}
/* Erase the entire sector */ /* If a page within the range is not erased, we need to
hal_flash_erase(sectorAddress, WOLFBOOT_SECTOR_SIZE); * read-modify-write the sector */
if (needsSectorRmw) {
/* Read entire sector into RAM */
cacheSector(currentSectorAddress, type);
/* Modify the relevant part of the RAM sector buffer */ /* Erase the entire sector */
offsetInSector = address - sectorAddress; hal_flash_erase(currentSectorAddress, WOLFBOOT_SECTOR_SIZE);
memcpy((uint8_t*)sectorBuffer + offsetInSector, data, size);
/* Program the modified sector back into flash */ /* Modify the relevant part of the RAM sector buffer */
programCachedSector(sectorAddress, type); memcpy((uint8_t*)sectorBuffer + offsetInSector,
} data + bytesWrittenTotal, bytesInThisSector);
else {
/* All affected pages are erased, program the data directly */ /* Program the modified sector back into flash */
programBytesToErasedFlash(address, data, size, type); programCachedSector(currentSectorAddress, type);
}
else {
/* All affected pages are erased, program the data directly */
programBytesToErasedFlash(currentAddress, data + bytesWrittenTotal,
bytesInThisSector, type);
}
/* Update pointers and counters */
bytesWrittenTotal += bytesInThisSector;
currentAddress += bytesInThisSector;
remainingSize -= bytesInThisSector;
} }
LED_OFF(LED_PROG); LED_OFF(LED_PROG);