> work around on ECC bit not becoming active : DBECCERR)
Aha, so you suspect ECC bit not becoming active, due to two-bit errors?
→ indeed :-)
> To return from the busfault handler, we needed some assembly code to have a recovery pointer.
This and filling the info in the g_fault_... variables is not included in the shown code. Is it already written? Does it run and reveal something about the reason of the fault?
→ the main reason / cause of the issue, the bits not becoming active we actually did not found / could not verify.
→ we call this a work around because in the bus fault handler we can read g_fault_sr2 and g_fault_ecc2
#include "flash_probe.h"
void BusFault_Handler_C(uint32_t *stack);
__asm void BusFault_Handler(void)
{
IMPORT BusFault_Handler_C
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B BusFault_Handler_C
}
void BusFault_Handler_C(uint32_t *stack)
{
if (g_flash_probe_active)
{
g_fault_cfsr = SCB->CFSR;
g_fault_hfsr = SCB->HFSR;
if (SCB->CFSR & SCB_CFSR_BFARVALID_Msk)
{
g_fault_bfar = SCB->BFAR;
}
g_fault_sr2 = FLASH->SR2;
g_fault_ecc2 = FLASH->ECC_FA2;
g_flash_probe_active = 0;
g_flash_probe_failed = 1;
/*
Clear BusFault bits.
CFSR bits are write-1-to-clear.
*/
SCB->CFSR = SCB_CFSR_IBUSERR_Msk |
SCB_CFSR_PRECISERR_Msk |
SCB_CFSR_IMPRECISERR_Msk |
SCB_CFSR_UNSTKERR_Msk |
SCB_CFSR_STKERR_Msk |
SCB_CFSR_LSPERR_Msk |
SCB_CFSR_BFARVALID_Msk;
//#ifdef FLASH_CCR_CLR_DBECCERR
FLASH->CCR2 = FLASH_CCR_CLR_DBECCERR |
FLASH_CCR_CLR_SNECCERR;
//#endif
/*
stack[6] is the stacked PC.
Redirect execution to the assembly recovery label.
*/
stack[6] = g_flash_probe_recovery_pc;
__DSB();
__ISB();
return;
}
while (1)
{
/*
Unexpected BusFault.
Do not try to recover.
*/
}
}
The “corrupt code” check.. where we can check if the sector faults are properly set (because now we can trust on them)
#include "flash_probe.h"
void flash_bank2_corrupt_check(uint32_t a_start_addr, uint32_t a_size)
{
// Clear old Bank 2 ECC / CRC-related flags first
FLASH->CCR2 = FLASH_CCR_CLR_EOP
| FLASH_CCR_CLR_WRPERR
| FLASH_CCR_CLR_PGSERR
| FLASH_CCR_CLR_STRBERR
| FLASH_CCR_CLR_INCERR
| FLASH_CCR_CLR_OPERR
| FLASH_CCR_CLR_RDPERR
| FLASH_CCR_CLR_RDSERR
| FLASH_CCR_CLR_SNECCERR
| FLASH_CCR_CLR_DBECCERR
| FLASH_CCR_CLR_CRCEND
| FLASH_CCR_CLR_CRCRDERR;
//Enable BusFault:
SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
//Read the entire sector in 32-byte increments:
g_fault_sr2 = 0; //
g_fault_ecc2 = 0;
g_fault_cfsr = 0;
g_fault_hfsr = 0;
g_fault_bfar = 0;
uint32_t sector_end = a_start_addr+a_size;//0x08200000;
for (uint32_t addr = a_start_addr; addr < sector_end; addr += 32) //The test need to be done only every 32 bytes
{
uint32_t dummy;
if (!Flash_TryRead32(addr, &dummy))
{
// addr is inside a failing 32-byte ECC flash word
if ((g_fault_sr2 & (/*FLASH_FLAG_SNECCERR_BANK2 |*/ FLASH_FLAG_DBECCERR_BANK2)) && g_fault_ecc2)
{
uint8_t i = GetSector(FLASH_BANK2_BASE + (g_fault_ecc2*32)); //eg. 0x00006000 => 0x08100000 + (0x00006000 *32) => 0x081c0000
if (i>=FLASH_SECTOR_TOTAL)
{ //unvalid sector nr
#ifdef __TARGET_DEBUG__
/* Infinite loop */
Error_Handler();//while (1);
#else
;
#endif
}
else
{
sys_flash_ECC_failures_sector_bits_on_bank[1] |= (1<<i);
}
}
break;
}
}
}
#endif
You haven’t answered about possibility of writing same flash location twice.
→ this is not relevant for us :-)
I hope this post makes it more clear of how the issue is tackled.