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.

TMS320F280049: disable Flash ecc still enter NMI ISRwhen do fault injection

Part Number: TMS320F280049
Other Parts Discussed in Thread: C2000WARE

Hi Expert,

When do the test with below code, if enable flash ecc, the test will go to NMI isr, 

but if disable flash ecc as below code show and compile the code again, we find that the test will still go to NMI isr, which does not make sense,

could you help explain the reason? thanks. 

C:\ti\c2000\C2000Ware_4_01_00_00\libraries\diagnostic\f28004x\examples\sdl_ex_flash_ecc_test

  • Hi Strong, 

    1. Please check if ECC is enabled later at another point in the code.  

    2. Did you already check the NMI registers to know the NMI source and confirm that it is flash uncomfortable error?

    Thanks and regards,

    Vamsi

  • Hi Strong,

    Do you need further support on this?  Or can I close this post?

    Thanks and regards,

    Vamsi

  • Vamsi,

    Sorry for the late response on this issue.

    1. Please check if ECC is enabled later at another point in the code.  

    --> No,, the code is the example code, only modify the code below, you can easily reproduce this issue. 

    C:\ti\c2000\C2000Ware_4_01_00_00\libraries\diagnostic\f28004x\examples\sdl_ex_flash_ecc_test

    2. Did you already check the NMI registers to know the NMI source and confirm that it is flash uncomfortable error?

    Yes, see below register: 

  • Hi Strong,

    Thank you for the response.  I will be able to take a look at this on 29th Tuesday.

    Thanks and regards,
    Vamsi

  • Hi Strong,

    What it the flash uncorrectable error address that you see in the flash ECC registers?  Also, check whether ECC is enabled or disabled when you look at the flash ECC registers for the error address.

    Note that there is no way for the ECC check to get enabled unless it is enabled by the code after code disables it (unless there is a reset during application execution).

    Thanks and regards,
    Vamsi

  • Vamsi,

    It seem ECC is disable but cause UNC_ERR_L error.

    Can you help reproduce this issue in the example?

    you can set a breakpoint here to check.

  • //#############################################################################
    //
    // FILE:   sdl_ex_flash_ecc_test.c
    //
    // TITLE:  Test of ECC logic in Flash
    //
    //! \defgroup sdl_ex_flash_ecc_test Test of ECC logic in Flash
    //! <h1>sdl_ex_flash_ecc_test</h1>
    //!
    //! This example demonstrates how to test the Flash ECC logic functionality.
    //!
    //! A software test of the Flash ECC logic can be performed with the help of
    //! ECC test registers. Using the test registers, you can generate both single
    //! bit errors and uncorrectable errors. For additional details on the
    //! implementation of this diagnostic, see the "SECDED Logic Correctness Check"
    //! section in the device technical reference manual.
    //!
    //! \b External \b Connections \n
    //!  - None.
    //!
    //! \b Watch \b Variables \n
    //!  - \b nmiISRFlag - Indicates that the NMI was triggered and called the ISR.
    //!  - \b nmiStatus - NMI status flags read in the ISR.
    //!  - \b errorISRFlag - Indicates that the correctable ECC error interrupt was
    //!       triggered and called the ISR.
    //!  - \b errorStatus - Error status flags read in the ISR, indicating whether
    //!       an error was single-bit or uncorrectable.
    //!  - \b errorCount - Number of correctable errors detected read in the ISR.
    //!  - \b errorType - For a single-bit error, indicates whether it was in the
    //!       data or ECC bits.
    //!  - \b dataOut - For a single-bit error, displays the corrected data.
    //!  - \b result - Status of a successful detection and handling of ECC errors.
    //!
    //
    //#############################################################################
    // $TI Release: C2000 Diagnostic Library v3.00.00 $
    // $Release Date: Thu Mar  3 16:52:56 IST 2022 $
    // $Copyright:
    // Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
    //
    // 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.
    // $
    //#############################################################################
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    
    //
    // Defines
    //
    #define PASS                    0U
    #define FAIL                    1U
    
    #define ISR_LOOP_TIMEOUT        0x3U
    #define MASK_ALL_BUT_FLASH_ERR  0x3F6UL
    
    //
    // Flash ECC Logic test values
    //
    #define TEST_FLASH_DATAL        ((uint32_t)(TEST_FLASH_DATA64))
    #define TEST_FLASH_DATAH        ((uint32_t)(TEST_FLASH_DATA64 >> 32))
    #define TEST_FLASH_ADDR         0x00090000UL
    #define TEST_FLASH_DATA64       0xFEDCBA0987654321ULL
    
    //
    // Typedefs
    //
    typedef enum
    {
        TEST_ECC_BLOCK_LOW  = 0x00,    //!< Low 64-bit block
        TEST_ECC_BLOCK_HIGH = 0x02     //!< High 64-bit block
    } ECCBlock;
    
    //
    // Globals
    //
    uint16_t calcECC;
    uint32_t result = FAIL;
    volatile bool nmiISRFlag;
    uint16_t nmiStatus;
    volatile bool errorISRFlag;
    uint16_t errorStatus;
    uint16_t errorCount;
    uint32_t errorType;
    uint64_t dataOut;
    
    //
    // Function Prototypes
    //
    __interrupt void nmiISR(void);
    __interrupt void corrErrorISR(void);
    uint16_t runCorrectableDataErrorTest(void);
    uint16_t runCorrectableECCErrorTest(void);
    uint16_t runUncorrectableErrorTest(void);
    void testECCBlock(uint64_t data, uint32_t address, ECCBlock eccBlock,
                      uint16_t ecc);
    #pragma CODE_SECTION(testECCBlock, ".TI.ramfunc");
    uint16_t calculateECC(uint32_t address, uint64_t data);
    
    //
    // Main
    //
    void main(void)
    {
        uint16_t failCount;
    
        //
        // Initialize device clock and peripherals.
        //
        Device_init();
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // Clear all the NMI and Flash error status flags.
        //
        EALLOW;
        HWREG(FLASH0ECC_BASE + FLASH_O_ERR_STATUS_CLR) = 0xFFFFFFFFU;
        HWREG(FLASH0ECC_BASE + FLASH_O_ERR_INTCLR) = 0xFFFFFFFFU;
        EDIS;
    
        SysCtl_clearAllNMIFlags();
    
        //
        // Plug the NMI and Flash correctable error ISRs.
        //
        Interrupt_register(INT_NMI, &nmiISR);
        Interrupt_register(INT_FLASH_CORR_ERR, corrErrorISR);
        Interrupt_enable(INT_FLASH_CORR_ERR);
    
        //
        // Enabling the NMI global interrupt (typically already enabled by boot ROM
        // or GEL file).
        //
        SysCtl_enableNMIGlobalInterrupt();
    
        //
        // Enable Global Interrupt (INTM) and Real Time interrupt (DBGM).
        //
        EINT;
        ERTM;
    
        //
        // Calculate ECC on test data.
        //
        calcECC = calculateECC(TEST_FLASH_ADDR, TEST_FLASH_DATA64);
    
        //
        // Enable ECC.
        //
    //    Flash_enableECC(FLASH0ECC_BASE);
        Flash_disableECC(FLASH0ECC_BASE);
    
        //
        // Test detection of correctable ECC errors in Flash data bits.
        //
        failCount = runCorrectableDataErrorTest();
    
        //
        // Test detection of correctable ECC errors in Flash ECC bits.
        //
        failCount += runCorrectableECCErrorTest();
    
        //
        // Test detection of uncorrectable ECC errors in Flash.
        //
        failCount += runUncorrectableErrorTest();
    
        //
        // Status of a successful handling of the ECC errors.
        //
        if(failCount != 0U)
        {
            result = FAIL;
        }
        else
        {
            result = PASS;
        }
    
        //
        // Loop here and check results in the CCS Expressions view.
        //
        while(1);
    }
    
    //
    // nmiISR -  The interrupt service routine called when the NMI is generated
    //           on an uncorrectable Flash ECC error.
    //
    __interrupt void nmiISR(void)
    {
        //
        // Set a flag indicating the NMI ISR occurred and get the NMI status.
        //
        nmiISRFlag = true;
        nmiStatus = SysCtl_getNMIFlagStatus();
    
        //
        // Record the error test status.
        //
        errorStatus = Flash_getECCTestStatus(FLASH0ECC_BASE);
    
    
        //
        // Clear all the flags.
        //
        EALLOW;
        HWREG(FLASH0ECC_BASE + FLASH_O_ERR_STATUS_CLR) = 0xFFFFFFFFU;
        EDIS;
    
        Flash_clearUncorrectableInterruptFlag(FLASH0ECC_BASE);
        SysCtl_clearAllNMIFlags();
    }
    
    //
    // corrErrorISR - The interrupt service routine called when the correctable
    //                error count hits the configured interrupt threshold.
    //
    __interrupt void corrErrorISR(void)
    {
        //
        // Set a flag indicating the RAM error ISR occurred.
        //
        errorISRFlag = true;
    
        //
        // Record the type of error injected, the status flags, the corrected data,
        // and the number of single-bit ECC errors detected.
        //
        errorType = Flash_getECCTestSingleBitErrorType(FLASH0ECC_BASE);
        errorStatus = Flash_getECCTestStatus(FLASH0ECC_BASE);
        dataOut = ((uint64_t)Flash_getTestDataOutHigh(FLASH0ECC_BASE) << 32) |
                  (uint64_t)Flash_getTestDataOutLow(FLASH0ECC_BASE);
        errorCount = Flash_getErrorCount(FLASH0ECC_BASE);
    
        //
        // Clear all the flags.
        //
        EALLOW;
        HWREG(FLASH0ECC_BASE + FLASH_O_ERR_STATUS_CLR) = 0xFFFFFFFFU;
        EDIS;
    
        Flash_clearSingleErrorInterruptFlag(FLASH0ECC_BASE);
    
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP12);
    }
    
    //
    // runCorrectableDataErrorTest - Runs a test of the correctable data error
    //      detection and correction as well as the error interrupt threshold.
    //
    uint16_t runCorrectableDataErrorTest(void)
    {
        uint16_t fail = 0U;
        uint16_t timeout= ISR_LOOP_TIMEOUT;
    
        //
        // Clear error status variables.
        //
        errorISRFlag = false;
        errorStatus = 0U;
        errorType = 0U;
        errorCount = 0U;
        dataOut = 0U;
    
        //
        // Configure the correctable error interrupt threshold to >1 errors.
        //
        Flash_setErrorThreshold(FLASH0ECC_BASE, 1U);
    
        //
        // Flip a single bit in the data to inject a correctable error for the
        // test to detect.
        //
        testECCBlock(TEST_FLASH_DATA64 ^ 0x80U, TEST_FLASH_ADDR,
                     TEST_ECC_BLOCK_LOW, calcECC);
    
        //
        // Generate another single bit error to increase the count above the
        // threshold.
        //
        testECCBlock(TEST_FLASH_DATA64 ^ ((uint64_t)0x1U << 37), TEST_FLASH_ADDR,
                     TEST_ECC_BLOCK_LOW, calcECC);
    
        //
        // Wait until the error interrupt is fired.
        //
        while((errorISRFlag != true) && (timeout != 0U))
        {
            timeout--;
        }
    
        //
        // Check if interrupt occurred as expected or if the loop timed out.
        //
        if(timeout == 0U)
        {
            fail++;
        }
    
        //
        // Check if the appropriate correctable Flash error flag was set.
        //
        if((errorStatus & FLASH_SINGLE_ERROR) != FLASH_SINGLE_ERROR)
        {
            fail++;
        }
    
        //
        // Check if the error count is 2.
        //
        if(errorCount != 2U)
        {
            fail++;
        }
    
        //
        // Check if the error was a data error.
        //
        if(errorType != FLASH_DATA_ERR)
        {
            fail++;
        }
    
        //
        // Check that the data value was corrected properly.
        //
        if(dataOut != TEST_FLASH_DATA64)
        {
            fail++;
        }
    
        return(fail);
    }
    
    //
    // runCorrectableECCErrorTest - Runs a test of the correctable error detection.
    //
    uint16_t runCorrectableECCErrorTest(void)
    {
        uint16_t fail = 0U;
        uint16_t timeout= ISR_LOOP_TIMEOUT;
    
        //
        // Clear error status variables.
        //
        errorISRFlag = false;
        errorStatus = 0U;
        errorType = 0U;
    
        //
        // Configure the correctable error interrupt threshold to >0 errors.
        //
        Flash_setErrorThreshold(FLASH0ECC_BASE, 0U);
    
        //
        // Flip a single bit in the data to inject a correctable error for the
        // test to detect.
        //
        testECCBlock(TEST_FLASH_DATA64, TEST_FLASH_ADDR,
                     TEST_ECC_BLOCK_LOW, calcECC ^ 0x2U);
    
        //
        // Wait until the error interrupt is fired.
        //
        while((errorISRFlag != true) && (timeout != 0U))
        {
            timeout--;
        }
    
        //
        // Check if interrupt occurred as expected or if the loop timed out.
        //
        if(timeout == 0U)
        {
            fail++;
        }
    
        //
        // Check if the appropriate correctable Flash error flag was set.
        //
        if((errorStatus & FLASH_SINGLE_ERROR) != FLASH_SINGLE_ERROR)
        {
            fail++;
        }
    
        //
        // Check if the error was an ECC error.
        //
        if(errorType != FLASH_ECC_ERR)
        {
            fail++;
        }
    
        return(fail);
    }
    
    //
    // runUncorrectableErrorTest - Runs a test of the uncorrectable data error
    //      detection and associated NMI generation.
    //
    uint16_t runUncorrectableErrorTest(void)
    {
        uint16_t fail = 0U;
        uint16_t timeout= ISR_LOOP_TIMEOUT;
    
        //
        // Clear error status variables.
        //
        nmiISRFlag = false;
        nmiStatus = 0U;
        errorStatus = 0U;
    
        //
        // Flip multiple bits in the data to inject an uncorrectable error for the
        // test to detect.
        //
        testECCBlock(TEST_FLASH_DATA64 ^ 0x30U, TEST_FLASH_ADDR,
                     TEST_ECC_BLOCK_LOW, calcECC);
    
        //
        // Wait until the NMI is fired.
        //
        while((nmiISRFlag != true) && (timeout != 0U))
        {
            timeout--;
        }
    
        //
        // Check if interrupt occurred as expected or if the loop timed out.
        //
        if(timeout == 0U)
        {
            fail++;
        }
    
        //
        // Check if the NMI triggered was due to an uncorrectable Flash error.
        //
        if((nmiStatus & SYSCTL_NMI_FLUNCERR) != SYSCTL_NMI_FLUNCERR)
        {
            fail++;
        }
    
        //
        // Check if the appropriate uncorrectable Flash error flag was set.
        //
        if((errorStatus & FLASH_UNC_ERROR) != FLASH_UNC_ERROR)
        {
            fail++;
        }
    
        return(fail);
    }
    
    //
    // testECCBlock - Sets up the ECC test registers and performs the ECC
    //                calculation to detect and error if one is injected.
    //
    void testECCBlock(uint64_t data, uint32_t address, ECCBlock eccBlock,
                      uint16_t ecc)
    {
        //
        // Write 128-bit flash address in FADDR_TEST
        //
        Flash_setECCTestAddress(FLASH0ECC_BASE, address);
    
        //
        // Write lower 32 bits of data in FDATAL_TEST
        //
        Flash_setDataLowECCTest(FLASH0ECC_BASE, (uint32_t)data);
    
        //
        // Write upper 32 bits of data in FDATAH_TEST
        //
        Flash_setDataHighECCTest(FLASH0ECC_BASE, (uint32_t)(data >> 32));
    
        //
        // Write corresponding ECC in the FECC_TEST
        // Insert double bit error in flash ecc
        //
        Flash_setECCTestECCBits(FLASH0ECC_BASE, ecc);
    
        //
        // Select the ECC block to be tested. Only one of the SECDED modules (out
        // of the two SECDED modules that work on lower 64 bits and upper 64 bits
        // of a read 128-bit data) at a time can be tested.
        //
        if(eccBlock == TEST_ECC_BLOCK_LOW)
        {
            Flash_selectLowECCBlock(FLASH0ECC_BASE);
        }
        else
        {
            Flash_selectHighECCBlock(FLASH0ECC_BASE);
        }
    
        //
        // Enable the ECC Test Mode
        //
        Flash_enableECCTestMode(FLASH0ECC_BASE);
    
        //
        // Perform ECC calculation
        //
        Flash_performECCCalculation(FLASH0ECC_BASE);
    
        //
        // Disable the ECC Test Mode
        //
        Flash_disableECCTestMode(FLASH0ECC_BASE);
    }
    
    //
    // calcECC - Calculate the ECC for an address/data pair. This code comes from
    //           the ECC Calculation Algorithm appendix of the Flash API reference
    //           guide (SPNU628). If you are using the Flash API in your code, you
    //           could use Fapi_calculateEcc() instead.
    //
    uint16_t calculateECC(uint32_t address, uint64_t data)
    {
        const uint32_t addrSyndrome[8] = {0x554EAU, 0x0BAD1U, 0x2A9B5U, 0x6A78DU,
                                          0x19F83U, 0x07F80U, 0x7FF80U, 0x0007FU};
        const uint64_t dataSyndrome[8] = {0xB4D1B4D14B2E4B2EU, 0x1557155715571557U,
                                          0xA699A699A699A699U, 0x38E338E338E338E3U,
                                          0xC0FCC0FCC0FCC0FCU, 0xFF00FF00FF00FF00U,
                                          0xFF0000FFFF0000FFU, 0x00FFFF00FF0000FFU};
        const uint16_t parity = 0xFCU;
        uint64_t xorData;
        uint32_t xorAddr;
        uint16_t bit, eccBit, eccVal;
    
        //
        // Extract bits "20:2" of the address
        //
        address = (address >> 2) & 0x7FFFFU;
    
        //
        // Compute the ECC one bit at a time.
        //
        eccVal = 0U;
    
        for (bit = 0U; bit < 8U; bit++)
        {
            //
            // Apply the encoding masks to the address and data
            //
            xorAddr = address & addrSyndrome[bit];
            xorData = data & dataSyndrome[bit];
    
            //
            // Fold the masked address into a single bit for parity calculation.
            // The result will be in the LSB.
            //
            xorAddr = xorAddr ^ (xorAddr >> 16);
            xorAddr = xorAddr ^ (xorAddr >> 8);
            xorAddr = xorAddr ^ (xorAddr >> 4);
            xorAddr = xorAddr ^ (xorAddr >> 2);
            xorAddr = xorAddr ^ (xorAddr >> 1);
    
            //
            // Fold the masked data into a single bit for parity calculation.
            // The result will be in the LSB.
            //
            xorData = xorData ^ (xorData >> 32);
            xorData = xorData ^ (xorData >> 16);
            xorData = xorData ^ (xorData >> 8);
            xorData = xorData ^ (xorData >> 4);
            xorData = xorData ^ (xorData >> 2);
            xorData = xorData ^ (xorData >> 1);
    
            //
            // Merge the address and data, extract the ECC bit, and add it in
            //
            eccBit = ((uint16_t)xorData ^ (uint16_t)xorAddr) & 0x0001U;
            eccVal |= eccBit << bit;
        }
    
        //
        // Handle the bit parity. For odd parity, XOR the bit with 1
        //
        eccVal ^= parity;
        return eccVal;
    }
    
    //
    // End of File
    //
    

  • Hi Strong,

    I am not able to reproduce this in my setup.

    We can have a meeting if needed.  Or you can send me your project so that I can modify/build and experiment as needed.

    Thanks and regards,
    Vamsi

  • https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/171/sdl_5F00_ex_5F00_flash_5F00_ecc_5F00_test.7z

    Vamsi,

    I post the project here, and you need to set a breakpoint in nmiISR to reproduce. 

  • Hi Strong,

    We need to have a meeting.

    Let me know your convenient date/time.  We can discuss offline.

    Thanks and regards,

    Vamsi

  • Strong,

    As discussed in the meeting, NMI is occurring since the ECC test mode is enabled with an uncorrectable error insertion.

    I am closing this post.

    Thanks and regards,

    Vamsi

  • Vamsi,

    Thanks for your support!