ecc错误检——sdl_ex_flash_ecc_test.c文件的使用

之前一直是按照FLASH_API手册上的流程来操作,使用ecc option选项来插入错误,但是移植代码之后尝试了几次都会出现一些莫名其妙的问题,有时会崩溃报错,有些时候会在一烧录就插入错误,然后也没有找到解决的方法。在E2E论坛上求助之后,今天收到了回复:

没想到C2000里面还能存在专门用于ecc引入错误的c文件。sdl_ex_flash_ecc_test.c的内容如下:

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

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

这里面定义了三个不同的错误验证函数:1. runCorrectableDataErrorTest();2. runCorrectableECCErrorTest(); 3. runUncorrectableErrorTest()。第一个函数引用可修正的数据错误;第二个函数引入ECC错误(就是在根据数据得到的ECC编码中引入错误,然后进行验证。但这种情况在现实中不太常见);第三个函数用于插入不可修正错误,用于验证寄存器对不可修改错误的行为,记录错误并进入中断)。

通过void testECCBlock(uint64_t data, uint32_t address, ECCBlock eccBlock, uint16_t ecc)来设置在哪里插入错误。

比如: testECCBlock(TEST_FLASH_DATA64 ^ 0x80U, TEST_FLASH_ADDR, TEST_ECC_BLOCK_LOW, calcECC),就是在数据的第7位进行翻转(1000 0000);

testECCBlock(TEST_FLASH_DATA64, TEST_FLASH_ADDR, TEST_ECC_BLOCK_LOW, calcECC ^ 0x2U), 是在数据的第二位进行翻转(0000 0010);

在testECCBlock(TEST_FLASH_DATA64 ^ 0x30U, TEST_FLASH_ADDR, TEST_ECC_BLOCK_LOW, calcECC)这个函数中,是对数据的第4和5位进行翻转(0011 0000)。

testECCBlock()函数通过手动设置测试地址、数据和 ECC 值,模拟 Flash 读取过程中的 ECC 校验,来验证系统对单 bit 和多 bit 错误的检测与响应能力。写入 64 位测试数据和人为构造的 ECC 值,然后选择测试的是 128 位数据中的低 64 位还是高 64 位部分。接着启用 ECC 测试模式并执行一次 ECC 校验,此时如果数据或 ECC 中存在人为制造的错误,系统就会触发相应的中断(可纠正错误)或 NMI(不可纠正错误),从而验证 ECC 检测机制是否有效。

例程里面是给出了一个固定的数据和地址,但是我们的例程里面数据是一个持续写入的过程,所以需要对它进行一下修改:

#include "driverlib.h"
#include "device.h"

#include "F021_F28004x_C28x.h"

#include "flash_programming_f28004x.h"

#define  WORDS_IN_FLASH_BUFFER    0xFF

#define PASS                    0U
#define FAIL                    1U

#define ISR_LOOP_TIMEOUT        0x3U
#define MASK_ALL_BUT_FLASH_ERR  0x3F6UL

#define TEST_FLASH_DATAL        ((uint32_t)(TEST_FLASH_DATA64))
#define TEST_FLASH_DATAH        ((uint32_t)(TEST_FLASH_DATA64 >> 32))
#define TEST_FLASH_ADDR         Bzero_Sector6_start
//#define TEST_FLASH_DATA64       0xFEDCBA0987654321ULL

typedef enum
{
    TEST_ECC_BLOCK_LOW  = 0x00,    //!< Low 64-bit block
    TEST_ECC_BLOCK_HIGH = 0x02     //!< High 64-bit block
} ECCBlock;

#pragma  DATA_SECTION(Buffer,"DataBufferSection");
uint16   Buffer[WORDS_IN_FLASH_BUFFER + 1];
uint32   *Buffer32 = (uint32 *)Buffer;
uint8    eccbuffer[(WORDS_IN_FLASH_BUFFER+1)/8];
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;

__interrupt void nmiISR(void);
__interrupt void corrErrorISR(void);
uint16_t runCorrectableDataErrorTest(uint32_t addr, uint64_t flashData, uint16_t eccdata);
uint16_t runCorrectableECCErrorTest(uint32_t addr, uint64_t flashData, uint16_t eccdata);
uint16_t runUncorrectableErrorTest(uint32_t addr, uint64_t flashData, uint16_t eccdata);
void testECCBlock(uint64_t data, uint32_t address, ECCBlock eccBlock,
                  uint16_t ecc);
uint16_t calculateECC(uint32_t address, uint64_t data);

void Example_Error(Fapi_StatusType status);
void Example_Done(void);
void Example_CallFlashAPI(void);
void FMSTAT_Fail(void);

void main(void)
{

    Device_init();

    Device_initGPIO();

    Interrupt_initModule();

    Interrupt_initVectorTable();

    EALLOW;
    HWREG(FLASH0ECC_BASE + FLASH_O_ERR_STATUS_CLR) = 0xFFFFFFFFU;
    HWREG(FLASH0ECC_BASE + FLASH_O_ERR_INTCLR) = 0xFFFFFFFFU;
    EDIS;

    SysCtl_clearAllNMIFlags();

    Interrupt_register(INT_NMI, &nmiISR);
    Interrupt_register(INT_FLASH_CORR_ERR, corrErrorISR);
    Interrupt_enable(INT_FLASH_CORR_ERR);

    SysCtl_enableNMIGlobalInterrupt();

    EINT;
    ERTM;

    Example_CallFlashAPI();

}

#ifdef __cplusplus
#pragma CODE_SECTION(".TI.ramfunc");
#else
#pragma CODE_SECTION(Example_CallFlashAPI, ".TI.ramfunc");
#endif

void Example_CallFlashAPI(void)
{
    uint32 u32Index = 0;
    uint16 i = 0;
    Fapi_StatusType  oReturnCheck;
    Fapi_FlashStatusType  oFlashStatus;
    Fapi_FlashStatusWordType  oFlashStatusWord;
    uint16_t failCount;

    oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 100);

    if(oReturnCheck != Fapi_Status_Success)
    {
        // Check Flash API documentation for possible errors
        Example_Error(oReturnCheck);
    }

    oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);

    if(oReturnCheck != Fapi_Status_Success)
    {
        // Check Flash API documentation for possible errors
        Example_Error(oReturnCheck);
    }


    // Erase Flash Bank0 sector6
    oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,
                                        (uint32 *)Bzero_Sector6_start);

    // Wait until FSM is done with erase sector operation
    while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}

	if(oReturnCheck != Fapi_Status_Success)
	{
		// Check Flash API documentation for possible errors
		Example_Error(oReturnCheck);
	}

    oFlashStatus = Fapi_getFsmStatus();
    if(oFlashStatus != 0)
    {

    	FMSTAT_Fail();
    }


    oReturnCheck = Fapi_doBlankCheck((uint32 *)Bzero_Sector6_start,
    		       Sector8KB_u32length,
                   &oFlashStatusWord);

    if(oReturnCheck != Fapi_Status_Success)
    {
        // Check Flash API documentation for error info
        Example_Error(oReturnCheck);
    }

    Flash_enableECC(FLASH0ECC_BASE);

    for(i=0; i <= WORDS_IN_FLASH_BUFFER; i++)
    {
        Buffer[i] = i;
    }

    for(i=0, u32Index = Bzero_Sector6_start;
       (u32Index < (Bzero_Sector6_start + WORDS_IN_FLASH_BUFFER)) &&
       (oReturnCheck == Fapi_Status_Success); i+= 8, u32Index+= 8)
    {
		oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32Index, Buffer+i, 8, 0, 0, Fapi_AutoEccGeneration);
        //oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32Index, Buffer + i, 8, eccbuffer, 2, Fapi_DataAndEcc);

		// Wait until the Flash program operation is over
		while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);

		if(oReturnCheck != Fapi_Status_Success)
		{
			// Check Flash API documentation for possible errors
			Example_Error(oReturnCheck);
		}

		oFlashStatus = Fapi_getFsmStatus();
		if(oFlashStatus != 0)
		{
			//Check FMSTAT and debug accordingly
			FMSTAT_Fail();
		}

		// ECC 检查用:读取刚刚写入的数据
        uint64_t flashData = *((uint32_t *)u32Index);
        flashData |= ((uint64_t)*((uint32_t *)(u32Index + 4))) << 32;
        calcECC = calculateECC(u32Index, flashData);

        runCorrectableDataErrorTest(u32Index, flashData, calcECC);

        if(failCount != 0U)
        {
            result = FAIL;
        }
        else
        {
            result = PASS;
        }

        oReturnCheck = Fapi_doVerify((uint32 *)u32Index,
                                     4, Buffer32+(i/2),
                                     &oFlashStatusWord);

		/*if(oReturnCheck != Fapi_Status_Success)
		{
			// Check Flash API documentation for possible errors
			Example_Error(oReturnCheck);
		}*/
    }

    oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,
                   (uint32 *)Bzero_Sector6_start);

    while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}

	if(oReturnCheck != Fapi_Status_Success)
	{
		// Check Flash API documentation for possible errors
		Example_Error(oReturnCheck);
	}

    oFlashStatus = Fapi_getFsmStatus();
    if(oFlashStatus != 0)
    {
    	FMSTAT_Fail();
    }

    oReturnCheck = Fapi_doBlankCheck((uint32 *)Bzero_Sector6_start,
    		       Sector8KB_u32length,
                   &oFlashStatusWord);

    if(oReturnCheck != Fapi_Status_Success)
    {
        // Check Flash API documentation for error info
        Example_Error(oReturnCheck);
    }

    Example_Done();
}

void Example_Error(Fapi_StatusType status)
{
    //  Error code will be in the status parameter
        __asm("    ESTOP0");
}

void Example_Done(void)
{
    __asm("    ESTOP0");
}

void FMSTAT_Fail(void)
{
        __asm("    ESTOP0");
}

__interrupt void nmiISR(void)
{
    nmiISRFlag = true;
    nmiStatus = SysCtl_getNMIFlagStatus();

    errorStatus = Flash_getECCTestStatus(FLASH0ECC_BASE);

    EALLOW;
    HWREG(FLASH0ECC_BASE + FLASH_O_ERR_STATUS_CLR) = 0xFFFFFFFFU;
    EDIS;

    Flash_clearUncorrectableInterruptFlag(FLASH0ECC_BASE);
    SysCtl_clearAllNMIFlags();
}

__interrupt void corrErrorISR(void)
{
    errorISRFlag = true;

    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);

    EALLOW;
    HWREG(FLASH0ECC_BASE + FLASH_O_ERR_STATUS_CLR) = 0xFFFFFFFFU;
    EDIS;

    Flash_clearSingleErrorInterruptFlag(FLASH0ECC_BASE);

    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP12);
}

uint16_t runCorrectableDataErrorTest(uint32_t addr, uint64_t flashData, uint16_t eccdata)
{
    uint16_t fail = 0U;
    uint16_t timeout= ISR_LOOP_TIMEOUT;

    errorISRFlag = false;
    errorStatus = 0U;
    errorType = 0U;
    errorCount = 0U;
    dataOut = 0U;

    Flash_setErrorThreshold(FLASH0ECC_BASE, 1U);

    testECCBlock(flashData ^ 0x80U, addr,
                 TEST_ECC_BLOCK_LOW, eccdata);

    testECCBlock(flashData ^ ((uint64_t)0x1U << 37), addr,
                 TEST_ECC_BLOCK_LOW, eccdata);

    while((errorISRFlag != true) && (timeout != 0U))
    {
        timeout--;
    }

    if(timeout == 0U)
    {
        fail++;
    }

    if((errorStatus & FLASH_SINGLE_ERROR) != FLASH_SINGLE_ERROR)
    {
        fail++;
    }

    if(errorCount != 2U)
    {
        fail++;
    }

    if(errorType != FLASH_DATA_ERR)
    {
        fail++;
    }

    if(dataOut != flashData)
    {
        fail++;
    }

    return(fail);
}

void testECCBlock(uint64_t data, uint32_t address, ECCBlock eccBlock,
                  uint16_t ecc)
{
    Flash_setECCTestAddress(FLASH0ECC_BASE, address);

    Flash_setDataLowECCTest(FLASH0ECC_BASE, (uint32_t)data);

    Flash_setDataHighECCTest(FLASH0ECC_BASE, (uint32_t)(data >> 32));

    Flash_setECCTestECCBits(FLASH0ECC_BASE, ecc);

    if(eccBlock == TEST_ECC_BLOCK_LOW)
    {
        Flash_selectLowECCBlock(FLASH0ECC_BASE);
    }
    else
    {
        Flash_selectHighECCBlock(FLASH0ECC_BASE);
    }

  
    Flash_enableECCTestMode(FLASH0ECC_BASE);

    Flash_performECCCalculation(FLASH0ECC_BASE);

    Flash_disableECCTestMode(FLASH0ECC_BASE);
}

为了方便每次都对写入的错误进行验证,我把函数uint16_t runCorrectableDataErrorTest(uint32_t addr, uint64_t flashData, uint16_t eccdata)修改成了这个形式,引入了几个参数,方便对每次的数据和ecc数据进行错误插入和验证。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值