Skip to content

Commit 9182b6d

Browse files
author
Rohit Grover
committed
erase-optimization: check sectors for all-1s before launching erase
With this change, we check for all-1s before executing erase. This means that the cost of erasing a range is now proportional to the amount of sectors which have been programmed. This should result in latency improvements in our use of containers based on flash storage.
1 parent 1efb48f commit 9182b6d

File tree

1 file changed

+84
-10
lines changed

1 file changed

+84
-10
lines changed

hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ static const ARM_STORAGE_INFO info = {
262262
* This is the command code written into the first FCCOB register, FCCOB0.
263263
*/
264264
enum FlashCommandOps {
265+
RD1SEC = (uint8_t)0x01, /* read 1s section */
265266
PGM8 = (uint8_t)0x07, /* program phrase */
266267
ERSBLK = (uint8_t)0x08, /* erase block */
267268
ERSSCR = (uint8_t)0x09, /* erase flash sector */
@@ -433,6 +434,34 @@ static inline void setupAddressInCCOB123(uint64_t addr)
433434
}
434435
#endif /* ifndef USING_KSDK2 */
435436

437+
static inline void setupRead1sSection(uint64_t addr, size_t cnt)
438+
{
439+
#ifdef USING_KSDK2
440+
kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(RD1SEC, addr);
441+
kFCCOBx[1] = BYTES_JOIN_TO_WORD_2_1_1(cnt >> 4, 0 /* normal read level */, 0);
442+
#else
443+
BW_FTFE_FCCOB0_CCOBn((uintptr_t)FTFE, RD1SEC);
444+
setupAddressInCCOB123(addr);
445+
BW_FTFE_FCCOB4_CCOBn((uintptr_t)FTFE, ((cnt >> 4) >> 8) & 0xFFUL); /* bits [15:8] of cnt in units of 128-bits. */
446+
BW_FTFE_FCCOB5_CCOBn((uintptr_t)FTFE, ((cnt >> 4) >> 0) & 0xFFUL); /* bits [7:0] of cnt in units of 128-bits. */
447+
BW_FTFE_FCCOB6_CCOBn((uintptr_t)FTFE, 0); /* use normal read level for 1s. */
448+
#endif
449+
}
450+
451+
static inline bool currentCommandByteIsRD1SEC(void)
452+
{
453+
#ifdef USING_KSDK2
454+
return ((kFCCOBx[0] >> 24) == RD1SEC);
455+
#else
456+
return (BR_FTFE_FCCOB0_CCOBn((uintptr_t)FTFE) == RD1SEC);
457+
#endif
458+
}
459+
460+
static inline bool currentCommandSetupIsAnEraseCheck(const struct mtd_k64f_data *context)
461+
{
462+
return ((context->currentCommand == ARM_STORAGE_OPERATION_ERASE) && currentCommandByteIsRD1SEC());
463+
}
464+
436465
static inline void setupEraseSector(uint64_t addr)
437466
{
438467
#ifdef USING_KSDK2
@@ -547,16 +576,33 @@ static inline void setupNextProgramData(struct mtd_k64f_data *context)
547576
}
548577
}
549578

579+
/* Setup a command to determine if erase is needed for the range
580+
* [context->currentOperatingStorageAddress, context->currentOperatingStorageAddress + ERASE_UNIT).
581+
* If any byte within the range isn't 0xFF, this command results in a run-time
582+
* error.
583+
*
584+
* Upon launch, if any byte within the given range isn't 0xFF then this command
585+
* will terminate in a run-time error.
586+
*/
587+
static inline void setupNextEraseCheck(const struct mtd_k64f_data *context)
588+
{
589+
setupRead1sSection(context->currentOperatingStorageAddress, ERASE_UNIT); /* setup check for erased */
590+
}
591+
592+
static inline void progressEraseContextByEraseUnit(struct mtd_k64f_data *context)
593+
{
594+
context->amountLeftToOperate -= ERASE_UNIT;
595+
context->currentOperatingStorageAddress += ERASE_UNIT;
596+
}
597+
550598
/**
551599
* Advance the state machine for erase. This function is called only if
552600
* amountLeftToOperate is non-zero.
553601
*/
554602
static inline void setupNextErase(struct mtd_k64f_data *context)
555603
{
556604
setupEraseSector(context->currentOperatingStorageAddress); /* Program FCCOB to load the required command parameters. */
557-
558-
context->amountLeftToOperate -= ERASE_UNIT;
559-
context->currentOperatingStorageAddress += ERASE_UNIT;
605+
progressEraseContextByEraseUnit(context);
560606
}
561607

562608
static int32_t executeCommand(struct mtd_k64f_data *context)
@@ -591,7 +637,10 @@ static int32_t executeCommand(struct mtd_k64f_data *context)
591637
return ARM_DRIVER_ERROR_PARAMETER;
592638
}
593639
if (failedWithRunTimeError()) {
594-
return ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE;
640+
/* filter away run-time errors which may legitimately arise from an erase-check operation. */
641+
if (!currentCommandSetupIsAnEraseCheck(context)) {
642+
return ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE;
643+
}
595644
}
596645

597646
/* signal synchronous completion. */
@@ -607,11 +656,22 @@ static int32_t executeCommand(struct mtd_k64f_data *context)
607656
break;
608657

609658
case ARM_STORAGE_OPERATION_ERASE:
659+
if (currentCommandSetupIsAnEraseCheck(context)) {
660+
if (failedWithRunTimeError()) {
661+
/* a run-time failure from an erase-check indicates at an erase operation is necessary */
662+
setupNextErase(context);
663+
/* continue on to the next iteration of the parent loop */
664+
break;
665+
} else {
666+
/* erase can be skipped since this sector is already erased. */
667+
progressEraseContextByEraseUnit(context);
668+
}
669+
}
610670
if (context->amountLeftToOperate == 0) {
611671
return context->sizeofCurrentOperation;
612672
}
613673

614-
setupNextErase(context); /* start the successive erase operation */
674+
setupNextEraseCheck(context); /* start the erase check on the successive erase sector */
615675
/* continue on to the next iteration of the parent loop */
616676
break;
617677

@@ -653,10 +713,13 @@ static void ftfe_ccie_irq_handler(void)
653713
return;
654714
}
655715
if (failedWithRunTimeError()) {
656-
if (context->commandCompletionCallback) {
657-
context->commandCompletionCallback(ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE, context->currentCommand);
716+
/* filter away run-time errors which may legitimately arise from an erase-check operation. */
717+
if (!currentCommandSetupIsAnEraseCheck(context)) {
718+
if (context->commandCompletionCallback) {
719+
context->commandCompletionCallback(ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE, context->currentCommand);
720+
}
721+
return;
658722
}
659-
return;
660723
}
661724

662725
switch (context->currentCommand) {
@@ -674,14 +737,25 @@ static void ftfe_ccie_irq_handler(void)
674737
break;
675738

676739
case ARM_STORAGE_OPERATION_ERASE:
740+
if (currentCommandSetupIsAnEraseCheck(context)) {
741+
if (failedWithRunTimeError()) {
742+
/* a run-time failure from an erase-check indicates at an erase operation is necessary */
743+
setupNextErase(context);
744+
launchCommandFromIRQ(context);
745+
break;
746+
} else {
747+
/* erase can be skipped since this sector is already erased. */
748+
progressEraseContextByEraseUnit(context);
749+
}
750+
}
677751
if (context->amountLeftToOperate == 0) {
678752
if (context->commandCompletionCallback) {
679753
context->commandCompletionCallback(context->sizeofCurrentOperation, ARM_STORAGE_OPERATION_ERASE);
680754
}
681755
return;
682756
}
683757

684-
setupNextErase(context);
758+
setupNextEraseCheck(context); /* start the erase check on the successive erase sector */
685759
launchCommandFromIRQ(context);
686760
break;
687761

@@ -915,7 +989,7 @@ static int32_t erase(uint64_t addr, uint32_t size)
915989
context->amountLeftToOperate = size;
916990

917991
clearErrorStatusBits();
918-
setupNextErase(context);
992+
setupNextEraseCheck(context);
919993
return executeCommand(context);
920994
}
921995

0 commit comments

Comments
 (0)