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.

TDA4VM: Some question about DDR ECC fault injection

Part Number: TDA4VM

Hi , 

I have some confusion about the usage about DDR ECC test. all i want to use in only 2GB ddr, start from 0x80000000

1. about ddr ecc init process:

according to this link: https://software-dl.ti.com/jacinto7/esd/processor-sdk-rtos-jacinto7/08_00_00_12/exports/docs/psdk_rtos/docs/user_guide/developer_notes_ddr_inline_ecc.html

step 1:Program the ECC Region registers

step 2:Enable ECC and pre-load the DDR with known pattern,in order to calculate the inline ecc 
step 3:Enable ECC check
it seems logical,but when i use board_init (BOARD_INIT_DDR | BOARD_INIT_DDR_ECC) for sbl_main file.
it will enable ddr and ecc check first (csl/src/ip/emif/v2/priv/csl_emif.c: CSL_emifconfigController()), after that fill the pattern. whether it will case a lot of ecc err?

2. about ddr ecc fault inject test:
demo code from csl\example\ecc\ecc_test_app\ecc_ddr.c: 
#define EMIF_ECC_MEM_BLOCK_SIZE       0x200                      //why we need use this macro to calculate translated address?
#define EMIF_ECC_DATA_SIZE_PER_BLOCK  0x40                   // as above
/*why we need to use translated address not the actrually physical address ?*/
uintptr_t DDRGetTranslatedAddress(uintptr_t memAddress)
{
    uint32_t memIndex;
    uintptr_t translatedMemAddr; 
       
    memIndex = (memAddress-0x80000000u)/EMIF_ECC_MEM_BLOCK_SIZE
    if ((memIndex & 0x1u) == 0)
    {
        translatedMemAddr = memAddress + ((memIndex)*EMIF_ECC_DATA_SIZE_PER_BLOCK);
    }
    else
    {
        translatedMemAddr = memAddress + ((memIndex+1u)*EMIF_ECC_DATA_SIZE_PER_BLOCK);
    }
    return  translatedMemAddr;
}
int32_t DDRSecErrTest(CSL_ecc_aggrRegs *eccAggrRegs, uint32_t ramId)
{
    int32_t  retVal = CSL_EFAIL;
    volatile uint32_t testVal2, testVal3;
    volatile uint32_t *translatedMemPtr;
    uint32_t waitCount = 0;

    /* set the test status to false */
    gSecTestPass = FALSE;

    /* Clear any residual ECC errors */
    CSL_emifClearAllECCErrors((CSL_emif_sscfgRegs *)DDRSS_CFG_BASE);

    /* Inject error */
    gTest_Addr = (uint32_t *) (DDR_ECC_TEST_ADDR);

    /* 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;

    /* Calculate translated address */
    translatedMemPtr = (volatile uint32_t *)(DDRGetTranslatedAddress((uintptr_t)gTest_Addr)); //why we need to calculate a translated address, when i only use 2GB DDR.  

    /* NOTE: The following section is test code only cannot be used in real application */
    /* ================================================================================ */

    /* Temporarily disable ECC */
    CSL_emifDisableECC((CSL_emif_sscfgRegs *)DDRSS_CFG_BASE);

    /* Now corrupt the value */
    *(translatedMemPtr) = testVal2;
    CacheP_wbInv((const void *)translatedMemPtr, 4);

    /* Enable back ECC */
    CSL_emifEnableECC((CSL_emif_sscfgRegs *)DDRSS_CFG_BASE);

    /* ================================================================================ */
    /* when i use this to inject a single bit ecc error in autosar OS(MCU_R51_0),   I always meet a undefined exception 1 here, and i found the last instruction is Os_Hal_StoreFpuRegisters().
   *   is there anybody else meet the same problem? i have not use a floating point handle here.  Is this caused by the translated address?
   */
    /* Invalidate cache */
    CacheP_Inv((const void *)gTest_Addr, 4);

    /* Read value to trigger error */
    testVal3 = gTest_Addr[0];

    /* wait until the test passes */
    UARTConfigPuts(gUartBaseAddr, "\r\n Waiting on SEC Interrupt...", -1);

    while ((gSecTestPass == FALSE) && (waitCount++ < 100u)) {
        Osal_delay(10);
    }
    if (gSecTestPass == TRUE) {
        UARTConfigPuts(gUartBaseAddr, "\r\n Got it (test pass)...", -1);
        retVal = CSL_PASS;
    }
    else
    {
        UARTConfigPuts(gUartBaseAddr, "\r\n Test failed timedout ...", -1);
       
    }

    /* 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;
}
Looking forward to the reply from TI engineers
  • one more thing about translated address:

    Assume that : i only protect 0xD2000000 - 0xD2FFFFFF

    test address = 0xD2000000 + 0x200000

    the translated address = 0xDC640000,   but there is already some code, maybe used by A72. 

  • Hi,

    it seems logical,but when i use board_init (BOARD_INIT_DDR | BOARD_INIT_DDR_ECC) for sbl_main file.
    it will enable ddr and ecc check first (csl/src/ip/emif/v2/priv/csl_emif.c: CSL_emifconfigController()), after that fill the pattern. whether it will case a lot of ecc err?

    Yes, there will be multiple errors logged in this case. Referring to the same documentation if ECC is not pre-loaded and ECC check gets enabled then multiple single/double bit errors will be logged.

    *why we need to use translated address not the actrually physical address ?*/

    I will check this internally, will get back on this by tomorrow.

    Regards,
    Parth