Hi,
we are working on a S32K142 and try to force and test the behavior on double ECC errors in Flash memory. We refer to S32K1xx Series Reference Manual, Rev. 13, 04/2020 chapter 35.1.3.1 ECC Implementation for NVM (for S32K14x devices):
Any single-bit ECC errors are automatically corrected, and any double-bit ECC errors are
reflected onto FERSTAT[DFDIF] flag at the read access from Data Flash or Program
Flash. When the double-bit ECC error has occurred, the flash controller reports the error
to the AHB which causes a bus fault. If Bus fault interrupt is not enabled, the error is
handled by the Hard fault. After servicing the Bus fault (if enabled), the Double Bit Fault
Detect Interrupt is serviced (if enabled).
Out assumption is, that the reporting of a double ECC error to AHB is done independent of activation or deactivation of the Flash Double Bit Fault Detect Interrupt (FERCNFG.DFDIE). Is that correct?
We are trying to force the error using the FERCNFG.FDFD bit and observe the following behavior:
1. When FERCNFG.DFDIE = 0 (Flash Double Bit Fault Detect Interrupt disabled), after forcing the error (FERCNFG.FDFD = 1) and access the Flash by instruction fetches or direct reads, neither a Bus Fault nor an escallated Hardfauld occurs ever.
2. When FERCNFG.DFDIE = 1 (Flash Double Bit Fault Detect Interrupt enabled), after forcing the error (FERCNFG.FDFD = 1) and access the Flash by instruction fetches or direct reads, the Flash Double Bit Fault Detect Interrupt is executed but we never see a Bus Fault or an escalated Hardfault.
We are using S32DS with S32K142_SDK 4.0.2 with GCC 6.3 and test on a S32K142 EVB. Please find a code snipped, how we try to force the Exception. Instruction Cache is disabled.
#include "sdk_project_config.h"
flash_ssd_config_t flashSsdConfig;
void HardFault_Handler(void)
{
while(1)
{
}
}
void BusFault_Handler(void)
{
while(1)
{
}
}
void FTFC_Fault_IRQHandler(void)
{
FLASH_DRV_ForceDoubleBitFaultDetectCmd(false);
FLASH_DRV_ClearDoubleBitFaultFlag();
// while(1)
// {
// }
}
int main(void)
{
status_t status;
uint32_t flashStart;
volatile uint8_t flashRead;
status = CLOCK_DRV_Init(g_clockManConfigsArr[0]);
status = FLASH_DRV_Init(&Flash_InitConfig0, &flashSsdConfig);
#if 1
// Test 1: do not enable the ECC error interrupt of flash controller
// FLASH_DRV_EnableDoubleBitFaultInterupt();
#else
// Test 2: enable the ECC error interrupt of flash controller
FLASH_DRV_EnableDoubleBitFaultInterupt();
#endif
// activate force ECC error on next read from flash
FLASH_DRV_ForceDoubleBitFaultDetectCmd(true);
// fetch instructions from code flash to force ECC error
__asm("nop");
__asm("nop");
__asm("nop");
__asm("nop");
__asm("nop");
__asm("nop");
// read from 256k flash to force ECC error
volatile uint8_t* pFlash = (volatile uint8_t*)0x0;
for(uint32_t i = 0; i < 0x40000; i++)
{
flashRead = *pFlash++;
}
while(1)
{
}
}
We hope that anybody can clarify the behavior for us or to point on the thing we are missing here.
Thanks in advance for your help and best regards,
Dom