TMS320F280039C: Continuous NMI Reset Loop caused by memcpy() reading corrupted Flash sector on every boot

Part Number: TMS320F280039C
Other Parts Discussed in Thread: UNIFLASH

Problem : 
MCU is stuck in a continuous NMI reset loop on every boot.

Findings after debugging : 
When the memcpy() call that reads from Flash is commented out, the MCU boots and runs normally without any resets. This strongly suggests the Flash sector being read is corrupted and triggering an uncorrectable ECC error on every memcpy() access. Also the corrupted sector works fine with memcpy() if i flash the code again by erasing the whole flash using CCS / Uniflash / C2prog Tools

The code line used is as below :

1. void app_meta_data_flash_init(); is called once everytime on bootup, 
2. mcal_flash_init();
mcal_flash_sector_erase(0x000AF000);
mcal_flash_program_autoecc_sector(0x000AF000, (uint32_t *)buffer, sizeof(struct mdata_t));
 
All these functions are one is to one given in Flash Api Examples only function name is changed
3. void app_meta_data_flash_write(struct mdata_t *buffer) is used based on requirement of application

I have gone through all the documents/datasheets required to work with Flash API.. 
This is happening randomly on the application that we are using and no sequence of occurence is found. Currently I am not able to recreate Flash corruption. Please help in ways of recreating flash corruption
struct mdata_t{
    uint16_t image_present;                                          
    uint16_t reset_cause;                                            
    uint32_t battery_unique_key;                                      
};

void app_meta_data_flash_write(struct mdata_t *buffer)
{
    mcal_flash_sector_erase(0x000AF000);
    mcal_flash_program_autoecc_sector(0x000AF000, (uint32_t *)buffer, sizeof(struct mdata_t));  // size is 8 words
}

void app_meta_data_flash_read()
{
    memcpy(&mdata, (uint16_t *)0xAF000, sizeof(struct mdata_t));
}

void app_meta_data_flash_init()
{
mcal_flash_init();    
app_meta_data_flash_read(); 
}

  • Hi Tanmay,

    Let me go through the issue, i will get back shortly.

    Thanks

    Aswin

  • Please help in ways of recreating flash corruption

    On of the option to create flash corruption is using a power interrupt simulation, reset the MCU mid write to leave a sector in corrupted state.

    Please ensure of the below checks are correct - 

    Verify the flash wait state are correct as per the datasheet.

    What i understand is that, the auto ECC write during the mcal_flash_program_autoecc_sector() created corrupted ECC code. Full erase (not just sector erase) clears residual bit patterns that caused the corruption.

    I would suggest for a full flash erase before every new program load(not a sector erase)

    Thanks

    Aswin

  • Hi Aswin, 

    On of the option to create flash corruption is using a power interrupt simulation, reset the MCU mid write to leave a sector in corrupted state

    At what function in the below code should i do power interrupt simulation ? Also does power interrupt simulation mean to turn off Power or something else ?  Also I do have access to only API's of flash library and not the enitre function 

    I would suggest for a full flash erase before every new program load(not a sector erase)

    So my application is running from Bank 0 and I am using Bank 2 (0xAF000) to store some data during runtime at particular trigger point, so need to erase sector only.. 

  • void mcal_flash_program_autoecc_sector(uint32_t address, uint32_t *buffer, uint32_t size)
    {
    uint32 u32Index = 0;
    uint16 i = 0;
    Fapi_StatusType oReturnCheck;
    Fapi_FlashStatusType oFlashStatus;
    Fapi_FlashStatusWordType oFlashStatusWord;
    
    //
    // A data buffer of max 8 16-bit words can be supplied to the program
    // function.
    // Each word is programmed until the whole buffer is programmed or a
    // problem is found. However to program a buffer that has more than 8
    // words, program function can be called in a loop to program 8 words for
    // each loop iteration until the whole buffer is programmed.
    //
    // Remember that the main array flash programming must be aligned to
    // 64-bit address boundaries and each 64 bit word may only be programmed
    // once per write/erase cycle. Meaning the length of the data buffer
    // (3rd parameter for Fapi_issueProgrammingCommand() function) passed
    // to the program function can only be either 4 or 8.
    //
    // Program data in Flash using "AutoEccGeneration" option.
    // When AutoEccGeneration option is used, Flash API calculates ECC for the
    // given 64-bit data and programs it along with the 64-bit main array data.
    // Note that any unprovided data with in a 64-bit data slice
    // will be assumed as 1s for calculating ECC and will be programmed.
    //
    // Note that data buffer (Buffer) is aligned on 64-bit boundary for verify
    // reasons.
    //
    // Monitor ECC address for the sector below while programming with
    // AutoEcc mode.
    //
    // In this example, the number of bytes specified in the flash buffer
    // are programmed in the flash sector below along with auto-generated
    // ECC.
    //
    
    for (i = 0, u32Index = address;
    //(u32Index < (address + WORDS_IN_FLASH_BUFFER));
    (u32Index < (address + size));
    i += 8, u32Index += 8)
    {
    
    oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32Index, (uint16 *)(buffer + i / 2),
    8, 0, 0, Fapi_AutoEccGeneration);
    
    //
    // 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);
    }
    
    //
    // Read FMSTAT register contents to know the status of FSM after
    // program command to see if there are any program operation related
    // errors
    //
    oFlashStatus = Fapi_getFsmStatus();
    if (oFlashStatus != 0)
    {
    //
    // Check FMSTAT and debug accordingly
    //
    // FMSTAT_Fail();
    }
    
    //
    // Verify the programmed values. Check for any ECC errors.
    //
    oReturnCheck = Fapi_doVerify((uint32 *)u32Index,
    4, buffer + (i / 2),
    &oFlashStatusWord);
    
    if (oReturnCheck != Fapi_Status_Success)
    {
    //
    // Check Flash API documentation for possible errors
    //
    // Example_Error(oReturnCheck);
    }
    }
    }
    
    

  • Hi Aswin, 

    Also 

    Can you help with,
    1. Why flash is corrupted, Is there any issue in FlashAPI which is creating this problem? (RCA)
    2. How can we avoid flash corruption? (Action item)
  • Hi Tanmay, Few suggestions in the flow - 

    • Clear the FSM status before you issue the program command.
    • Enable program/erase protection for select sectors where this example is located before the program command

    Also i see you are commenting all the error return statements, If an error has occurred, there is no way to track it if it is commented. Please uncomment that and check if any error is getting returned.

    Thanks

    Aswin

  • Hello Tanmay,

    I have a couple additional questions:

    1. Has this flash corruption occurred multiple times, even though it is not directly reproducible?

    2. If you have seen it again, were you able to capture the value of the ECC error registers?

    3. How old is the device? How many read/write cycles does it have?

    Erroneous flash programming is best managed by keeping parameters (read/write cycles, etc.) within the ranges given on the device datasheet.

    During programming, Fapi_getFsmStatus will report a failure after the programming command if flash was not programmed successfully. In your code this failure is not caught because FMSTAT_Fail() is commented out.

    Additionally, you can add interrupt handlers for ECC errors to avoid resetting the device entirely.

    Best,

    Alex

  • Has this flash corruption occurred multiple times, even though it is not directly reproducible?

    Yes this has occurred multiple times, occurrence is not predictable

    If you have seen it again, were you able to capture the value of the ECC error registers?

    The bottleneck is the MCU is mounted on PCB and we don't have debuggers in the PCB, as this is happening on the initialisation of the code before we init all the peripherals.. so there is no way to get the ECC error registers with whatever the Production PCB is .. 
    So my intent is to recreate this on Launchpad where i do have debugger

    How old is the device? How many read/write cycles does it have?

     The read/write count is not more than 50 cycles on whatever device this has occured 


    Can you guys help with recreation ? That question is still unanswered ? Once recreated.. I can manage on working around solutions

    At what function in the below code should i do power interrupt simulation ? Also does power interrupt simulation mean to turn off Power or something else ?  Also I do have access to only API's of flash library and not the enitre function 


    Thanks,
    Tanmay

  • Hello Tanmay,

    If the error is intermittent, it will be hard to reproduce the exact conditions that cause it. An alternative to corrupt flash would be to program/erase the flash in a loop and then power off the device while it is running. The timing may be tricky on this though -- you need to interrupt the flash pump in the middle of its operation.

    Best,

    Alex

  • Hi Alex, 

    I was able to recreate the issue multiple times :

    What I did : 
    1. Tried to erase and program a particular sector at every 100ms
    2. Blink an LED at 100ms
    3. Tried doing multiple Power Reset and was able to recreate in one of the instance

    How did i identify : 
    1. I am using below function once after every power reset (In initialistion of code)

    void app_meta_data_flash_read()
    {
        memcpy(&mdata, (uint16_t *)0xAF000, sizeof(struct mdata_t));
    }

    2. After flash getting corrupted, the LED stopped blinking .. indicating the continuous loop is not getting executed
    3. If I comment the above function on top of corrupted event, the LED starts blinking again.. indicating memcpy is the issue

    Further Deep Dive :
    1. Using debugger I was able to identify the it was stuck in NMI Interrupt Handler 
    2. 

    During programming, Fapi_getFsmStatus will report a failure after the programming command if flash was not programmed successfully. In your code this failure is not caught because FMSTAT_Fail() is commented out


    Your suggestion of using FSM Status to identify the Flash error wont be applicable here, as this function is used after issuing programming command and check if programming is okay or not .. but the failure here is mid of flash operation and we are able to know the failure in next power reset cycle where the programming command was never performed (just reading the flash using memcpy)

    What are your further suggestions in this ? 

    Thanks,
    Tanmay

  • Also, is there a way to identify if a particular flash address is corrupted using any functions or method .. considering I am never using erase or write operations of flash API in my entire code..

  • Hi Tanmay,

    Apologies for the delayed response, let us go through your previous response, will get back to you shortly.

    Thanks

    Aswin

  • Tanmay,

    Please find attached an example of handling a Flash ECC uncorrectable error NMI

    Best,

    Alex

    //#############################################################################
    //
    // FILE:   flashapi_ex1_programming.c
    //
    // TITLE:  Flash programming example
    //
    //! \addtogroup driver_example_list
    //! <h1> Flash Programming with AutoECC, DataAndECC, DataOnly and EccOnly </h1>
    //!
    //! This example demonstrates how to program Flash using API's following options
    //! 1. AutoEcc generation
    //! 2. DataOnly and EccOnly
    //! 3. DataAndECC
    //!
    //! \b External \b Connections \n
    //!  - None.
    //!
    //! \b Watch \b Variables \n
    //!  - None.
    //!
    //
    //#############################################################################
    // $Copyright:
    // Copyright (C) 2026 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"
    #include <stdio.h>
    
    //
    // Include Flash API include file
    //
    #include "F021_F28003x_C28x.h"
    
    // Include Flash API example header file
    //
    #include "flash_programming_f28003x.h"
    
    //
    // Defines
    //
    
    //
    // Length (in 16-bit words) of data buffer used for program
    //
    #define  WORDS_IN_FLASH_BUFFER    0x100
    
    //
    // Globals
    //
    
    //
    // Data Buffers used for program operation using the flash API program function
    //
    #pragma  DATA_SECTION(Buffer,"DataBufferSection");
    uint16   Buffer[WORDS_IN_FLASH_BUFFER];
    uint32   *Buffer32 = (uint32 *)Buffer;
    
    
    //
    // Prototype of the functions used in this example
    //
    void Example_Error(Fapi_StatusType status);
    void Example_Done(void);
    void Example_CallFlashAPI(void);
    void FMSTAT_Fail(void);
    void ECC_Fail(void);
    
    void Example_EraseBanks(void);
    void Example_EraseSector(void);
    void Example_ProgramUsingAutoECC(void);
    void Example_ProgramBankUsingAutoECC(void);
    void Example_ProgramUsingDataOnlyECCOnly(void);
    void Example_ProgramUsingDataAndECC(void);
    void Flash_DisablePrefetch_SW_Workaround(uint32_t ctrlBase);
    void Flash_EnablePrefetch_SW_Workaround(uint32_t ctrlBase);
    __interrupt void nmiISR(void);
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        // Copy the Flash initialization code from Flash to RAM
        // Copy the Flash API from Flash to RAM
        // Configure Flash wait-states, fall back power mode, performance features
        // and ECC
        //
        Device_init();
    
        //
        // Initialize GPIO
        //
        Device_initGPIO();
    
        //
        // 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);
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //
        // At 120MHz, execution wait-states for external oscillator is 5. Modify the
        // wait-states when the system clock frequency is changed.
        //
        Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, 5);
    
    
        //
        // Flash API functions should not be executed from the same bank on which
        // erase/program operations are in progress.
        // Also, note that there should not be any access to the Flash bank on
        // which erase/program operations are in progress.  Hence below function
        // is mapped to RAM for execution.
        //
        Example_CallFlashAPI();
    
    
        //
        // Example is done here
        //
        Example_Done();
    }
    
    //
    // nmiISR -  The interrupt service routine called when the NMI is generated
    //           on an uncorrectable Flash ECC error.
    //
    volatile bool nmiISRFlag;
    uint16_t nmiStatus;
    volatile bool errorISRFlag;
    
    __interrupt void nmiISR(void)
    {
        //
        // Set a flag indicating the NMI ISR occurred and get the NMI status.
        //
        nmiISRFlag = true;
        nmiStatus = SysCtl_getNMIFlagStatus();
        
        //
        // Clear all the flags.
        //
        uint16 nmi_sts = SysCtl_getNMIFlagStatus();
        SysCtl_clearAllNMIFlags();
    
        if (nmiStatus == (SYSCTL_NMI_FLUNCERR | SYSCTL_NMI_NMIINT))
        {
            uint32_t err_addr_low = Flash_getUncorrectableErrorAddressLow(FLASH0ECC_BASE);
            uint32_t err_addr_high = Flash_getUncorrectableErrorAddressHigh(FLASH0ECC_BASE);
            
            Flash_clearUncorrectableInterruptFlag(FLASH0ECC_BASE);
            EALLOW;
            HWREG(FLASH0ECC_BASE + FLASH_O_ERR_STATUS_CLR) = 0xFFFFFFFFU;
            EDIS;
    
            // Erase Flash Banks
            Example_EraseSector();
    
            if(err_addr_low)
            {
                printf("Uncorrectable error at addr = 0x%lx\n", err_addr_low);
            }
    
            if(err_addr_high)
            {
                printf("Uncorrectable error at addr = 0x%lx\n", err_addr_high);
            }
        }
    }
    
    //*****************************************************************************
    //  Example_CallFlashAPI
    //
    //  This function will interface to the flash API.
    //  Flash API functions used in this function are executed from RAM in this
    //  example.
    //*****************************************************************************
    #ifdef __cplusplus
    #pragma CODE_SECTION(".TI.ramfunc");
    #else
    #pragma CODE_SECTION(Example_CallFlashAPI, ".TI.ramfunc");
    #endif
    void Example_CallFlashAPI(void)
    {
        uint16 i = 0;
        Fapi_StatusType  oReturnCheck;
    
        //
        // Initialize the Flash API by providing the Flash register base address
        // and operating frequency(in MHz).
        // This function is required to initialize the Flash API based on System
        // frequency before any other Flash API operation can be performed.
        // This function must also be called whenever System frequency or RWAIT is
        // changed.
        //
        oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 
                                          DEVICE_SYSCLK_FREQ/1000000U);
    
        if(oReturnCheck != Fapi_Status_Success)
        {
            //
            // Check Flash API documentation for possible errors
            //
            Example_Error(oReturnCheck);
        }
    
        //
        // Disable prefetch mechanism before changing wait states
        //
        Flash_DisablePrefetch_SW_Workaround(FLASH0CTRL_BASE);
        //
        // Initialize the Flash banks and FMC for erase and program operations.
        // Fapi_setActiveFlashBank() function sets the Flash banks and FMC for
        // further Flash operations to be performed on the banks.
        //
        oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
    
        if(oReturnCheck != Fapi_Status_Success)
        {
            //
            // Check Flash API documentation for possible errors
            //
            Example_Error(oReturnCheck);
        }
        //
        // Enable prefetch mechanism before changing wait states
        //
        Flash_EnablePrefetch_SW_Workaround(FLASH0CTRL_BASE);
    
        //
        // Erase bank 1 before programming
        //
        Example_EraseBanks();
        //
        // Fill a buffer with data to program into the flash.
        //
        for(i=0; i < WORDS_IN_FLASH_BUFFER; i++)
        {
            Buffer[i] = i;
        }
    
        //
        // Program the sector using DataOnly and ECCOnly options
        //
        Example_ProgramUsingDataOnlyECCOnly();
    
        //
        // Erase bank 1 before programming
        //
        Example_EraseBanks();
    
    }
    
    
    //*****************************************************************************
    //  Example_ProgramUsingDataOnlyECCOnly
    //
    //  Example function to Program data in Flash using "DataOnly" option and ECC
    //  using "EccOnly" option.
    //  Flash API functions used in this function are executed from RAM in this
    //  example.
    //*****************************************************************************
    #ifdef __cplusplus
    #pragma CODE_SECTION(".TI.ramfunc");
    #else
    #pragma CODE_SECTION(Example_ProgramUsingDataOnlyECCOnly, ".TI.ramfunc");
    #endif
    void Example_ProgramUsingDataOnlyECCOnly(void)
    {
        uint32 u32Index = 0;
        uint16 i = 0;
        Fapi_StatusType  oReturnCheck;
        Fapi_FlashStatusType  oFlashStatus;
        Fapi_FlashStatusWordType  oFlashStatusWord;
    
        //
        // Program data using "DataOnly" option and ECC using "EccOnly" option.
        //
        // When DataOnly option is used, Flash API will program only the data
        // portion in Flash at the address specified.
        //
        // When EccOnly option is used, Flash API will program only the ECC portion
        // in Flash ECC memory space (Flash main array address should be provided
        // for this function and not the corresponding ECC address).
        // Fapi_calculateEcc is used to calculate the corresponding ECC of the data.
        //
        // Note that data buffer (Buffer) is aligned on 64-bit boundary for verify
        // reasons.
        //
        // In this example, 0x100 bytes are programmed in Flash Sector6
        // along with the specified ECC.
        //
    
        for(i=0, u32Index = Bone_Sector1_start;
           (u32Index < (Bone_Sector1_start + WORDS_IN_FLASH_BUFFER));
           i+= 8, u32Index+= 8)
        {
    
            oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32Index,Buffer+i,
                                                            8, 0, 0, Fapi_DataOnly);
    
            //
            // 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);
            }
    
            //
            // Read FMSTAT register contents to know the status of FSM after
            // program command to see if there are any program operation related
            // errors
            //
            oFlashStatus = Fapi_getFsmStatus();
            if(oFlashStatus != 0)
            {
                //Check FMSTAT and debug accordingly
                FMSTAT_Fail();
            }
    
    
            //
            // Verify the programmed values.  Trigger ECC NMI
            //
            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);
            }
        }
    }
    
    //*****************************************************************************
    //  Example_EraseBanks
    //
    //  Example function to Erase data of a sector in Flash.
    //  Flash API functions used in this function are executed from RAM in this
    //  example.
    //*****************************************************************************
    #ifdef __cplusplus
    #pragma CODE_SECTION(".TI.ramfunc");
    #else
    #pragma CODE_SECTION(Example_EraseBanks, ".TI.ramfunc");
    #endif
    void Example_EraseBanks(void)
    {
        Fapi_StatusType  oReturnCheck;
        Fapi_FlashStatusType  oFlashStatus;
        Fapi_FlashStatusWordType  oFlashStatusWord;
        uint32 u32CurrentAddress;
    
        u32CurrentAddress = Bzero_Sector8_start;
        oReturnCheck = Fapi_issueBankEraseCommand((uint32 *)u32CurrentAddress, 0x001F);
    
        // Wait until FSM is done with bank erase operation
        while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady)
        {
             //
             // Initialize the Erase Pulses to zero after issuing max pulses
             //
             if(HWREG(FLASH0CTRL_BASE + FLASH_O_ACC_EP) > MAX_ERASE_PULSE)
             {
                 EALLOW;
    
                 //
                 // Enable Flash Optimization
                 //
                 HWREG(FLASH0CTRL_BASE + FLASH_O_OPT) = OPT_ENABLE;
    
                 HWREG(FLASH0CTRL_BASE + FLASH_O_ERA_PUL) =
                         HWREG(FLASH0CTRL_BASE + FLASH_O_ERA_PUL) &
                         ~(uint32_t)FLASH_ERA_PUL_MAX_ERA_PUL_M;
    
                 //
                 // Disable Flash Optimization
                 //
                 HWREG(FLASH0CTRL_BASE + FLASH_O_OPT) = OPT_DISABLE;
    
                 EDIS;
             }
        }
    
        if(oReturnCheck != Fapi_Status_Success)
        {
            // Check Flash API documentation for possible errors
            Example_Error(oReturnCheck);
        }
    
        // Read FMSTAT register contents to know the status of FSM after
        // erase command to see if there are any erase operation related errors
        oFlashStatus = Fapi_getFsmStatus();
        if(oFlashStatus != 0)
        {
            // Check Flash API documentation for FMSTAT and debug accordingly
            // Fapi_getFsmStatus() function gives the FMSTAT register contents.
            // Check to see if any of the EV bit, ESUSP bit, CSTAT bit or
            // VOLTSTAT bit is set (Refer to API documentation for more details).
            FMSTAT_Fail();
        }
    
        u32CurrentAddress = Bone_Sector0_start;
        oReturnCheck = Fapi_issueBankEraseCommand((uint32 *)u32CurrentAddress, 0x0000);
    
        // Wait until FSM is done with bank erase operation
        while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady)
        {
            //
            // Initialize the Erase Pulses to zero after issuing max pulses
            //
            if(HWREG(FLASH0CTRL_BASE + FLASH_O_ACC_EP) > MAX_ERASE_PULSE)
            {
                EALLOW;
    
                //
                // Enable Flash Optimization
                //
                HWREG(FLASH0CTRL_BASE + FLASH_O_OPT) = OPT_ENABLE;
    
                HWREG(FLASH0CTRL_BASE + FLASH_O_ERA_PUL) =
                        HWREG(FLASH0CTRL_BASE + FLASH_O_ERA_PUL) &
                        ~(uint32_t)FLASH_ERA_PUL_MAX_ERA_PUL_M;
    
                //
                // Disable Flash Optimization
                //
                HWREG(FLASH0CTRL_BASE + FLASH_O_OPT) = OPT_DISABLE;
    
                EDIS;
             }
        }
    
        if(oReturnCheck != Fapi_Status_Success)
        {
            // Check Flash API documentation for possible errors
            Example_Error(oReturnCheck);
        }
    
        // Read FMSTAT register contents to know the status of FSM after
        // erase command to see if there are any erase operation related errors
        oFlashStatus = Fapi_getFsmStatus();
        if(oFlashStatus != 0)
        {
            // Check Flash API documentation for FMSTAT and debug accordingly
            // Fapi_getFsmStatus() function gives the FMSTAT register contents.
            // Check to see if any of the EV bit, ESUSP bit, CSTAT bit or
            // VOLTSTAT bit is set (Refer to API documentation for more details).
            FMSTAT_Fail();
        }
    
        // Do blank check
        // Verify that Bank0 sectors 5-15 and Bank 1 sectors 0-15 are erased.
        // The Erase command itself does a verify as it goes.
        // Hence erase verify by CPU reads (Fapi_doBlankCheck()) is optional.
        u32CurrentAddress = Bzero_Sector5_start;
        oReturnCheck = Fapi_doBlankCheck((uint32 *)u32CurrentAddress,
                       (27*Sector8KB_u32length),
                       &oFlashStatusWord);
    
        if(oReturnCheck != Fapi_Status_Success)
        {
            // Check Flash API documentation for error info
            Example_Error(oReturnCheck);
        }
    }
    
    //*****************************************************************************
    //  Example_EraseSector
    //
    //  Example function to Erase data of a sector in Flash.
    //  Flash API functions used in this function are executed from RAM in this
    //  example.
    //*****************************************************************************
    #ifdef __cplusplus
    #pragma CODE_SECTION(".TI.ramfunc");
    #else
    #pragma CODE_SECTION(Example_EraseSector, ".TI.ramfunc");
    #endif
    void Example_EraseSector(void)
    {
        Fapi_StatusType  oReturnCheck;
        Fapi_FlashStatusType  oFlashStatus;
        Fapi_FlashStatusWordType  oFlashStatusWord;
    
        //
        // Issue ClearMore command
        //
        oReturnCheck = Fapi_issueAsyncCommand(Fapi_ClearMore);
    
        //
        // 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);
        }
    
        //
        // Erase the sector that is programmed in the above example
        // Erase Sector1
        //
        oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,
                       (uint32 *)Bone_Sector1_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);
        }
    
        //
        // Read FMSTAT register contents to know the status of FSM after
        // erase command to see if there are any erase operation related errors
        //
        oFlashStatus = Fapi_getFsmStatus();
            if(oFlashStatus != 0)
        {
            //
            // Check Flash API documentation for FMSTAT and debug accordingly
            // Fapi_getFsmStatus() function gives the FMSTAT register contents.
            // Check to see if any of the EV bit, ESUSP bit, CSTAT bit or
            // VOLTSTAT bit is set (Refer to API documentation for more details).
            //
            FMSTAT_Fail();
        }
    
        //
        // Verify that Sector1 is erased
        //
        oReturnCheck = Fapi_doBlankCheck((uint32 *)Bone_Sector1_start,
                       Sector8KB_u32length,
                       &oFlashStatusWord);
    
        if(oReturnCheck != Fapi_Status_Success)
        {
            //
            // Check Flash API documentation for error info
            //
            Example_Error(oReturnCheck);
        }
    }
    
    /* Below is the code for Flash_DisablePrefetch_SW_Workaround().  */
    
    //*****************************************************************************
    //
    //! Disables flash prefetch mechanism and adds 7 cycle delay
    //!
    //! \param ctrlBase is the base address of the flash wrapper control registers.
    //!
    //! \return None.
    //
    //*****************************************************************************
    
    #ifdef __cplusplus
    #pragma CODE_SECTION(".TI.ramfunc");
    #else
    #pragma CODE_SECTION(Flash_DisablePrefetch_SW_Workaround, ".TI.ramfunc");
    #endif
    void Flash_DisablePrefetch_SW_Workaround(uint32_t ctrlBase)
    {
        //
        // Check the arguments.
        //
        ASSERT(Flash_isCtrlBaseValid(ctrlBase));
    
        //
        // Disable flash prefetch
        //
        Flash_disablePrefetch(ctrlBase);
    
        //
        // Force a pipeline flush to ensure that the write to the last register
        // configured occurs before returning.
        //
        FLASH_DELAY_CONFIG;
    }
    
    /* Below is the code for Flash_EnablePrefetch_SW_Workaround()  */
    
    //*****************************************************************************
    //
    //! Enables flash prefetch mechanism and adds 7 cycle delay
    //!
    //! \param ctrlBase is the base address of the flash wrapper control registers.
    //!
    //! \return None.
    //
    //*****************************************************************************
    
    #ifdef __cplusplus
    #pragma CODE_SECTION(".TI.ramfunc");
    #else
    #pragma CODE_SECTION(Flash_EnablePrefetch_SW_Workaround, ".TI.ramfunc");
    #endif
    void Flash_EnablePrefetch_SW_Workaround(uint32_t ctrlBase)
    {
        //
        // Check the arguments.
        //
        ASSERT(Flash_isCtrlBaseValid(ctrlBase));
    
        //
        // Disable flash prefetch
        //
        Flash_enablePrefetch(ctrlBase);
    
        //
        // Force a pipeline flush to ensure that the write to the last register
        // configured occurs before returning.
        //
        FLASH_DELAY_CONFIG;
    }
    
    //******************************************************************************
    // For this example, just stop here if an API error is found
    //******************************************************************************
    void Example_Error(Fapi_StatusType status)
    {
        //
        //  Error code will be in the status parameter
        //
        __asm("    ESTOP0");
    }
    
    //******************************************************************************
    //  For this example, once we are done just stop here
    //******************************************************************************
    void Example_Done(void)
    {
        __asm("    ESTOP0");
    }
    
    //******************************************************************************
    // For this example, just stop here if FMSTAT fail occurs
    //******************************************************************************
    void FMSTAT_Fail(void)
    {
        __asm("    ESTOP0");
    }
    
    //******************************************************************************
    // For this example, just stop here if ECC fail occurs
    //******************************************************************************
    void ECC_Fail(void)
    {
        __asm("    ESTOP0");
    }
    
    //
    // End of File
    //