Part Number: TDA4VL-Q1
Other Parts Discussed in Thread: TDA4VL
Tool/software:
How to enable and perform single and double bit error injection on inline ECC for DDR?
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
Please follow the below patch to enable and inject single and double bit errors on inline ECC for DDRSS0 and DDRSS1 of J721S2.
From e79f94cc2ec1678bdb00eb03ff41e0caec92f2d1 Mon Sep 17 00:00:00 2001
From: Josiitaa RL <j-rl@ti.com>
Date: Fri, 13 Jun 2025 16:54:19 +0530
Subject: [PATCH] [PDK-17791][J721S2] Enabling and Testing inline ECC on DDRSS0
and DDRSS1. - Includes DDRSS0 and DDRSS1 configuration - ECC enabled for
the following regions on DDRSS0 and DDRSS1 - R0: 0x80000000 - 0x80001000
- R1: 0x90000000 - 0x90001000 - R2: 0xA0000000 - 0xA0001000 - ECC
memory priming - Residual ECC errors and interrupts cleared - Includes
single bit error injection to trigger events in both DDRSS0 and DDRSS1 -
Includes double bit error injection to trigger events in both DDRSS0 and
DDRSS1
Signed-off-by: Josiitaa RL <j-rl@ti.com>
---
csl_component.mk | 24 +
example/ddr/ddr_ecc_test_app/ecc_ddr.c | 528 ++++++++++++++++++
example/ddr/ddr_ecc_test_app/ecc_ddr.h | 92 +++
.../ddr/ddr_ecc_test_app/linker_r5_j721s2.lds | 101 ++++
example/ddr/ddr_ecc_test_app/main.c | 366 ++++++++++++
example/ddr/ddr_ecc_test_app/makefile | 76 +++
6 files changed, 1187 insertions(+)
create mode 100644 example/ddr/ddr_ecc_test_app/ecc_ddr.c
create mode 100644 example/ddr/ddr_ecc_test_app/ecc_ddr.h
create mode 100644 example/ddr/ddr_ecc_test_app/linker_r5_j721s2.lds
create mode 100644 example/ddr/ddr_ecc_test_app/main.c
create mode 100644 example/ddr/ddr_ecc_test_app/makefile
diff --git a/csl_component.mk b/csl_component.mk
index f8770ae91..c9825c848 100644
--- a/csl_component.mk
+++ b/csl_component.mk
@@ -1851,6 +1851,30 @@ endif
csl_ddr_test_app_SBL_APPIMAGEGEN = yes
export csl_ddr_test_app_SBL_APPIMAGEGEN
+# DDR ECC test app
+csl_ddr_ecc_test_app_COMP_LIST = csl_ddr_ecc_test_app
+csl_ddr_ecc_test_app_RELPATH = ti/csl/example/ddr/ddr_ecc_test_app
+csl_ddr_ecc_test_app_PATH = $(PDK_CSL_COMP_PATH)/example/ddr/ddr_ecc_test_app
+csl_ddr_ecc_test_app_BOARD_DEPENDENCY = yes
+ccsl_ddr_ecc_test_app_CORE_DEPENDENCY = yes
+export csl_ddr_ecc_test_app_COMP_LIST
+export csl_ddr_ecc_test_app_BOARD_DEPENDENCY
+export csl_ddr_ecc_test_app_CORE_DEPENDENCY
+csl_ddr_ecc_test_app_PKG_LIST = csl_ddr_ecc_test_app
+csl_ddr_ecc_test_app_INCLUDE = $(csl_ddr_ecc_test_app_PATH)
+csl_ddr_ecc_test_app_BOARDLIST = j721s2_evm
+export csl_ddr_ecc_test_app_BOARDLIST
+ifeq ($(BOARD),$(filter $(BOARD), j721s2_evm))
+csl_ddr_ecc_test_app_$(SOC)_CORELIST = mcu1_0
+endif
+export csl_ddr_ecc_test_app_$(SOC)_CORELIST
+
+# Packaged for below CSL_BUILDS
+ifeq ($(CSL_BUILD),$(filter $(CSL_BUILD), CSL))
+csl_EXAMPLE_LIST += csl_ddr_ecc_test_app
+endif
+csl_ddr_ecc_test_app_SBL_APPIMAGEGEN = yes
+export csl_ddr_ecc_test_app_SBL_APPIMAGEGEN
# CCM R5 test app
csl_ccmr5_baremetal_test_app_COMP_LIST = csl_ccmr5_baremetal_test_app
diff --git a/example/ddr/ddr_ecc_test_app/ecc_ddr.c b/example/ddr/ddr_ecc_test_app/ecc_ddr.c
new file mode 100644
index 000000000..27325db3f
--- /dev/null
+++ b/example/ddr/ddr_ecc_test_app/ecc_ddr.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) Texas Instruments Incorporated 2025
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file ecc_ddr.c
+ *
+ * \brief This file implements DDR ECC functions
+ */
+
+/*===========================================================================*/
+/* Include files */
+/*===========================================================================*/
+
+#include "ecc_ddr.h"
+#include <sdl_esm.h>
+#include <ti/osal/osal.h>
+
+/* ========================================================================== */
+/* Macros */
+/* ========================================================================== */
+
+/* None */
+
+/* ========================================================================== */
+/* Global Variables */
+/* ========================================================================== */
+
+volatile uint32_t gSecTestPass;
+volatile uint32_t gDedTestPass;
+
+volatile uint32_t testVal;
+
+SDL_ESM_config ECC_Test_esmInitConfig_MAIN =
+{
+ .esmErrorConfig = {1u, 8u}, /* Self test error config */
+ .enableBitmap = {0x00000000u, 0xffffffdbu, 0x7fffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0x00000000u,
+ 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
+ 0xfffbfeffu,
+ },
+ /**< All events enable: except clkstop events for unused clocks
+ * and PCIE events */
+ .priorityBitmap = {0x00000000u, 0xfffeffdbu, 0x7fffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0x00000000u,
+ 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
+ 0xfffbfeffu,
+ },
+ /**< All events high priority: except clkstop events for unused clocks
+ * and PCIE events */
+ .errorpinBitmap = {0x00000000u, 0xfffeffdbu, 0x7fffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0x00000000u,
+ 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
+ 0xfffbfeffu,
+ },
+ /**< All events high priority: except clkstop for unused clocks
+ * and PCIE events */
+};
+
+/* ========================================================================== */
+/* Function Definitions */
+/* ========================================================================== */
+
+static void DDREccInit();
+static int32_t DDREccConfig();
+static int32_t DDRSecErrTest(CSL_ecc_aggrRegs *eccAggrRegs, uint32_t test_address_offset);
+static int32_t DDRDedErrTest(CSL_ecc_aggrRegs *eccAggrRegs, uint32_t test_address_offset);
+int32_t DDREnableECC(CSL_emif_sscfgRegs *ddrCfgAddr);
+int32_t DDRDisableECC(CSL_emif_sscfgRegs *ddrCfgAddr);
+int32_t SDL_ESM_applicationCallbackFunction(SDL_ESM_Inst esmInstType,
+ SDL_ESM_IntType esmIntType,
+ uint32_t grpChannel,
+ uint32_t index,
+ uint32_t intSrc,
+ void *arg);
+
+/* ========================================================================== */
+/* Internal Function Declarations */
+/* ========================================================================== */
+
+int32_t DDREccTest(void)
+{
+ int32_t retVal;
+ static uint32_t arg;
+ void *ptr = (void *)&arg;
+ SDL_ErrType_t result = 0;
+
+ /* Initialize Test variables */
+ gSecTestPass = FALSE;
+ gDedTestPass = FALSE;
+
+ /* Initialize MAIN ESM module */
+ retVal = SDL_ESM_init(SDL_ESM_INST_MAIN_ESM0, &ECC_Test_esmInitConfig_MAIN, SDL_ESM_applicationCallbackFunction, ptr);
+ if (retVal != CSL_PASS) {
+ /* print error and quit */
+ UART_printf("ESM_ECC_Example_init: Error initializing MAIN ESM: result = %d\n", result);
+ } else {
+ UART_printf("\nESM_ECC_Example_init: Init MAIN ESM complete \n");
+ }
+
+
+ while (1)
+ {
+ DDREccInit();
+ //Injecting within DDRSS0
+ retVal = DDRSecErrTest(NULL, 0x15);
+ retVal = DDRDedErrTest(NULL, 0x15);
+
+ //Injecting within DDRSS1
+ retVal = DDRSecErrTest(NULL, 0x95);
+ retVal = DDRDedErrTest(NULL, 0x95);
+ UART_printf( "\r\nDDR ECC test exiting...");
+ break;
+ }
+
+ if (gSecTestPass)
+ {
+ UART_printf( "\r\nDDR ECC SEC ECC TESTS PASSED");
+ }
+ else
+ {
+ UART_printf( "\r\nDDR ECC SEC ECC TESTS FAILED");
+ }
+
+ if (gDedTestPass)
+ {
+ UART_printf( "\r\nDDR ECC DED ECC TESTS PASSED");
+ }
+ else
+ {
+ UART_printf( "\r\nDDR ECC DED ECC TESTS FAILED");
+ }
+ if (gDedTestPass & gSecTestPass)
+ {
+ UART_printf( "\r\nDDR ECC TESTS PASS\n");
+#if defined (UNITY_INCLUDE_CONFIG_H)
+ TEST_PASS();
+#endif
+ }
+ else
+ {
+ UART_printf( "\r\nDDR ECC TESTS FAILED");
+#if defined (UNITY_INCLUDE_CONFIG_H)
+ TEST_FAIL();
+#endif
+ }
+ return retVal;
+}
+
+/* Function initialized DDR ECC */
+static void DDREccInit()
+{
+ int32_t cslRet;
+
+ /* Ecc config */
+ cslRet = DDREccConfig();
+
+ if (cslRet != CSL_PASS)
+ {
+ UART_printf( "\r\nECC Config failed...");
+ }
+
+ return;
+}
+
+int32_t DDRDisableECC(CSL_emif_sscfgRegs *ddrCfgAddr)
+{
+ CSL_EmifConfig emifCfg;
+ int32_t cslRet;
+ int32_t retVal =0;
+ /* Configure ECC addresses and other configuration */
+ emifCfg.bEnableMemoryECC = true;
+ emifCfg.bReadModifyWriteEnable = true;
+ emifCfg.bECCCheck = true;
+ emifCfg.bWriteAlloc = true;
+ emifCfg.ECCThreshold = 1U;
+ emifCfg.pMemEccCfg.endAddr[0] = DDR_ECC_START_ADDR-EMIF_DDR_START_ADDR;
+ emifCfg.pMemEccCfg.startAddr[0] = DDR_ECC_END_ADDR-EMIF_DDR_START_ADDR;
+ emifCfg.pMemEccCfg.endAddr[1] = DDR_ECC_START_ADDR1-EMIF_DDR_START_ADDR;
+ emifCfg.pMemEccCfg.startAddr[1] = DDR_ECC_END_ADDR1-EMIF_DDR_START_ADDR;
+ emifCfg.pMemEccCfg.endAddr[2] = DDR_ECC_START_ADDR2-EMIF_DDR_START_ADDR;
+ emifCfg.pMemEccCfg.startAddr[2] = DDR_ECC_END_ADDR2-EMIF_DDR_START_ADDR;
+ cslRet = CSL_emifConfig(ddrCfgAddr, &emifCfg);
+ if (cslRet != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifConfig failed");
+ retVal = -1;
+ }
+ return retVal;
+}
+
+int32_t DDREnableECC(CSL_emif_sscfgRegs *ddrCfgAddr)
+{
+ CSL_EmifConfig emifCfg;
+ int32_t cslRet;
+ int32_t retVal =0;
+ /* Configure ECC addresses and other configuration */
+ emifCfg.bEnableMemoryECC = true;
+ emifCfg.bReadModifyWriteEnable = true;
+ emifCfg.bECCCheck = true;
+ emifCfg.bWriteAlloc = true;
+ emifCfg.ECCThreshold = 1U;
+ emifCfg.pMemEccCfg.startAddr[0] = (DDR_ECC_START_ADDR-EMIF_DDR_START_ADDR)/2;
+ emifCfg.pMemEccCfg.endAddr[0] = (DDR_ECC_END_ADDR-EMIF_DDR_START_ADDR)/2;
+ emifCfg.pMemEccCfg.startAddr[1] = (DDR_ECC_START_ADDR1-EMIF_DDR_START_ADDR)/2;
+ emifCfg.pMemEccCfg.endAddr[1] = (DDR_ECC_END_ADDR1-EMIF_DDR_START_ADDR)/2;
+ emifCfg.pMemEccCfg.startAddr[2] = (DDR_ECC_START_ADDR2-EMIF_DDR_START_ADDR)/2;
+ emifCfg.pMemEccCfg.endAddr[2] = (DDR_ECC_END_ADDR2-EMIF_DDR_START_ADDR)/2;
+ cslRet = CSL_emifConfig(ddrCfgAddr, &emifCfg);
+ if (cslRet != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifConfig failed");
+ retVal = -1;
+ }
+ return retVal;
+}
+
+/* Function configures DDR ECC and also primes the memory area */
+int32_t DDREccConfig()
+{
+ int32_t cslResult = CSL_PASS;
+ uintptr_t memPtr;
+ int32_t retVal = 0;
+
+ UART_printf( "\r\n Enabling ECC for DDRSS0 ");
+ retVal = DDREnableECC((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+ UART_printf( "\r\n Enabling ECC for DDRSS1 ");
+ retVal = DDREnableECC((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ if ( retVal == 0 )
+ {
+ /* Prime memory section 1 with known pattern */
+ for (memPtr = DDR_ECC_START_ADDR; memPtr < DDR_ECC_END_ADDR; memPtr += 4)
+ {
+ *((uint32_t *) memPtr) = 0x0;
+ }
+
+ CacheP_wbInv((void *)DDR_ECC_START_ADDR, DDR_ECC_END_ADDR-DDR_ECC_START_ADDR);
+
+ /* Prime memory section 2 with known pattern */
+ for (memPtr = DDR_ECC_START_ADDR1; memPtr < DDR_ECC_END_ADDR1; memPtr += 4)
+ {
+ *((uint32_t *) memPtr) = 0x0;
+ }
+
+ CacheP_wbInv((void *)DDR_ECC_START_ADDR1, DDR_ECC_END_ADDR1-DDR_ECC_START_ADDR1);
+
+ /* Prime memory section 3 with known pattern */
+ for (memPtr = DDR_ECC_START_ADDR2; memPtr < DDR_ECC_END_ADDR2; memPtr += 4)
+ {
+ *((uint32_t *) memPtr) = 0x0;
+ }
+
+ CacheP_wbInv((void *)DDR_ECC_START_ADDR2, DDR_ECC_END_ADDR2-DDR_ECC_START_ADDR2);
+
+ /* Clear any residual ECC errors */
+ cslResult = CSL_emifClearAllECCErrors((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+ if (cslResult != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCErrors failed for DDRSS0 ");
+ retVal = -1;
+ }
+ cslResult = CSL_emifClearAllECCErrors((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+ if (cslResult != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCErrors failed for DDRSS1");
+ retVal = -1;
+ }
+ }
+
+ if ( retVal == 0 )
+ {
+ /* clear interrupt status */
+ cslResult = CSL_emifClearECCInterruptStatus((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE,
+ CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECCM1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN_MASK);
+ if (cslResult != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifEnableECCInterrupts failed for DDRSS0");
+ retVal = -1;
+ }
+ /* clear interrupt status */
+ cslResult = CSL_emifClearECCInterruptStatus((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE,
+ CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECCM1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN_MASK);
+ if (cslResult != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifEnableECCInterrupts failed for DDRSS1");
+ retVal = -1;
+ }
+ }
+
+ if ( retVal == 0 )
+ {
+ /* Configure ECC interrupts : 1 bit error , 1 bit error multiple and 2 bit errors */
+ cslResult = CSL_emifEnableECCInterrupts((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE,
+ CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECCM1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN_MASK);
+ if (cslResult != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifEnableECCInterrupts for DDRSS0 ");
+ retVal = -1;
+ }
+ /* Configure ECC interrupts : 1 bit error , 1 bit error multiple and 2 bit errors */
+ cslResult = CSL_emifEnableECCInterrupts((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE,
+ CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECCM1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN_MASK);
+ if (cslResult != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifEnableECCInterrupts for DDRSS1");
+ retVal = -1;
+ }
+ }
+
+ if ( retVal != 0 )
+ {
+ UART_printf( "\r\nECC AGGR Configuration failed...");
+ }
+
+ return (retVal);
+}
+
+/* Function performs DDR single bit error test
+ * Configures ECC, Inserts single bit error
+ * and waits for handler to finish
+ */
+int32_t DDRSecErrTest(CSL_ecc_aggrRegs *eccAggrRegs, uint32_t test_address_offset)
+{
+
+ int32_t retVal = CSL_EFAIL;
+ volatile uint32_t testVal2;
+ uint32_t waitCount = 0;
+ uint32_t test_address;
+
+ UART_printf( "\r\n Offset: 0x%x", test_address_offset);
+
+ /* set the test status to false */
+ gSecTestPass = FALSE;
+
+ /* Clear any residual ECC errors */
+ CSL_emifClearAllECCErrors((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+ CSL_emifClearAllECCErrors((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ test_address = DDR_ECC_START_ADDR + test_address_offset;
+
+ /* Inject error */
+ gTest_Addr = (uint32_t *) (test_address);
+
+ /* Write back any pending writes */
+ CacheP_wbInv((const void *)gTest_Addr, 4);
+
+ /* Read value from test location */
+ testVal = gTest_Addr[0];
+
+ /* Flip one bit to introduce error */
+ testVal2 = testVal ^ 0x00010000u;
+
+ /* No need to translate the address */
+
+ /* NOTE: The following section is test code only cannot be used in real application */
+ /* ================================================================================ */
+
+ /* Temporarily disable ECC */
+ retVal = DDRDisableECC((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+ retVal = DDRDisableECC((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ /* Now corrupt the value */
+ *(gTest_Addr) = testVal2;
+ CacheP_wbInv((const void *)gTest_Addr, 4);
+
+ /* Enable back ECC */
+ retVal = DDREnableECC((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+ retVal = DDREnableECC((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ /* ================================================================================ */
+
+ /* Invalidate cache */
+ CacheP_Inv((const void *)gTest_Addr, 4);
+
+ /* Read value to trigger error */
+ testVal2 = gTest_Addr[0];
+
+ /* wait until the test passes */
+ UART_printf( "\r\n Waiting on SEC Interrupt...");
+
+ while ((gSecTestPass == FALSE) && (waitCount++ < 100u)) {
+ Osal_delay(10);
+ }
+ if (gSecTestPass == TRUE) {
+ UART_printf( "\r\n Got it (test pass)...");
+ retVal = CSL_PASS;
+ }
+ else
+ {
+ UART_printf( "\r\n Test failed timedout ...");
+
+ }
+
+ /* Restore original value */
+ gTest_Addr[0] = testVal;
+
+ /* Write back any pending writes */
+ CacheP_wbInv((const void *)gTest_Addr, 4);
+
+#if defined (UNITY_INCLUDE_CONFIG_H)
+ TEST_ASSERT_EQUAL_INT32(CSL_PASS, retVal);
+#endif
+ /* return the test status */
+ return retVal;
+}
+
+/* Function performs DDR double bit error test
+ * Inserts double bit error and waits for handler to finish
+ */
+static int32_t DDRDedErrTest(CSL_ecc_aggrRegs *eccAggrRegs, uint32_t test_address_offset)
+{
+ int32_t retVal = CSL_EFAIL;
+ volatile uint32_t testVal;
+ volatile uint32_t testVal2;
+ uint32_t waitCount = 0;
+ uint32_t test_address;
+
+ gDedTestPass = FALSE;
+
+ UART_printf( "\r\n Offset: 0x%x", test_address_offset);
+
+ /* Clear any residual ECC errors */
+ CSL_emifClearAllECCErrors((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+ CSL_emifClearAllECCErrors((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ test_address = DDR_ECC_START_ADDR + test_address_offset;
+ gTest_Addr = (uint32_t *) (test_address);
+
+ CacheP_wbInv((const void *)gTest_Addr, 4);
+ /* Read reference value */
+ testVal = gTest_Addr[0];
+ /* flip 2 bits */
+ testVal2 = testVal ^ 0x00101000u;
+
+ /* No need to translate the address */
+
+ /* NOTE: The following section is test code only cannot be used in real application */
+ /* ================================================================================ */
+
+ /* Temporarily disable ECC */
+ retVal = DDRDisableECC((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+ retVal = DDRDisableECC((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ /* Now corrupt the value */
+ *(gTest_Addr) = testVal2;
+
+ /* Make sure the values are written back */
+ CacheP_wbInv((const void *)gTest_Addr, 4);
+
+ /* Enable back ECC */
+ retVal = DDREnableECC((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+ retVal = DDREnableECC((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ /* ================================================================================ */
+
+ /* Invalidate cache */
+ CacheP_Inv((const void *)gTest_Addr, 4);
+
+ /* Read value to trigger error */
+ testVal2 = gTest_Addr[0];
+
+ /* wait until the test passes */
+ UART_printf( "\r\n Waiting on DED interrupt...");
+ while ((gDedTestPass == FALSE) && (waitCount++ < 10u)) {
+ Osal_delay(1000);
+ }
+
+ if (gDedTestPass == TRUE) {
+ UART_printf( "\r\n Got it (test pass)...");
+ retVal = CSL_PASS;
+ }
+ else
+ {
+ UART_printf( "\r\n Test failed timedout ...");
+ }
+
+ /* Restore original value */
+ gTest_Addr[0] = testVal;
+
+ /* return the test status */
+ return retVal;
+}
+
+/* Nothing past this point */
\ No newline at end of file
diff --git a/example/ddr/ddr_ecc_test_app/ecc_ddr.h b/example/ddr/ddr_ecc_test_app/ecc_ddr.h
new file mode 100644
index 000000000..bb6699b4c
--- /dev/null
+++ b/example/ddr/ddr_ecc_test_app/ecc_ddr.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) Texas Instruments Incorporated 2025
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file ecc_ddr.h
+ *
+ * \brief This file contains DDR ECC example code defines.
+ */
+
+/*===========================================================================*/
+/* Include files */
+/*===========================================================================*/
+
+#ifndef ECC_DDR_H_
+#define ECC_DDR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ti/csl/csl_emif.h>
+#include <ti/csl/src/ip/ecc_aggr/V1/cslr_ecc_aggr.h>
+
+#include <ti/drv/uart/UART_stdio.h>
+
+#ifdef UNITY_INCLUDE_CONFIG_H
+#include <ti/build/unit-test/Unity/src/unity.h>
+#include <ti/build/unit-test/config/unity_config.h>
+#endif
+
+/* ========================================================================== */
+/* Macros */
+/* ========================================================================== */
+
+extern volatile uint32_t *gTest_Addr;
+
+
+#define DDRSS0_CFG_BASE (SDL_COMPUTE_CLUSTER0_DDR0_0_SS_CFG_BASE)
+#define DDRSS1_CFG_BASE (SDL_COMPUTE_CLUSTER0_DDR1_1_SS_CFG_BASE)
+
+#define DDR_ECC_START_ADDR (0x80000000)
+#define DDR_ECC_END_ADDR (0x90000000)
+#define DDR_ECC_START_ADDR1 (0x90000000)
+#define DDR_ECC_END_ADDR1 (0xA0000000)
+#define DDR_ECC_START_ADDR2 (0xA0000000)
+#define DDR_ECC_END_ADDR2 (0xB0000000)
+
+#define EMIF_DDR_START_ADDR (0x80000000u)
+
+/* ========================================================================== */
+/* Function Declarations */
+/* ========================================================================== */
+
+int32_t DDREccTest(void);
+int32_t DDREnableECC(CSL_emif_sscfgRegs *ddrCfgAddr);
+int32_t DDRDisableECC(CSL_emif_sscfgRegs *ddrCfgAddr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ECC_DDR_H_ */
\ No newline at end of file
diff --git a/example/ddr/ddr_ecc_test_app/linker_r5_j721s2.lds b/example/ddr/ddr_ecc_test_app/linker_r5_j721s2.lds
new file mode 100644
index 000000000..15bb8e937
--- /dev/null
+++ b/example/ddr/ddr_ecc_test_app/linker_r5_j721s2.lds
@@ -0,0 +1,101 @@
+/* Linker Settings */
+--retain="*(.bootCode)"
+--retain="*(.startupCode)"
+--retain="*(.startupData)"
+--retain="*(.intvecs)"
+--retain="*(.intc_text)"
+--retain="*(.rstvectors)"
+--retain="*(.irqStack)"
+--retain="*(.fiqStack)"
+--retain="*(.abortStack)"
+--retain="*(.undStack)"
+--retain="*(.svcStack)"
+--fill_value=0
+--stack_size=0x2000
+--heap_size=0x1000
+--entry_point=_resetvectors /* Default C RTS boot.asm */
+
+-stack 0x2000 /* SOFTWARE STACK SIZE */
+-heap 0x2000 /* HEAP AREA SIZE */
+
+/* Stack Sizes for various modes */
+__IRQ_STACK_SIZE = 0x1000;
+__FIQ_STACK_SIZE = 0x1000;
+__ABORT_STACK_SIZE = 0x1000;
+__UND_STACK_SIZE = 0x1000;
+__SVC_STACK_SIZE = 0x1000;
+
+/* Memory Map */
+MEMORY
+{
+ /* MCU0_R5F_0 local view */
+ MCU0_R5F_TCMA_SBL_RSVD (X) : origin=0x0 length=0x100
+ MCU0_R5F_TCMA (X) : origin=0x100 length=0x8000 - 0x100
+ MCU0_R5F_TCMB0 (RWIX) : origin=0x41010000 length=0x8000
+
+ /* MCU0_R5F_1 SoC view */
+ MCU0_R5F1_ATCM (RWIX) : origin=0x41400000 length=0x8000
+ MCU0_R5F1_BTCM (RWIX) : origin=0x41410000 length=0x8000
+
+ /* Refer the user guide for details on persistence of these sections */
+ OCMC_RAM_BOARD_CFG (RWIX) : origin=0x41C80000 length=0x2000
+ OCMC_RAM_SCISERVER (RWIX) : origin=0x41C82000 length=0x60000
+ VECTORS (X) : origin=0x41CE2000 length=0x1000
+ RESET_VECTORS (X) : origin=0x41CE3000 length=0x100
+ OCMC_RAM (RWIX) : origin=0x41CE3100 length=0x1AA00
+ OCMC_RAM_X509_HEADER (RWIX) : origin=0x41CFDB00 length=0x500
+
+ /* j721s2 MCMS3 locations */
+ /* j721s2 Reserved Memory for ARM Trusted Firmware */
+ MSMC3_ARM_FW (RWIX) : origin=0x70000000 length=0x40000 /* 256KB */
+ MSMC3 (RWIX) : origin=0x70040000 length=0x3B0000 /* 4MB - 320KB */
+ /* j721s2 Reserved Memory for DMSC Firmware */
+ MSMC3_DMSC_FW (RWIX) : origin=0x703F0000 length=0x10000 /* 64KB */
+
+ DDR0 (RWIX) : origin=0x80000000 length=0x40000000 /* 2GB */
+}
+
+/* Section Configuration */
+SECTIONS
+{
+ /* 'intvecs' and 'intc_text' sections shall be placed within */
+ /* a range of +\- 16 MB */
+ .intvecs : {} palign(8) > VECTORS
+ .intc_text : {} palign(8) > VECTORS
+ .rstvectors : {} palign(8) > RESET_VECTORS
+ .bootCode : {} palign(8) > MSMC3
+ .startupCode : {} palign(8) > MSMC3
+ .startupData : {} palign(8) > MSMC3, type = NOINIT
+ .text : {} palign(8) > MSMC3
+ .const : {} palign(8) > MSMC3
+ .cinit : {} palign(8) > MSMC3
+ .pinit : {} palign(8) > MSMC3
+ .bss : {} align(4) > MSMC3
+ .far : {} align(4) > MSMC3
+ .data : {} palign(128) > MSMC3
+ .boardcfg_data : {} palign(128) > MSMC3
+ .sysmem : {} > MSMC3
+ .data_buffer : {} palign(128) > MSMC3
+ .bss.devgroup : {*(.bss.devgroup*)} align(4) > MSMC3
+ .const.devgroup: {*(.const.devgroup*)} align(4) > MSMC3
+
+ /* USB or any other LLD buffer for benchmarking */
+ .benchmark_buffer (NOLOAD) {} ALIGN (8) > MSMC3
+
+ .stack : {} align(4) > MSMC3 (HIGH)
+ .irqStack : {. = . + __IRQ_STACK_SIZE;} align(4) > MSMC3 (HIGH)
+ RUN_START(__IRQ_STACK_START)
+ RUN_END(__IRQ_STACK_END)
+ .fiqStack : {. = . + __FIQ_STACK_SIZE;} align(4) > MSMC3 (HIGH)
+ RUN_START(__FIQ_STACK_START)
+ RUN_END(__FIQ_STACK_END)
+ .abortStack : {. = . + __ABORT_STACK_SIZE;} align(4) > MSMC3 (HIGH)
+ RUN_START(__ABORT_STACK_START)
+ RUN_END(__ABORT_STACK_END)
+ .undStack : {. = . + __UND_STACK_SIZE;} align(4) > MSMC3 (HIGH)
+ RUN_START(__UND_STACK_START)
+ RUN_END(__UND_STACK_END)
+ .svcStack : {. = . + __SVC_STACK_SIZE;} align(4) > MSMC3 (HIGH)
+ RUN_START(__SVC_STACK_START)
+ RUN_END(__SVC_STACK_END)
+}
\ No newline at end of file
diff --git a/example/ddr/ddr_ecc_test_app/main.c b/example/ddr/ddr_ecc_test_app/main.c
new file mode 100644
index 000000000..5603e17e1
--- /dev/null
+++ b/example/ddr/ddr_ecc_test_app/main.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) Texas Instruments Incorporated 2024-2025
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file main.c
+ *
+ * \brief File containing main function implementation for csl_ddr_ecc_test_app
+ */
+
+/* ========================================================================== */
+/* Include Files */
+/* ========================================================================== */
+
+#include <ti/osal/CacheP.h>
+
+#include <ti/board/board.h>
+
+#include "ecc_ddr.h"
+#include <sdl_esm.h>
+#include <sdl_ecc.h>
+#include <osal_interface.h>
+
+#ifdef UNITY_INCLUDE_CONFIG_H
+#include <ti/build/unit-test/Unity/src/unity.h>
+#include <ti/build/unit-test/config/unity_config.h>
+#endif
+
+/* ========================================================================== */
+/* Macros & Typedefs */
+/* ========================================================================== */
+
+#define BOARD_INIT_WAIT_DELAY 1000
+
+/* ========================================================================== */
+/* Structure Declarations */
+/* ========================================================================== */
+
+/* None */
+
+/* ========================================================================== */
+/* Global Variables */
+/* ========================================================================== */
+
+volatile uint32_t *gTest_Addr = NULL;
+
+volatile uint32_t gSecTestPass;
+volatile uint32_t gDedTestPass;
+
+int32_t gDdrEccTestResult = CSL_EFAIL;
+
+/* ========================================================================== */
+/* Internal Function Declarations */
+/* ========================================================================== */
+
+/* Unity functions */
+void test_csl_ddr_ecc_test_app_runner(void);
+void test_csl_ddr_ecc_test_app (void);
+
+/* ========================================================================== */
+/* Function Definitions */
+/* ========================================================================== */
+#ifdef UNITY_INCLUDE_CONFIG_H
+/*
+ * ======== Unity set up and tear down ========
+ */
+void setUp(void)
+{
+ /* Do nothing */
+}
+
+void tearDown(void)
+{
+ /* Do nothing */
+}
+#endif
+
+int32_t SDL_ESM_applicationCallbackFunction(SDL_ESM_Inst esmInst,
+ SDL_ESM_IntType esmIntrType,
+ uint32_t grpChannel,
+ uint32_t index,
+ uint32_t intSrc,
+ uintptr_t *arg)
+{
+
+ SDL_ECC_MemType eccmemtype;
+ SDL_Ecc_AggrIntrSrc eccIntrSrc;
+ SDL_ECC_ErrorInfo_t eccErrorInfo;
+ int32_t retVal;
+ volatile uint32_t testVal =0;
+
+ UART_printf("\n ESM Call back function called : instType 0x%x, intType 0x%x, " \
+ "intSrc 0x%x \n",
+ esmInst, esmIntrType, intSrc);
+ UART_printf(" Take action \n");
+ if(esmIntrType == 1u){
+ UART_printf(" High Priority Interrupt Executed\n");
+ }
+ else{
+ UART_printf(" Low Priority Interrupt Executed\n");
+ }
+ retVal = SDL_ECC_getESMErrorInfo(esmInst, intSrc, &eccmemtype, &eccIntrSrc);
+
+ /* Any additional customer specific actions can be added here */
+ retVal = SDL_ECC_getErrorInfo(eccmemtype, eccIntrSrc, &eccErrorInfo);
+
+ if (intSrc == SDLR_ESM0_ESM_LVL_EVENT_DDR0_DDRSS_DRAM_ECC_CORR_ERR_LVL_0)
+ {
+ gSecTestPass = TRUE;
+ /* Clear Specific ECC error */
+ retVal = CSL_emifClearECCError((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE,
+ CSL_EMIF_ECC_ERROR_TYPE_SINGLE_BIT);
+ if (retVal != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCErrors failed ");
+ }
+
+ /* Clear ECC interupt bits */
+ retVal = CSL_emifClearECCInterruptStatus((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE,
+ CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECCM1BERR_EN_MASK);
+ if (retVal != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCInterruptStatus Failed ");
+ }
+
+ }
+ else if (intSrc == SDLR_ESM0_ESM_LVL_EVENT_DDR1_DDRSS_DRAM_ECC_CORR_ERR_LVL_0)
+ {
+ gSecTestPass = TRUE;
+ /* Clear Specific ECC error */
+ retVal = CSL_emifClearECCError((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE,
+ CSL_EMIF_ECC_ERROR_TYPE_SINGLE_BIT);
+ if (retVal != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCErrors failed ");
+ }
+
+ /* Clear ECC interupt bits */
+ retVal = CSL_emifClearECCInterruptStatus((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE,
+ CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN_MASK
+ | CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECCM1BERR_EN_MASK);
+ if (retVal != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCInterruptStatus Failed ");
+ }
+
+ }
+ else if (intSrc == SDLR_ESM0_ESM_LVL_EVENT_DDR0_DDRSS_DRAM_ECC_UNCORR_ERR_LVL_0)
+ {
+ gDedTestPass = TRUE;
+
+ /* This section corrects the ECC error simulated */
+ /* In a real application the user must take necessary corrective action */
+ /******************************************************************/
+
+ /* Temporarily disable ECC */
+ DDRDisableECC((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+
+ /* Now replace location with original value as 2b errors are not corrected */
+ *(gTest_Addr) = testVal;
+
+ /* Write back any pending writes */
+ CacheP_wbInv((const void *)gTest_Addr, 4);
+
+ /* Enable back ECC */
+ DDREnableECC((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE);
+
+ /******************************************************************/
+ /* Clear specific error */
+ retVal = CSL_emifClearECCError((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE,
+ CSL_EMIF_ECC_ERROR_TYPE_DOUBLE_BIT);
+ if (retVal != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCErrors failed ");
+ }
+
+ /* Clear ECC interrupt bits */
+ retVal = CSL_emifClearECCInterruptStatus((CSL_emif_sscfgRegs *)DDRSS0_CFG_BASE,
+ CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN_MASK);
+ if (retVal != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCInterruptStatus Failed ");
+ }
+ }
+ else if (intSrc == SDLR_ESM0_ESM_LVL_EVENT_DDR1_DDRSS_DRAM_ECC_UNCORR_ERR_LVL_0)
+ {
+ gDedTestPass = TRUE;
+
+ /* This section corrects the ECC error simulated */
+ /* In a real application the user must take necessary corrective action */
+ /******************************************************************/
+
+ /* Temporarily disable ECC */
+ DDRDisableECC((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ /* Now replace location with original value as 2b errors are not corrected */
+ *(gTest_Addr) = testVal;
+
+ /* Write back any pending writes */
+ CacheP_wbInv((const void *)gTest_Addr, 4);
+
+ /* Enable back ECC */
+ DDREnableECC((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE);
+
+ /******************************************************************/
+ /* Clear specific error */
+ retVal = CSL_emifClearECCError((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE,
+ CSL_EMIF_ECC_ERROR_TYPE_DOUBLE_BIT);
+ if (retVal != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCErrors failed ");
+ }
+
+ /* Clear ECC interrupt bits */
+ retVal = CSL_emifClearECCInterruptStatus((CSL_emif_sscfgRegs *)DDRSS1_CFG_BASE,
+ CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN_MASK);
+ if (retVal != CSL_PASS)
+ {
+ UART_printf( "\r\n CSL_emifClearECCInterruptStatus Failed ");
+ }
+ }
+ SDL_ESM_clrNError(esmInst);
+ return retVal;
+}
+
+static int32_t sdlApp_osalInit(void)
+{
+ SDL_ErrType_t ret = SDL_PASS;
+
+ ret = SDL_TEST_osalInit();
+ if (ret != SDL_PASS)
+ {
+ UART_printf("Error: Init Failed\n");
+ }
+
+ return ret;
+}
+
+void test_csl_ddr_ecc_test_app(void)
+{
+
+ gDdrEccTestResult = DDREccTest();
+#if defined (UNITY_INCLUDE_CONFIG_H)
+ TEST_ASSERT_EQUAL_INT32(CSL_PASS, gDdrEccTestResult);
+#else
+ if (gDdrEccTestResult != CSL_PASS)
+ {
+ UART_printf("\r\n DDR ECC test failed \n");
+ }
+#endif
+ return;
+}
+
+void test_csl_ddr_ecc_test_app_runner(void)
+{
+#if defined(UNITY_INCLUDE_CONFIG_H)
+ UNITY_BEGIN();
+ /* DDR ECC test for R5F */
+ RUN_TEST (test_csl_ddr_ecc_test_app);
+
+ UNITY_END();
+ /* Function to print results defined in our unity_config.h file */
+ print_unityOutputBuffer_usingUARTstdio();
+#else
+ test_csl_ddr_ecc_test_app();
+#endif
+ return;
+}
+
+int main (void)
+{
+ Board_initCfg boardCfg;
+ Board_STATUS status = BOARD_SOK;
+
+ boardCfg = BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO;
+ status = Board_init(boardCfg);
+#if defined (UNITY_INCLUDE_CONFIG_H)
+ TEST_ASSERT_EQUAL_INT32(BOARD_SOK, status);
+#else
+ if (status != BOARD_SOK)
+ {
+ UART_printf("\n Board Init failed \n");
+ return;
+ }
+#endif /* (UNITY_INCLUDE_CONFIG_H) */
+
+#ifdef NO_SBL
+ if (status == BOARD_SOK)
+ {
+ Osal_delay(BOARD_INIT_WAIT_DELAY);
+ boardCfg = BOARD_INIT_PINMUX_CONFIG;
+ status = Board_init(boardCfg);
+#if defined (UNITY_INCLUDE_CONFIG_H)
+ TEST_ASSERT_EQUAL_INT32(BOARD_SOK, status);
+#else
+ if (status != BOARD_SOK)
+ {
+ UART_printf("\n Board Init Pinmux Config failed \n");
+ return;
+ }
+#endif /* (UNITY_INCLUDE_CONFIG_H) */
+ }
+ if (status == BOARD_SOK)
+ {
+ Osal_delay(BOARD_INIT_WAIT_DELAY);
+ boardCfg = BOARD_INIT_DDR |
+ BOARD_INIT_DDR_ECC;
+ status = Board_init(boardCfg);
+#if defined (UNITY_INCLUDE_CONFIG_H)
+ TEST_ASSERT_EQUAL_INT32(BOARD_SOK, status);
+#else
+ if (status != BOARD_SOK)
+ {
+ UART_printf("\n Board Init DDR with ECC failed \n");
+ return;
+ }
+#endif /* (UNITY_INCLUDE_CONFIG_H) */
+ }
+#endif /* NO_SBL */
+
+ UART_printf("\n Board init complete \n");
+
+ sdlApp_osalInit();
+
+ test_csl_ddr_ecc_test_app_runner();
+ if (gDdrEccTestResult == CSL_PASS)
+ {
+#if defined (SOC_J721E)
+ if(gMsmcMemParityResult == CSL_PASS)
+#endif
+ {
+ UART_printf("\r\nAll tests have passed.");
+ }
+ }
+ while (1);
+}
\ No newline at end of file
diff --git a/example/ddr/ddr_ecc_test_app/makefile b/example/ddr/ddr_ecc_test_app/makefile
new file mode 100644
index 000000000..e39cfbf50
--- /dev/null
+++ b/example/ddr/ddr_ecc_test_app/makefile
@@ -0,0 +1,76 @@
+include $(PDK_INSTALL_PATH)/ti/build/Rules.make
+
+BUILD_OS_TYPE=baremetal
+
+APP_NAME = csl_ddr_ecc_test_app
+
+SRCDIR = .
+INCDIR = .
+
+# List all the external components/interfaces, whose interface header files
+# need to be included for this component
+INCLUDE_EXTERNAL_INTERFACES = pdk csl_arch
+
+# List all the components required by the application
+ifeq ($(BOARD),$(filter $(BOARD), j721s2_evm))
+ COMP_LIST_COMMON += $(PDK_COMMON_BAREMETAL_COMP)
+else
+ COMP_LIST_COMMON += csl
+ ifeq ($(CORE),$(filter $(CORE), mcu1_0))
+ COMP_LIST_a15_0 = csl_init
+ endif
+endif
+
+# Common source files and CFLAGS across all platforms and cores
+PACKAGE_SRCS_COMMON = .
+
+CFLAGS_LOCAL_COMMON = $(PDK_CFLAGS)
+
+ifeq ($(SOC), $(filter $(SOC), j721s2))
+ifeq ($(CORE),mcu1_0)
+SDL_INSTALL_PATH=$(PDK_INSTALL_PATH)/../../sdl
+INCDIR += $(PDK_INSTALL_PATH)/../../sdl
+INCDIR += $(PDK_INSTALL_PATH)/../../sdl/src/sdl
+INCDIR += $(PDK_INSTALL_PATH)/../../sdl/include/soc/$(SOC)
+INCDIR += $(PDK_INSTALL_PATH)/../../sdl/include
+INCDIR += $(PDK_INSTALL_PATH)/../../sdl/osal
+INCDIR += $(PDK_INSTALL_PATH)/../../sdl/test/osal
+INCDIR += $(PDK_INSTALL_PATH)/../../sdl/src/ip/ecc/V1
+SRCDIR += $(PDK_INSTALL_PATH)/../../sdl/src/sdl/ecc
+SRCDIR += $(PDK_INSTALL_PATH)/../../sdl/src/sdl/esm
+SRCDIR += $(PDK_INSTALL_PATH)/../../sdl/src/ip/esm/V0
+SRCDIR += $(PDK_INSTALL_PATH)/../../sdl/src/ip/ecc/V1
+SRCDIR += $(PDK_INSTALL_PATH)/../../sdl/osal/src
+SRCDIR += $(PDK_INSTALL_PATH)/../../sdl/test/osal/src
+EXT_LIB_LIST_COMMON += $(SDL_INSTALL_PATH)/binary/src/sdl/lib/$(SOC)/r5f/$(BUILD_PROFILE)/sdl_api.$(LIBEXT)
+EXT_LIB_LIST_COMMON += $(SDL_INSTALL_PATH)/binary/osal/lib/$(SOC)/r5f/$(BUILD_PROFILE)/sdl_osal.$(LIBEXT)
+EXT_LIB_LIST_COMMON += $(SDL_INSTALL_PATH)/binary/src/ip/lib/$(SOC)/r5f/$(BUILD_PROFILE)/sdl_ip.$(LIBEXT)
+EXTERNAL_LNKCMD_FILE_LOCAL = $(PDK_CSL_COMP_PATH)/example/ddr/ddr_ecc_test_app/linker_r5_$(SOC).lds
+SRCS_COMMON = main.c ecc_ddr.c osal_interface.c
+endif
+endif
+
+# LNKFLAGS_LOCAL_a15_0 += --entry Entry
+# LNKFLAGS_LOCAL_mpu1_0 += --entry Entry
+
+ifeq ($(SOC),$(filter $(SOC), j721s2))
+ SRCDIR += $(PDK_INSTALL_PATH)/ti/build/unit-test/Unity/src
+ SRCDIR += $(PDK_INSTALL_PATH)/ti/build/unit-test/config
+ INCDIR += $(PDK_INSTALL_PATH)/ti/build/unit-test/Unity/src
+ INCDIR += $(PDK_INSTALL_PATH)/ti/build/unit-test/config
+ SRCS_COMMON += unity_config.c unity.c
+ CFLAGS_LOCAL_COMMON += -DUNITY_INCLUDE_CONFIG_H
+endif
+
+# Include common make files
+ifeq ($(MAKERULEDIR), )
+#Makerule path not defined, define this and assume relative path from ROOTDIR
+ MAKERULEDIR := $(ROOTDIR)/ti/build/makerules
+ export MAKERULEDIR
+endif
+include $(MAKERULEDIR)/common.mk
+
+# OBJs and libraries are built by using rule defined in rules_<target>.mk
+# and need not be explicitly specified here
+
+# Nothing beyond this point
\ No newline at end of file
--
2.34.1
This patch has been tested on SDK 11.0. Please apply the patch using the below mentioned steps -
cd $RTOS_SDK/
git init
git add .
git commit -m "init commit"
git am $PATH_TO_PATCH_SHARED_BELOW
The following are the memory ranges for which ECC has been enabled and primed -
#define DDR_ECC_START_ADDR (0x80000000)
#define DDR_ECC_END_ADDR (0x90000000)
#define DDR_ECC_START_ADDR1 (0x90000000)
#define DDR_ECC_END_ADDR1 (0xA0000000)
#define DDR_ECC_START_ADDR2 (0xA0000000)
#define DDR_ECC_END_ADDR2 (0xB0000000)
For more details on inline ECC please refer to the following userguide - https://software-dl.ti.com/jacinto7/esd/processor-sdk-rtos-j721s2/latest/exports/docs/psdk_rtos/docs/user_guide/developer_notes_ddr_inline_ecc.html
Please note that this patch is applicable for TDA4VL/J721S2 with 2x DDRSS interleaved every 128 bytes. For 1 or 3x DDRSS interleaved every 128 bytes, the following change would be required -
Regards,
Josiitaa