@@ -262,6 +262,7 @@ static const ARM_STORAGE_INFO info = {
262262 * This is the command code written into the first FCCOB register, FCCOB0.
263263 */
264264enum 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+
436465static 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 */
554602static 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
562608static 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