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
Features NOT Supported
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.
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);
}
Initialization structure for ESM instances
{
.enableBitmap = {0x00000006u, 0x00000000u, 0x0000000eu, 0x00003000u,
0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
},
.priorityBitmap = {0x00000006u, 0x00000000u, 0x0000000eu, 0x00003000u,
0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
},
.errorpinBitmap = {0x00000006u, 0x00000000u, 0x0000000eu, 0x00003000u,
0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
},
};
{
.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,
},
.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,
},
.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,
},
};
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,
};
{
.
numRams = MAIN_AGGR0_AGGR0_MAX_MEM_SECTIONS,
.pMemSubTypeList = &(ECC_Test_AGGR0_A0subMemTypeList[0]),
};
{
SDL_PSRAMECC1_PSRAM256X32E_ECC_AGGR_PSRAM256X32E_PSRAM0_ECC_RAM_ID,
};
{
.
numRams = PSRAM0_MAX_MEM_SECTIONS,
.pMemSubTypeList = &(ECC_Test_PSRAM0subMemTypeList[0]),
};
{
SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR_MCANSS_MSGMEM_WRAP_MSGMEM_ECC_RAM_ID,
};
{
.
numRams = MCUMCAN1_MAX_MEM_SECTIONS,
.pMemSubTypeList = &(ECC_Test_MCUMCAN1subMemTypeList[0]),
};
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) {
if (result != SDL_APP_TEST_PASS) {
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)
{
if (result != SDL_APP_TEST_PASS) {
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)
{
result =
SDL_ECC_init(SDL_ECC_AGGR0_SAM62A_SEC_HSM_ECC_AGGR, &ECC_Test_AGGR0A0ECCInitConfig);
if (result != SDL_APP_TEST_PASS)
{
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");
}
result =
SDL_ECC_init(SDL_PSRAMECC1_PSRAM256X32E_ECC_AGGR, &ECC_Test_PSRAM0ECCInitConfig);
if (result != SDL_APP_TEST_PASS)
{
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");
}
result =
SDL_ECC_init(SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR, &ECC_Test_MCUMCAN1ECCInitConfig);
if (result != SDL_APP_TEST_PASS)
{
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:
To clear and acknowledge the ECC interrupt:
if (eccErrorInfo.injectBitErrCnt != 0)
{
}
else
{
}
Execute an ECC Self-Test for a specified ECC aggregator (memtype) and RAM Id (subtype):
injectErrorConfig.pErrMem = (uint32_t *)(0x04E10000u);
SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR_MCANSS_MSGMEM_WRAP_MSGMEM_ECC_RAM_ID,
&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;
Inject an error for a specified ECC aggregator (memtype) and RAM Id (subtype)
injectErrorConfig.pErrMem = (uint32_t *)(0x04E10000u);
injectErrorConfig.flipBitMask = 0x10;
SDL_MCU_MCAN1_MCANSS_MSGMEM_WRAP_ECC_AGGR_MCANSS_MSGMEM_WRAP_MSGMEM_ECC_RAM_ID,
&injectErrorConfig);
if (result != SDL_EFAIL ) {
DebugP_log(
"\r\n Error inject at pErrMem 0x%p EFAIL test failed",
injectErrorConfig.pErrMem);
retVal = -1;
} else {
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:
if (result != SDL_PASS) {
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
APIs for SDL ECC