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.

LAUNCHXL2-RM57L: Procedure to perform DMA self tests ECC on RM57 board

Part Number: LAUNCHXL2-RM57L

Hi,

We are trying incorporate one and two DMA tests to run during startup. We have copied these tests over from the safety library 2.4.0. The tests complete, but we are not seeing the expected esm error for any of the tests. We are enabling the DMA ECC in our _c_int00() function by writing 0xAU to the dmaREG->DMAPCR register.

Here is our tests. Any guidance would be much appreciated. 

namespace
{
    constexpr uint32_t DmaGCtrlResetBit { 1U };
    constexpr uint32_t DmaGCtrlBusBusy { 0x4000U };
    constexpr uint32_t DmaGCtrlDmaEnable { 0x10000U };
    constexpr uint32_t DmaSramEccDisabled { 0x5U };
    constexpr uint32_t DmaParCtrlEccDetectEnable { 0xAU };
    constexpr uint32_t DmaParCtrlEccDetectEnableStart { 0U };
    constexpr uint32_t DmaParCtrlEccDetectEnableLength { 4U };
    constexpr uint32_t DmaParCtrlEccDisable { 0x5U };
    constexpr uint32_t DmaParCtrlEccStart { 0U };
    constexpr uint32_t DmaParCtrlEccLength { 4U };
    constexpr uint32_t DmaEccTestEnable { 1U << 8U };

    constexpr uint32_t DmaRAMBaseAddress { 0xFFF80000U };
    constexpr uint32_t DmaBadEcc { 0xFFF80010U };

    constexpr uint32_t DMapCtrl1Reg0ApEnable { 0x1U };
    constexpr uint32_t DMapCtrl1Reg0ApEnableStart { 1U };
    constexpr uint32_t DMapCtrl1Reg0ApEnableLength { 2U };
    constexpr uint32_t DMapCtrl1Int0Enable { 0x8U };

    constexpr uint32_t DmaMpst1Reg0Ft { 0x1U };

    constexpr uint32_t DmaSbeEvtEnable { 0xAU };
    constexpr uint32_t DmaSbeEvtStart { 8U };
    constexpr uint32_t DmaSbeEvtLength { 4U };

    constexpr uint32_t DmaEccSbErr { 16U };
    constexpr uint32_t DmaEccErr { 24U };
    constexpr uint32_t DmaEccUnCorErrAddrStart { 0U };
    constexpr uint32_t DmaEccUnCorErrAddrLength { 12U };

    constexpr uint32_t DmaEdacModeDisable { 0x5U };
    constexpr uint32_t DmaEdacModeStart { 0U };
    constexpr uint32_t DmaEdacModeLength { 4U };

    constexpr uint32_t DmaPermissionAllAccess { 0x0U };
    constexpr uint32_t DmaPermissionWriteAccess { 0x2U };
    constexpr uint32_t DmaPermissionReadAccess { 0x1U };
    constexpr uint32_t DmaPermissionNoAccess { 0x3U };

    constexpr uint32_t DmaFlipDataOneBit { 0x1U };
    constexpr uint32_t DmaFlipDataTwoBit { 0x3U };

    constexpr uint32_t EsmG1ErrDmaEccSbErr { 82U }; //ESM Group 1 - DMA - ECC single bit error bit
    constexpr uint32_t EsmG1ErrDmaEccUnCorr { 3U }; //ESM Group 1 - DMA - ECC uncorrectable error

    constexpr uint32_t a { 1U }
    ;

    uint32_t GetEsmBitNum(uint32_t num)
    {
        if (num < 32U)
        {
            return num;
        }
        if (num < 64)
        {
            return num - 32U;
        }
        return num - 64U;
    }
}
bool Rm57Dma::EccOneBitTest( const bool faultInject )
{
    auto *dmaRead = reinterpret_cast<uint32_t*>(DmaBadEcc);

    /* backup DATA stored at this location */
    const auto dataVal = *dmaRead;

    /* Enable ECC */
    SetBitField(dmaREG->DMAPCR, DmaParCtrlEccDetectEnable, DmaParCtrlEccDetectEnableStart, DmaParCtrlEccDetectEnableLength);

    /* rewrite the data back to the DMA RAM, this will ensure that the ECC is
     * correctly computed for this location. */
    *dmaRead = dataVal;

    /* Enable ECC test mode */
    BitSet(dmaREG->DMAPCR, DmaEccTestEnable);

    auto regBackupSECCTL = dmaREG->DMASECCCTRL;
    auto regBackupPCR = dmaREG->DMAPCR;

    /*Backup grp1 esm interrupt enable register and clear the interrupt enable */
    auto regBkupIntEnaSet = esmREG->IESR7;
    auto regBckupErrInfulence = esmREG->IEPSR7;

    if (!faultInject) {
        esmREG->IECR7 = GetEsmBitNum(EsmG1ErrDmaEccSbErr);
        esmREG->IEPCR7 = GetEsmBitNum(EsmG1ErrDmaEccSbErr);
    }

    /* Enable generation of single bit event to the ESM (will set the ESM
     * Status flag upon detection of single bit error.) If ESM is enabled
     * (fault injection), will cause ESM interrupt to occur.  */
    SetBitField(dmaREG->DMASECCCTRL, DmaSbeEvtEnable, DmaSbeEvtStart, DmaSbeEvtLength);
    /* Write clear any pending single bit error flag */
    BitSet(dmaREG->DMASECCCTRL, DmaEccErr);
    /* Disable correction of Single Bit Error detected by SECDED block */
    SetBitField(dmaREG->DMASECCCTRL, DmaEdacModeDisable, DmaEdacModeStart, DmaEdacModeLength);

    /* Read clear the error address offset */
    volatile auto ramRead = dmaREG->DMAECCSBE;

    /* Check syndrome */
    /* Flip bit 0 to introduce a single bit error */
    BitFlip(*dmaRead, DmaFlipDataOneBit);

    /*required when running with optimisation*/
    _SL_Barrier_Data_Access();

    /* Cause 1 bit ECC error */
    ramRead = *dmaRead;

    auto ram1erraddr = (dmaREG->DMAECCSBE | DmaRAMBaseAddress);

    auto success = false;

    if (!faultInject) {
        if (Bit(DmaEccSbErr) == (dmaREG->DMASECCCTRL & Bit(DmaEccSbErr)) &&
                DmaBadEcc == ram1erraddr &&
                (esmREG->SR7[0] & GetEsmBitNum(EsmG1ErrDmaEccSbErr))
                == GetEsmBitNum(EsmG1ErrDmaEccSbErr)) {
            /* Clear ESM error status */
            esmREG->SR7[0] =  GetEsmBitNum(EsmG1ErrDmaEccSbErr);
            success = true;
        }
    }
    else {
        /*nothing to be done for fault injection */
        success = true;
    }

    /* Clear flags and read error address */
    BitSet(dmaREG->DMASECCCTRL, Bit(DmaEccSbErr));

    /* Disable ECC */
    SetBitField(dmaREG->DMAPCR, DmaParCtrlEccDisable, DmaParCtrlEccStart, DmaParCtrlEccLength);

    /* Restore data. ECC should remain the same as before. */
    *dmaRead = dataVal;

    /* Clear the TEST bit of Parity control register */
    BitSet(dmaREG->DMAPCR, DmaEccTestEnable);

    /* Restore DMA register states */
    dmaREG->DMAPCR = regBackupPCR;
    dmaREG->DMASECCCTRL = regBackupSECCTL;

    /* Restore ESM registers states */
    esmREG->IESR7 = regBkupIntEnaSet;
    esmREG->IEPSR7 = regBckupErrInfulence;

    return success;
}

bool Rm57Dma::EccTwoBitTest(const bool faultInject)
{
    auto *dmaRead = reinterpret_cast<uint32_t*>(DmaBadEcc);

    /* backup DATA stored at this location */
    const auto dataVal = *dmaRead;

    /* Enable ECC */
    SetBitField(dmaREG->DMAPCR, DmaParCtrlEccDetectEnable, DmaParCtrlEccDetectEnableStart, DmaParCtrlEccDetectEnableLength);

    /* rewrite the data back to the DMA RAM, this will ensure that the ECC is
     * correctly computed for this location. */
    *dmaRead = dataVal;

    /* Enable ECC test mode */
    dmaREG->DMAPCR = dmaREG->DMAPCR | DmaEccTestEnable;

    auto regBackupSECCTL = dmaREG->DMASECCCTRL;
    auto regBackupPCR = dmaREG->DMAPCR;
    auto regBkupIntEnaSet = esmREG->IESR1;
    auto regBckupErrInfulence = esmREG->EEPAPR1;


    if (!faultInject) {
        /* Disable ESM notification */
        esmREG->IECR1 = GetEsmBitNum(EsmG1ErrDmaEccUnCorr);
        esmREG->DEPAPR1 = GetEsmBitNum(EsmG1ErrDmaEccUnCorr);
    }

    /* Clear previous ECC error */
    BitSet(dmaREG->DMAPAR, DmaEccErr);

    /* Read clear the error address */
    volatile auto ramRead = dmaREG->DMAPAR;

    /* Introduce a double bit error */
    BitFlip(*dmaRead, DmaFlipDataTwoBit);

    /*required when running with optimisation*/
    _SL_Barrier_Data_Access();

    ramRead = *dmaRead;

    auto ram1erraddr = (GetBitField(dmaREG->DMAPAR, DmaEccUnCorErrAddrStart, DmaEccUnCorErrAddrLength) | DmaRAMBaseAddress);

    auto success = false;

    if (!faultInject) {
        if ((dmaREG->DMAPAR & Bit(DmaEccErr)) == Bit(DmaEccErr) &&
            DmaBadEcc == ram1erraddr    &&
            GetEsmBitNum(EsmG1ErrDmaEccUnCorr) ==
            (esmREG->SR1[0] & GetEsmBitNum(EsmG1ErrDmaEccUnCorr))) {
            success = true;
            /* Clear ESM error status */
            esmREG->SR1[0] =  GetEsmBitNum(EsmG1ErrDmaEccUnCorr);
        }
    }
    else {
        success = true;
    }

    /* Clear flags and read error address */
    BitSet(dmaREG->DMAPAR, Bit(DmaEccErr));

    /* Disable ECC */
    SetBitField(dmaREG->DMAPCR, DmaParCtrlEccDisable, DmaParCtrlEccStart, DmaParCtrlEccLength);

    /* Restore data */
    *dmaRead = dataVal;

    /* Disable ECC test mode */
    BitSet(dmaREG->DMAPCR, DmaEccTestEnable);

    /* Restore DMA register states */
    dmaREG->DMAPCR = regBackupPCR;
    dmaREG->DMASECCCTRL = regBackupSECCTL;

    /* Restore ESM registers states */
    esmREG->IESR1 = regBkupIntEnaSet;
    esmREG->EEPAPR1 = regBckupErrInfulence;

    return success;
  • Hi Phadon,

    The SDL includes an example for RM57Lx device. Please check if you are able to get the ESM error after performing the DMA ECC selftest in the example.

    retVal = SL_SelfTest_DMA(DMA_ECC_TEST_MODE_1BIT);
    INCREMENT_PASS_FAIL_COUNTER(ST_PASS, retVal);

    retVal = SL_SelfTest_DMA(DMA_ECC_TEST_MODE_2BIT);
    INCREMENT_PASS_FAIL_COUNTER(ST_PASS, retVal);

    Please let me know if ESM flag is set when running those tests.

    BTW, To enable generation of single-bit error to ESM, the SBE_EVT_EN bit of DMASECCCTRL must be configured to 0xA. It is disabled by default.