ECC

To increase functional and system reliability, the memories in many device modules and subsystems are protected by Error Correcting Code (ECC), which performs Single Error Correction (SEC) and Double Error Detection (DED). Detected errors are reported via ESM. Single bit errors are corrected, and double bit errors are detected. The ECC Aggregator is connected to these memory and interconnect components which have the ECC. The ECC aggregator provides access to control and monitor the ECC protected memories in a module or subsystem.

SDL provides support for ECC aggregator configuration. Each ECC aggregator instance can be independently configured through the same SDL API by passing a different instance. The safety manual also defines test-for-diagnostics for the various IPs with ECC/parity support. The SDL also provides the support for executing ECC aggregator self-tests, using the error injection feature of the ECC aggregator. The ECC aggregators should be configured at startup, after running BIST.

Features Supported

The SDL provides support for the ECC through:

  • ECC Configuration API

  • ECC self-test API

  • ECC error injection API

  • ECC static register readback API

  • ECC error status APIs

There are 49 ECC aggregators on the device each supporting multiple memories and interconnects.

SysConfig Features

  • None

Features NOT Supported

  • None

Important Usage Guidelines

There are two types of ECC aggregator RAM IDs supported on the device (wrapper and interconnect). The wrapper types are used for memories where local computations are performed for particular processing cores in the device, and the interconnect types are utilized for interconnect bus signals between cores or to/from peripherals.

For wrapper RAM ID types, after injecting an error, the memory associated with that RAM ID needs to be accessed in order to trigger the error interrupt event. It is the application’s responsibility to trigger the error event through memory access after injecting the error.

Example Usage

The following shows an example of SDL ECC API usage by the application to set up the ECC to monitor for errors, as well as how to perform ECC self-test. The ESM should be configured to notify of the desired ECC events for the IPs. Please refer to the TRM for a list of the ESM events.

The following function is required to be defined by the application. It is used by the ECC module to notify the application in case of certain ECC errors that are reported through the R5F exception handlers. If it is not defined, it will result in a linker error. An example implementation is given below.

void SDL_ECC_applicationCallbackFunction(SDL_ECC_MemType eccMemType,
                                         uint32_t errorSrc,
                                         uint32_t address,
                                         uint32_t ramId,
                                         uint64_t bitErrorOffset,
                                         uint32_t bitErrorGroup)
{

    DebugP_log("\r\n  ECC Error Call back function called : eccMemType %d, errorSrc 0x%x, " \
                "address 0x%x, ramId %d, bitErrorOffset 0x%04x%04x, bitErrorGroup %d\n",
                eccMemType, errorSrc, address, ramId, (uint32_t)(bitErrorOffset >> 32),
                (uint32_t)(bitErrorOffset & 0x00000000FFFFFFFF), bitErrorGroup);
    DebugP_log("\r  Take action \n");

    /* Any additional customer specific actions can be added here */

}

Initialization structure for ESM instances

  SDL_ESM_config ECC_Test_esmInitConfig_MAIN =

{ .esmErrorConfig = {1u, 8u}, /* Self test error config / .enableBitmap = {0x00000006u, 0x00000000u, 0x0000000eu, 0x00003000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, }, /**< All events enable: except timer and self test events, and Main ESM output / / Temporarily disabling vim compare error as well/ .priorityBitmap = {0x00000006u, 0x00000000u, 0x0000000eu, 0x00003000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, }, /< All events high priority: except timer, selftest error events, and Main ESM output */ .errorpinBitmap = {0x00000006u, 0x00000000u, 0x0000000eu, 0x00003000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, }, /< All events high priority: except timer, selftest error events, and Main ESM output */ };

SDL_ESM_config ECC_Test_esmInitConfig_MCU = { .esmErrorConfig = {0u, 3u}, /* Self test error config */ .enableBitmap = {0x000c0000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, }, /< All events enable: except clkstop events for unused clocks * and PCIE events */ .priorityBitmap = { 0x000c0000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, }, /< All events high priority: except clkstop events for unused clocks * and PCIE events */ .errorpinBitmap = { 0x000c0000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, }, /**< All events high priority: except clkstop for unused clocks * and PCIE events */ };

To configure ECC for an instance and specified ram IDs: static SDL_ECC_MemSubType ECC_Test_AGGR0_A0subMemTypeList[MAIN_AGGR0_AGGR0_MAX_MEM_SECTIONS] = { SDL_ECC_AGGR0_SAM62A_SEC_HSM_ECC_AGGR_AM62A_MAIN_IPCSS_CBASS_HSM_CLK_2_CLK_EDC_CTRL_CBASS_INT_HSM_CLK_2_BUSECC_RAM_ID, SDL_ECC_AGGR0_SAM62A_SEC_HSM_ECC_AGGR_AM62A_MAIN_CENTRAL_CBASS_HSM_CLK_1_CLK_EDC_CTRL_CBASS_INT_HSM_CLK_1_BUSECC_RAM_ID, };

static SDL_ECC_InitConfig_t ECC_Test_AGGR0A0ECCInitConfig = { .numRams = MAIN_AGGR0_AGGR0_MAX_MEM_SECTIONS, /< Number of Rams ECC is enabled */ .pMemSubTypeList = &(ECC_Test_AGGR0_A0subMemTypeList[0]), /< Sub type list */ };

static SDL_ECC_MemSubType ECC_Test_PSRAM0subMemTypeList[PSRAM0_MAX_MEM_SECTIONS] = { SDL_PSRAMECC1_PSRAM256X32E_ECC_AGGR_PSRAM256X32E_PSRAM0_ECC_RAM_ID, };

static SDL_ECC_InitConfig_t ECC_Test_PSRAM0ECCInitConfig = { .numRams = PSRAM0_MAX_MEM_SECTIONS, /< Number of Rams ECC is enabled */ .pMemSubTypeList = &(ECC_Test_PSRAM0subMemTypeList[0]), /< Sub type list */ };

static SDL_ECC_MemSubType ECC_Test_MCUMCAN1subMemTypeList[MCUMCAN1_MAX_MEM_SECTIONS] = { SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR_MCANSS_MSGMEM_WRAP_MSGMEM_ECC_RAM_ID, };

static SDL_ECC_InitConfig_t ECC_Test_MCUMCAN1ECCInitConfig = { .numRams = MCUMCAN1_MAX_MEM_SECTIONS, /< Number of Rams ECC is enabled */ .pMemSubTypeList = &(ECC_Test_MCUMCAN1subMemTypeList[0]), /< Sub type list */ };

Initialization of ECC

  int32_t ECC_Example_init (void)

{ int32_t retValue=0; void *ptr = (void *)&arg; SDL_ErrType_t result;

   if (retValue == SDL_APP_TEST_PASS) {
       /* Initialize MAIN ESM module */
       result = SDL_ESM_init(SDL_ESM_INST_MAIN_ESM0, &ECC_Test_esmInitConfig_MAIN, SDL_ESM_applicationCallbackFunction, ptr);
       if (result != SDL_APP_TEST_PASS) {
           /* print error and quit */
           DebugP_log("\rECC_Example_init: Error initializing MAIN ESM: result = %d\n\n", result);

           retValue = SDL_APP_TEST_FAILED;
       } else {
           DebugP_log("\rECC_Example_init: Init MAIN ESM complete \n\n");
       }
   }
   if (retValue == SDL_APP_TEST_PASS)
{
       /* Initialize WKUP ESM module */

	result = SDL_ESM_init(SDL_ESM_INST_WKUP_ESM0, &ECC_Test_esmInitConfig_MCU, SDL_ESM_applicationCallbackFunction, ptr);

       if (result != SDL_APP_TEST_PASS) {
           /* print error and quit */
           DebugP_log("\rECC_Example_init: Error initializing WKUP ESM: result = %d\n\n", result);

           retValue = SDL_APP_TEST_FAILED;
       } else {
           DebugP_log("\rECC_Example_init: Init WKUP ESM complete \n\n");
       }
   }
   if (retValue == SDL_APP_TEST_PASS)
{
	/* Initialize AGGR0 SAM62A ECC */
       result = SDL_ECC_init(SDL_ECC_AGGR0_SAM62A_SEC_HSM_ECC_AGGR, &ECC_Test_AGGR0A0ECCInitConfig);
	if (result != SDL_APP_TEST_PASS)
	{
		/* print error and quit */
		DebugP_log("\r\nECC_init: Error initializing SAM62A ECC: result = %d\r\n", result);

		retValue = SDL_APP_TEST_FAILED;
       }
	else {
           DebugP_log("\r\nECC_init: AGGR0 ECC Init complete \r\n");
       }

	/* Initialize PSRAM ECC */
       result = SDL_ECC_init(SDL_PSRAMECC1_PSRAM256X32E_ECC_AGGR, &ECC_Test_PSRAM0ECCInitConfig);
	if (result != SDL_APP_TEST_PASS)
	{
		/* print error and quit */
		DebugP_log("\r\nECC_init: Error initializing PSRAM ECC: result = %d\r\n", result);

		retValue = SDL_APP_TEST_FAILED;
       }
	else {
           DebugP_log("\r\nECC_init: PSRAM ECC Init complete \r\n");
       }

       /* Initialize ECC */
       result = SDL_ECC_init(SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR, &ECC_Test_MCUMCAN1ECCInitConfig);
       if (result != SDL_APP_TEST_PASS)
       {
           /* print error and quit */
           DebugP_log("\r\nECC_init: Error initializing MCU MCAN1 ECC: result = %d\r\n", result);

           retValue = SDL_APP_TEST_FAILED;
       }
       else {
           DebugP_log("\r\nECC_init: MCU MCAN1 ECC Init complete \r\n");
       }
}
   return retValue;

}

Once the ECC is configured, then error notifications will come to the ESM module, and will activate the ESM-registered application callback. The application callback may want to retrive the error information in order to take some action based on the error, like clearing the ECC interrupts, logging the error information, or some other action:

retVal = SDL_ECC_getESMErrorInfo(esmInst, intSrc, &eccmemtype, &eccIntrSrc);

/* Any additional customer specific actions can be added here */
retVal = SDL_ECC_getErrorInfo(eccmemtype, eccIntrSrc, &eccErrorInfo);

To clear and acknowledge the ECC interrupt:

if (eccErrorInfo.injectBitErrCnt != 0)
{
    SDL_ECC_clearNIntrPending(eccmemtype, eccErrorInfo.memSubType, eccIntrSrc, SDL_ECC_AGGR_ERROR_SUBTYPE_INJECT, eccErrorInfo.injectBitErrCnt);
}
else
{
    SDL_ECC_clearNIntrPending(eccmemtype, eccErrorInfo.memSubType, eccIntrSrc, SDL_ECC_AGGR_ERROR_SUBTYPE_NORMAL, eccErrorInfo.bitErrCnt);
}

retVal = SDL_ECC_ackIntr(eccmemtype, eccIntrSrc);

Execute an ECC Self-Test for a specified ECC aggregator (memtype) and RAM Id (subtype):

  /* Note the address is relative to start of ram */

injectErrorConfig.pErrMem = (uint32_t *)(0x04E10000u); result = SDL_ECC_selfTest(SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR, SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR_MCANSS_MSGMEM_WRAP_MSGMEM_ECC_RAM_ID, SDL_INJECT_ECC_ERROR_FORCING_1BIT_ONCE, &injectErrorConfig, 100000);

if (result != SDL_PASS ) {
     DebugP_log("\r\nSingle bit error self test at pErrMem 0x%p test failed\r\n",
                 injectErrorConfig.pErrMem);
    retVal = -1;
} else {

    DebugP_log("\r\nSingle bit error self test at pErrMem 0x%p: test complete\r\n",
                injectErrorConfig.pErrMem);
}

return retVal;
if (result != SDL_PASS ) {
     DebugP_log("\r\nDouble bit error self test at pErrMem 0x%p test failed\r\n",
                 injectErrorConfig.pErrMem);
    retVal = -1;
} else {

    DebugP_log("\r\nDouble bit error self test at pErrMem 0x%p: test complete\r\n",
                injectErrorConfig.pErrMem);
}

return retVal;

Inject an error for a specified ECC aggregator (memtype) and RAM Id (subtype)

  /* Note the address is relative to start of ram */

injectErrorConfig.pErrMem = (uint32_t *)(0x04E10000u);

/* Run one shot test for MCU MCAN1 1 bit error */ injectErrorConfig.flipBitMask = 0x10; result = SDL_ECC_injectError(SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR, SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR_MCANSS_MSGMEM_WRAP_MSGMEM_ECC_RAM_ID, SDL_INJECT_ECC_ERROR_FORCING_1BIT_ONCE, &injectErrorConfig);

if (result != SDL_EFAIL ) {
    DebugP_log("\r\n Error inject at pErrMem 0x%p EFAIL test failed",
                injectErrorConfig.pErrMem);
    retVal = -1;
} else {
    /* Access the memory where injection is expected */
    testLocationValue = injectErrorConfig.pErrMem[0];

    DebugP_log("\r\n Error inject at pErrMem 0x%p: EFAIL test complete",
                injectErrorConfig.pErrMem);
}

return retVal;

Read the Static registers:

  /* Read back the static registers */

result = SDL_ECC_getStaticRegisters(SDL_ECC_AGGR0_SAM62_SEC_ECC_AGGR, &staticRegs);

  /* Read back the static registers */

result = SDL_ECC_getStaticRegisters(SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR, &staticRegs);

if (result != SDL_PASS) {
    /* print error and quit */
    DebugP_log("\r\nECC_Test_init: Error reading the static registers: result = %d\n\n");

    retValue = -1;
} else {
    DebugP_log("\r\nECC_Test_init: M4F Memtype Register Readback successful \n\n");
}

API Reference

Header file contains enumerations, structure definitions and function.

declarations for SDL ECC interface.

Typedefs

typedef uint32_t SDL_ECC_MemSubType

This enumerator indicate ECC memory Sub Type.

typedef void (*SDL_ECC_ErrorCallback_t)(uint32_t errorSrc, uint32_t address)

/brief Format of ECC error Call back function

Enums

enum SDL_ECC_AggregatorType

Values:

enumerator SDL_ECC_AGGR_TYPE_INJECT_ONLY

Ecc aggregator inject only

enumerator SDL_ECC_AGGR_TYPE_FULL_FUNCTION

Ecc aggregator full funtionality

enum SDL_ECC_InjectErrorType

ECC Inject error types.

Values:

enumerator SDL_INJECT_ECC_NO_ERROR

No error

enumerator SDL_INJECT_ECC_ERROR_FORCING_1BIT_ONCE

1-Bit ECC Error forcing once

enumerator SDL_INJECT_ECC_ERROR_FORCING_2BIT_ONCE

2-Bit ECC Error forcing once

enumerator SDL_INJECT_ECC_ERROR_FORCING_1BIT_N_ROW_ONCE

1-Bit ECC Error Force once on next any Ram read

enumerator SDL_INJECT_ECC_ERROR_FORCING_2BIT_N_ROW_ONCE

2-Bit ECC Error Force once on next Ram read

enumerator SDL_INJECT_ECC_ERROR_FORCING_1BIT_REPEAT

1-Bit ECC Error forcing once

enumerator SDL_INJECT_ECC_ERROR_FORCING_2BIT_REPEAT

2-Bit ECC Error forcing once

enumerator SDL_INJECT_ECC_ERROR_FORCING_1BIT_N_ROW_REPEAT

1-Bit ECC Error Force once on next any Ram read

enumerator SDL_INJECT_ECC_ERROR_FORCING_2BIT_N_ROW_REPEAT

2-Bit ECC Error Force once on next Ram read

enum SDL_ECC_RamIdType

Values:

enumerator SDL_ECC_RAM_ID_TYPE_WRAPPER

Ecc RAM ID Wrapper type

enumerator SDL_ECC_RAM_ID_TYPE_INTERCONNECT

Ecc RAM ID Interconnect/CBASS type

Functions

int32_t SDL_ECC_initEsm(const SDL_ESM_Inst esmInstType)

Initializes an module for usage with ECC module.

============================================================================*

Parameters:

esmInstType – Instance of

Returns:

SDL_PASS : Success; SDL_FAIL for failures

int32_t SDL_ECC_init(SDL_ECC_MemType eccMemType, const SDL_ECC_InitConfig_t *pECCInitConfig)

Initializes ECC module for ECC detection.

============================================================================*

Parameters:
  • eccMemType – ECC memory type

  • pECCInitConfig – Pointer to Ecc init configuration

Returns:

SDL_PASS : Success; SDL_FAIL for failuresn

int32_t SDL_ECC_initMemory(SDL_ECC_MemType eccMemType, SDL_ECC_MemSubType memSubType)

Initializes Memory to be ready for ECC error detection. Assumes ECC is already enabled.

============================================================================

Parameters:
  • eccMemType – ECC memory type

  • memSubType – Memory subtype

Returns:

SDL_PASS : Success; SDL_FAIL for failures

int32_t SDL_ECC_selfTest(SDL_ECC_MemType eccMemType, SDL_ECC_MemSubType memSubType, SDL_ECC_InjectErrorType errorType, const SDL_ECC_InjectErrorConfig_t *pECCErrorConfig, uint32_t selfTestTimeOut)

Runs self test by injecting and error and monitor response Assumes ECC is already enabled.

============================================================================

Parameters:
  • eccMemType – ECC memory type

  • memSubType – Memory subtype

  • errorType – ECC Self test type

  • pECCErrorConfig – Pointer to Error configuration

  • selfTestTimeOut – Number of retries before time out

Returns:

SDL_PASS : Success; SDL_FAIL for failures

int32_t SDL_ECC_injectError(SDL_ECC_MemType eccMemType, SDL_ECC_MemSubType memSubType, SDL_ECC_InjectErrorType errorType, const SDL_ECC_InjectErrorConfig_t *pECCErrorConfig)

Injects ECC error at specified location Assumes ECC is already enabled.

============================================================================

Parameters:
  • eccMemType – ECC memory type

  • memSubType – Memory subtype

  • errorType – ECC error type

  • pECCErrorConfig – Pointer to Error configuration

Returns:

SDL_PASS : Success; SDL_FAIL for failures

int32_t SDL_ECC_getStaticRegisters(SDL_ECC_MemType eccMemType, SDL_ECC_staticRegs *pStaticRegs)

Gets the static registers for the specified ECC instance.

============================================================================

Parameters:
  • eccMemType – ECC memory type

  • pStaticRegs – Pointer to Static registers structure

Returns:

SDL_PASS : Success; SDL_FAIL for failures

int32_t SDL_ECC_getErrorInfo(SDL_ECC_MemType eccMemType, SDL_Ecc_AggrIntrSrc intrSrc, SDL_ECC_ErrorInfo_t *pErrorInfo)

Retrieves the ECC error information for the specified memtype and interrupt source.

============================================================================

Parameters:
  • eccMemType – ECC memory type

  • intrSrc – interrupt source

  • pErrorInfo – Pointer to the Error Information

Returns:

SDL_PASS : Success; SDL_FAIL for failures

int32_t SDL_ECC_ackIntr(SDL_ECC_MemType eccMemType, SDL_Ecc_AggrIntrSrc intrSrc)

Acknowledge the ECC interrupt.

============================================================================

Parameters:
  • eccMemType – ECC memory type

  • intrSrc – interrupt source

Returns:

SDL_PASS : Success; SDL_FAIL for failures

int32_t SDL_ECC_getESMErrorInfo(SDL_ESM_Inst instance, uint32_t intSrc, SDL_ECC_MemType *eccMemType, SDL_Ecc_AggrIntrSrc *intrSrcType)

Retrieves the ECC error information for the specified ESM error. If it isn’t an ECC error or the ECC error is not supported an error is returned.

============================================================================

Parameters:
  • instance – ESM instance

  • intSrc – ESM interrupt number

  • eccMemType – Pointer to the ECC memory type

  • intrSrcType – Pointer to the interrupt source type

Returns:

SDL_PASS : Success; SDL_FAIL for failures

int32_t SDL_ECC_clearNIntrPending(SDL_ECC_MemType eccMemType, SDL_ECC_MemSubType memSubType, SDL_Ecc_AggrIntrSrc intrSrc, SDL_Ecc_AggrEDCErrorSubType subType, uint32_t numEvents)

Clears N pending interrupts for the specified memtype, subtype and interrupt source.

============================================================================

Parameters:
  • eccMemType – ECC memory type

  • memSubType – Memory subtype

  • intrSrc – interrupt source

  • subType – error subtype (valid for EDC types only)

  • numEvents – number of pending interrupts to clear

Returns:

SDL_PASS : Success; SDL_FAIL for failures

struct SDL_ECC_InitConfig_t
#include <sdl_ecc.h>

Public Members

uint32_t numRams

Max number of memory sections ECC is enabled on R5F, the memory sections include ATCM, VIM, BTCM RAMs

SDL_ECC_MemSubType *pMemSubTypeList

Pointer to list of Vector ID types of ECC enabled memory sections

struct SDL_ECC_InjectErrorConfig_t
#include <sdl_ecc.h>

Public Members

uint32_t *pErrMem

Address to inject error

uint32_t flipBitMask

Bit location to flip bits

uint16_t chkGrp

Group checker (for Interconnect RAM ID’s only)

struct SDL_ECC_ErrorInfo_t
#include <sdl_ecc.h>

Public Members

SDL_ECC_MemType eccMemType

ECC Memory type

SDL_ECC_MemSubType memSubType

Memory subtype

SDL_Ecc_AggrIntrSrc intrSrc

Interrupt source

uint32_t bitErrCnt

bit error count for the interrupt source. 0-2 Number of errors, 3 means 3 or more errors.

uint32_t injectBitErrCnt

inject bit error count for the interrupt source (valid for EDC only). 0-2 Number of errors, 3 means 3 or more errors.

uint32_t bitErrorGroup

bit error group. Indicates the Checker Group where the error occurred.

uint64_t bitErrorOffset

bit error offset