From a0085fcfe1f4d8253cead0db86b714f0099ffae8 Mon Sep 17 00:00:00 2001 From: Richard Li Date: Fri, 24 Jul 2026 14:28:39 +0800 Subject: [PATCH 1/3] Fixes can further reduce wearing level --- radio/src/drivers/frftl.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/radio/src/drivers/frftl.cpp b/radio/src/drivers/frftl.cpp index e6d27d49799..66245ace697 100644 --- a/radio/src/drivers/frftl.cpp +++ b/radio/src/drivers/frftl.cpp @@ -159,6 +159,11 @@ static PhysicalPageState getPhysicalPageState(FrFTL* ftl, static void setPhysicalPageState(FrFTL* ftl, uint16_t physicalPageNo, PhysicalPageState state) { + if (state == ERASE_REQUIRED) { + if (ftl->callbacks->isFlashErased(physicalPageNo * PAGE_SIZE)) { + state = ERASED; + } + } uint32_t idx = physicalPageNo >> 4; uint32_t mask = 0x3 << ((physicalPageNo & 0xf) * 2); ftl->physicalPageState[idx] &= ~mask; @@ -549,10 +554,10 @@ static bool quickErase(FrFTL* ftl, uint32_t addr) { const FrFTLOps* cb = ftl->callbacks; + uint16_t ppn = addr / PAGE_SIZE; if ((addr & BLOCK_MASK) == 0) { // Block aligned - uint16_t ppn = addr / PAGE_SIZE; uint8_t count = 0; bool hasUsed = false; @@ -578,7 +583,11 @@ static bool quickErase(FrFTL* ftl, uint32_t addr) return ret; } } - return cb->flashErase(addr); + if (cb->flashErase(addr)) { + setPhysicalPageState(ftl, ppn, ERASED); + return true; + } + return false; } static bool programPage(FrFTL* ftl, PageBuffer* buffer, bool doErase) @@ -777,7 +786,7 @@ bool ftlSync(FrFTL* ftl) bool ftlWrite(FrFTL* ftl, uint32_t startSectorNo, uint32_t noOfSectors, const uint8_t* buf) { - resolveUnknownState(ftl, ftl->ttPageCount); + resolveUnknownState(ftl, ftl->ttPageCount > 16 ? ftl->ttPageCount : 16); if (startSectorNo + noOfSectors > ftl->usableSectorCount) { return false; } @@ -867,7 +876,6 @@ bool ftlWrite(FrFTL* ftl, uint32_t startSectorNo, uint32_t noOfSectors, bool ftlRead(FrFTL* ftl, uint32_t sectorNo, uint8_t* buffer) { - // doGC(ftl, ftl->ttPageCount, 1); if (sectorNo >= ftl->usableSectorCount) { return false; } @@ -893,7 +901,7 @@ bool ftlRead(FrFTL* ftl, uint32_t sectorNo, uint8_t* buffer) bool ftlTrim(FrFTL* ftl, uint32_t startSectorNo, uint32_t noOfSectors) { - resolveUnknownState(ftl, ftl->ttPageCount); + resolveUnknownState(ftl, ftl->ttPageCount > 16 ? ftl->ttPageCount : 16); if (startSectorNo + noOfSectors > ftl->usableSectorCount) { return false; } From f65aae1d81bbca4517b6e7e01c4feaba9fd085f3 Mon Sep 17 00:00:00 2001 From: Richard Li Date: Fri, 24 Jul 2026 15:43:19 +0800 Subject: [PATCH 2/3] Better fix --- radio/src/drivers/frftl.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/radio/src/drivers/frftl.cpp b/radio/src/drivers/frftl.cpp index 66245ace697..3e301a9486e 100644 --- a/radio/src/drivers/frftl.cpp +++ b/radio/src/drivers/frftl.cpp @@ -171,7 +171,6 @@ static void setPhysicalPageState(FrFTL* ftl, uint16_t physicalPageNo, ((state & 0x3) << ((physicalPageNo & 0xf) * 2)); } - static const uint16_t crc16_ccitt_start = 0xFFFF; static inline uint16_t crc16_x25_ccitt(const void* buf, uint32_t len) { @@ -196,9 +195,8 @@ static void resolveUnknownState(FrFTL* ftl, uint16_t count) const FrFTLOps* cb = ftl->callbacks; for (uint16_t i = 0; i < ftl->physicalPageCount; i++) { if (getPhysicalPageState(ftl, idx) == UNKNOWN) { - PhysicalPageState state = - cb->isFlashErased(idx * PAGE_SIZE) ? ERASED : ERASE_REQUIRED; - setPhysicalPageState(ftl, idx, state); + // Will detect automatically whether a erase is really required + setPhysicalPageState(ftl, idx, ERASE_REQUIRED); count--; if (count == 0) { earlyEnd = true; @@ -1192,6 +1190,7 @@ bool ftlInit(FrFTL* ftl, const FrFTLOps* cb, uint16_t flashSizeInMB) memset(ftl->physicalPageState, 0, stateSize * sizeof(uint32_t)); createFTL(ftl); } + return true; } From f0ec8dbcab9957faed4b76c99d066fbc4877caa5 Mon Sep 17 00:00:00 2001 From: Richard Li Date: Sat, 25 Jul 2026 14:04:30 +0800 Subject: [PATCH 3/3] Fixed some potential bugs --- radio/src/drivers/frftl.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/radio/src/drivers/frftl.cpp b/radio/src/drivers/frftl.cpp index 3e301a9486e..800b82ef3a0 100644 --- a/radio/src/drivers/frftl.cpp +++ b/radio/src/drivers/frftl.cpp @@ -192,7 +192,6 @@ static void resolveUnknownState(FrFTL* ftl, uint16_t count) uint16_t idx = ftl->writeFrontier; bool earlyEnd = false; - const FrFTLOps* cb = ftl->callbacks; for (uint16_t i = 0; i < ftl->physicalPageCount; i++) { if (getPhysicalPageState(ftl, idx) == UNKNOWN) { // Will detect automatically whether a erase is really required @@ -698,11 +697,17 @@ static bool lockTTPages(FrFTL* ftl, uint16_t logicalPageNo) } ttBuffer = loadPhysicalPageInBuffer(ftl, ttPageNo, ttPageInfo.physicalPageNo); + if (!ttBuffer) { + return false; + } ttBuffer->lock = LOCKED; ttBuffer->pMode = RELOCATE_ERASE_PROGRAM; if (ttPageNo > 0) { // TT page not MTT page, need to lock MTT page as well ttBuffer = loadPhysicalPageInBuffer(ftl, 0, ftl->mttPhysicalPageNo); + if (!ttBuffer) { + return false; + } ttBuffer->lock = LOCKED; ttBuffer->pMode = RELOCATE_ERASE_PROGRAM; } @@ -785,7 +790,8 @@ bool ftlWrite(FrFTL* ftl, uint32_t startSectorNo, uint32_t noOfSectors, const uint8_t* buf) { resolveUnknownState(ftl, ftl->ttPageCount > 16 ? ftl->ttPageCount : 16); - if (startSectorNo + noOfSectors > ftl->usableSectorCount) { + if (startSectorNo > ftl->usableSectorCount || + noOfSectors > ftl->usableSectorCount - startSectorNo) { return false; } @@ -805,7 +811,9 @@ bool ftlWrite(FrFTL* ftl, uint32_t startSectorNo, uint32_t noOfSectors, // Read page info PageInfo pageInfo; - readPageInfo(ftl, &pageInfo, logicalPageNo); + if (!readPageInfo(ftl, &pageInfo, logicalPageNo)) { + return false; + } PageBuffer* dataBuffer; // Allocate new physical page for uninitialized logical page @@ -883,7 +891,9 @@ bool ftlRead(FrFTL* ftl, uint32_t sectorNo, uint8_t* buffer) // Read page info PageInfo pageInfo; - readPageInfo(ftl, &pageInfo, logicalPageNo); + if (!readPageInfo(ftl, &pageInfo, logicalPageNo)) { + return false; + } // Check if sector written before uint8_t sectMask = 1 << pageSectorNo; @@ -900,7 +910,8 @@ bool ftlRead(FrFTL* ftl, uint32_t sectorNo, uint8_t* buffer) bool ftlTrim(FrFTL* ftl, uint32_t startSectorNo, uint32_t noOfSectors) { resolveUnknownState(ftl, ftl->ttPageCount > 16 ? ftl->ttPageCount : 16); - if (startSectorNo + noOfSectors > ftl->usableSectorCount) { + if (startSectorNo > ftl->usableSectorCount || + noOfSectors > ftl->usableSectorCount - startSectorNo) { return false; } @@ -920,7 +931,9 @@ bool ftlTrim(FrFTL* ftl, uint32_t startSectorNo, uint32_t noOfSectors) // Read page info PageInfo pageInfo; - readPageInfo(ftl, &pageInfo, logicalPageNo); + if (!readPageInfo(ftl, &pageInfo, logicalPageNo)) { + return false; + } // Check if physical page in used if (pageInfo.physicalPageNo != 0xffff) {