//###########################################################################
//
// FILE:   flash_programming_cpu01.c
//
// TITLE:  Flash Programming Example for F2837xD.
//
//! \addtogroup dual_example_list
//! <h1> Flash Programming </h1>
//!
//! This example demonstrates F021 Flash API usage.
//!
//
//###########################################################################
// $TI Release: F2837xD Support Library v3.07.00.00 $
// $Release Date: Sun Sep 29 07:34:54 CDT 2019 $
// $Copyright:
// Copyright (C) 2013-2019 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 "F28x_Project.h"
#include "../common/include/F28x_Project.h"
#include <string.h>
#include "flash_programming_c28.h" // Flash API example header file
#include "F021_F2837xD_C28x.h"
#include "flash_programming.h"

//
// Defines
//
#define  WORDS_IN_FLASH_BUFFER    0xFF  // Data/Program Buffer used for testing
                                        // the flash API functions

#ifdef __TI_COMPILER_VERSION__
    #if __TI_COMPILER_VERSION__ >= 15009000
        #define ramFuncSection ".TI.ramfunc"
    #else
        #define ramFuncSection "ramfuncs"
    #endif
#endif

#pragma CODE_SECTION(Flash_Programming, ramFuncSection);
#pragma CODE_SECTION(Flash_CallFlashAPI, ramFuncSection);
#pragma CODE_SECTION(Flash_write,ramFuncSection);
#pragma CODE_SECTION(Flash_erase,ramFuncSection);
#pragma CODE_SECTION(Flash_read,ramFuncSection);
#pragma CODE_SECTION(Flash_Error,ramFuncSection);
#pragma CODE_SECTION(Flash_Done,ramFuncSection);

//
// Globals
//
//#pragma DATA_SECTION(Buffer,"BufferDataSection");
uint16   Buffer[WORDS_IN_FLASH_BUFFER + 1];
uint32   *Buffer32 = (uint32 *)Buffer;

uint16   Buffer1[WORDS_IN_FLASH_BUFFER + 1];
uint32   *Buffer321 = (uint32 *)Buffer1;

volatile uint16 flash_state = 0;

//
// Main
//

void Flash_Programming(void)
{
//
// Step 1. Initialize System Control:
// Enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//
    InitSysCtrl();

//
//  Unlock CSM
//
//  If the API functions are going to run in unsecured RAM
//  then the CSM must be unlocked in order for the flash
//  API functions to access the flash.
//  If the flash API functions are executed from secure memory
//  then this step is not required.
//
    //DcsmZ1Unlock();

//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
// InitGpio();  // Skipped for this example

//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
    DINT;

//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
//
    InitPieCtrl();

//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
    IER = 0x0000;
    IFR = 0x0000;

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in DSP2802x_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//
    InitPieVectTable();

//
// Copy time critical code and Flash setup code to RAM
// This includes InitFlash(), Flash API functions and any functions that are
// assigned to ramfuncs section.
// The  RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart
// symbols are created by the linker. Refer to the device .cmd file.
//
   //memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

//
// Call Flash Initialization to setup flash waitstates
// This function must reside in RAM
//
    InitFlash();

//
// Gain pump semaphore
//
    SeizeFlashPump();

//
// Jump to RAM and call the Flash API functions
//
    Flash_CallFlashAPI();
}

//
// Flash_CallFlashAPI - This function will interface to the flash API.
//                        Flash API functions used in this function are
//                        executed from RAM
//
void Flash_CallFlashAPI(void)
{
    uint32 u32Index = 0;
    uint16 i = 0;

    Fapi_StatusType oReturnCheck;
    volatile Fapi_FlashStatusType oFlashStatus;
    Fapi_FlashStatusWordType oFlashStatusWord;

//    while(1)
//    {
        switch(flash_state)
        {
        case 0:
            break;
        case 1: // FLASH Sector M data write

            SeizeFlashPump();

            EALLOW;
            //
            // This function is required to initialize the Flash API based on System
            // frequency before any other Flash API operation can be performed
            //
            oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 200);

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

            //
            // Fapi_setActiveFlashBank function sets the Flash bank and FMC for further
            // Flash operations to be performed on the bank
            //
            oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
            if(oReturnCheck != Fapi_Status_Success)
            {
                //
                // Check Flash API documentation for possible errors
                //
                //Flash_Error(oReturnCheck);
            }

            ///////////////////////////////////////////////////////////

            //
            // Erase Sector C
            //
            oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,
                           (uint32 *)Bzero_SectorM_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
                // If Erase command fails, use Fapi_getFsmStatus() function to get the
                // FMSTAT register contents to see if any of the EV bit, ESUSP bit,
                // CSTAT bit or VOLTSTAT bit is set (Refer to API documentation for
                // more details)
                //
                //Flash_Error(oReturnCheck);
            }

            //
            // Read FMSTAT register contents to know the status of FSM after
            // program command for any debug
            //
            oFlashStatus = Fapi_getFsmStatus();
            if (oFlashStatus!=0)
            {
                //Flash_Error(oReturnCheck);
            }
            //
            // Verify that SectorL is erased.  The Erase step itself does a
            // verify as it goes.  This verify is a 2nd verification that can be done.
            //
            oReturnCheck = Fapi_doBlankCheck((uint32 *)Bzero_SectorM_start,
                                             Bzero_16KSector_u32length,
                                             &oFlashStatusWord);
            if(oReturnCheck != Fapi_Status_Success)
            {
                //
                // Check Flash API documentation for possible errors
                // If Erase command fails, use Fapi_getFsmStatus() function to get the
                // FMSTAT register contents to see if any of the EV bit, ESUSP bit,
                // CSTAT bit or VOLTSTAT bit is set (Refer to API documentation for
                // more details)
                //
                //Flash_Error(oReturnCheck);
            }

            ///////////////////////////////////////////////////////////


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

            for(i=0, u32Index = Bzero_SectorM_start;
               (u32Index < (Bzero_SectorM_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);
                while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);
                if(oReturnCheck != Fapi_Status_Success)
                {
                    //
                    // Check Flash API documentation for possible errors
                    //
                    //Flash_Error(oReturnCheck);
                }

                //
                // Read FMSTAT register contents to know the status of FSM after
                // program command for any debug
                //
                oFlashStatus = Fapi_getFsmStatus();
                if(oFlashStatus != 0)
                {
                //Check FMSTAT and debug accordingly
                    //Flash_Error(oReturnCheck);
                }

                //
                // Verify the values programmed.  The Program step itself does a verify
                // as it goes.  This verify is a 2nd verification that can be done.
                //
                oReturnCheck = Fapi_doVerify((uint32 *)u32Index,
                                             4, Buffer32+(i/2),
                                             &oFlashStatusWord);
                if(oReturnCheck != Fapi_Status_Success)
                {
                    //
                    // Check Flash API documentation for possible errors
                    //
                    //Flash_Error(oReturnCheck);
                }
            }

            //
            // Enable ECC
            //
            Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0xA;

            EDIS;// protect set

            //
            // Leave control over flash pump
            //
            ReleaseFlashPump();
            flash_state = 0;
            break;
        case 2: // FLASH Sector M Erase

            SeizeFlashPump();

            //Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0x0;

            EALLOW; // protect clear

            //
            // This function is required to initialize the Flash API based on System
            // frequency before any other Flash API operation can be performed
            //
            oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 200);
            if(oReturnCheck != Fapi_Status_Success)
            {
                //
                // Check Flash API documentation for possible errors
                //
                //Flash_Error(oReturnCheck);
            }

            //
            // Fapi_setActiveFlashBank function sets the Flash bank and FMC for further
            // Flash operations to be performed on the bank
            //
            oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
            if(oReturnCheck != Fapi_Status_Success)
            {
                //
                // Check Flash API documentation for possible errors
                //
                //Flash_Error(oReturnCheck);
            }

            //
            // Erase Sector C
            //
            oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,
                           (uint32 *)Bzero_SectorM_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
                // If Erase command fails, use Fapi_getFsmStatus() function to get the
                // FMSTAT register contents to see if any of the EV bit, ESUSP bit,
                // CSTAT bit or VOLTSTAT bit is set (Refer to API documentation for
                // more details)
                //
                //Flash_Error(oReturnCheck);
            }

            //
            // Read FMSTAT register contents to know the status of FSM after
            // program command for any debug
            //
            oFlashStatus = Fapi_getFsmStatus();
            if (oFlashStatus!=0)
            {
                //Flash_Error(oReturnCheck);
            }
            //
            // Verify that SectorL is erased.  The Erase step itself does a
            // verify as it goes.  This verify is a 2nd verification that can be done.
            //
            oReturnCheck = Fapi_doBlankCheck((uint32 *)Bzero_SectorM_start,
                                             Bzero_16KSector_u32length,
                                             &oFlashStatusWord);
            while(Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
            if(oReturnCheck != Fapi_Status_Success)
            {
                Flash_Error(oReturnCheck);
            }
            //
            // Enable ECC
            //
            //Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0xA;

            EDIS;// protect set

            //
            // Leave control over flash pump
            //
            ReleaseFlashPump();

            //EDIS;
            //EINT;
            flash_state = 0;
            break;
        case 3: // FLASH 0xFFFF dummy data write

            //SeizeFlashPump();

            //DINT;
            EALLOW;

#if 0
            for(i=0, u32Index = Bzero_SectorM_start;
               (u32Index < (Bzero_SectorM_start + WORDS_IN_FLASH_BUFFER)) &&
               (oReturnCheck == Fapi_Status_Success); i++, u32Index++)
            {
                oReturnCheck = Fapi_doMarginRead((uint32 *)u32Index, Buffer321+i, 1, Fapi_NormalRead);
            }

#else
            oReturnCheck = Fapi_doMarginRead((uint32 *)Bzero_SectorM_start, Buffer321, WORDS_IN_FLASH_BUFFER, Fapi_NormalRead);
            if(oReturnCheck != Fapi_Status_Success)
            {
                //
                // Check Flash API documentation for possible errors
                //
                Flash_Error(oReturnCheck);
            }

            oFlashStatus = Fapi_getFsmStatus();
            if(oFlashStatus != 0)
            {
            //Check FMSTAT and debug accordingly
                Flash_Error(oReturnCheck);
            }
#endif
            //
            // Enable ECC
            //
            //Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0xA;

            EDIS;// protect set

            //
            // Leave control over flash pump
            //
            //ReleaseFlashPump();

            flash_state = 0;
            break;
        default:
            break;
        }
    //}
}


//void Flash_write(uint16 *buf, uint16 len)
void Flash_write(void)
{
    uint32 u32Index = 0;
    uint16 i = 0;

    Fapi_StatusType oReturnCheck;
    volatile Fapi_FlashStatusType oFlashStatus;
    Fapi_FlashStatusWordType oFlashStatusWord;

    //uint32 *p_buf = (uint32*)buf;

    SeizeFlashPump();

    EALLOW;

    //
    // This function is required to initialize the Flash API based on System
    // frequency before any other Flash API operation can be performed
    //
    oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 200);

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

    //
    // Fapi_setActiveFlashBank function sets the Flash bank and FMC for further
    // Flash operations to be performed on the bank
    //
    oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
    if(oReturnCheck != Fapi_Status_Success)
    {
        //
        // Check Flash API documentation for possible errors
        //
        //Flash_Error(oReturnCheck);
    }

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

    for(i=0, u32Index = Bzero_SectorM_start;
       (u32Index < (Bzero_SectorM_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);
        while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);
        if(oReturnCheck != Fapi_Status_Success)
        {
            //
            // Check Flash API documentation for possible errors
            //
            //Flash_Error(oReturnCheck);
        }

        //
        // Read FMSTAT register contents to know the status of FSM after
        // program command for any debug
        //
        oFlashStatus = Fapi_getFsmStatus();
        if(oFlashStatus != 0)
        {
        //Check FMSTAT and debug accordingly
            //Flash_Error(oReturnCheck);
        }

        //
        // Verify the values programmed.  The Program step itself does a verify
        // as it goes.  This verify is a 2nd verification that can be done.
        //
        oReturnCheck = Fapi_doVerify((uint32 *)u32Index,
                                     4, Buffer32+(i/2),
                                     &oFlashStatusWord);
        if(oReturnCheck != Fapi_Status_Success)
        {
            //
            // Check Flash API documentation for possible errors
            //
            //Flash_Error(oReturnCheck);
        }
    }

    //
    // Enable ECC
    //
    Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0xA;

    EDIS;// protect set

    //
    // Leave control over flash pump
    //
    ReleaseFlashPump();
}


void Flash_erase(void)
{
    uint32 u32Index = 0;
    uint16 i = 0;

    Fapi_StatusType oReturnCheck;
    volatile Fapi_FlashStatusType oFlashStatus;
    Fapi_FlashStatusWordType oFlashStatusWord;

    SeizeFlashPump();

    //Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0x0;

    EALLOW; // protect clear

    //
    // This function is required to initialize the Flash API based on System
    // frequency before any other Flash API operation can be performed
    //
    oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 200);
    if(oReturnCheck != Fapi_Status_Success)
    {
        //
        // Check Flash API documentation for possible errors
        //
        //Flash_Error(oReturnCheck);
    }

    //
    // Fapi_setActiveFlashBank function sets the Flash bank and FMC for further
    // Flash operations to be performed on the bank
    //
    oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
    if(oReturnCheck != Fapi_Status_Success)
    {
        //
        // Check Flash API documentation for possible errors
        //
        //Flash_Error(oReturnCheck);
    }

    //
    // Erase Sector C
    //
    oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,
                   (uint32 *)Bzero_SectorM_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
        // If Erase command fails, use Fapi_getFsmStatus() function to get the
        // FMSTAT register contents to see if any of the EV bit, ESUSP bit,
        // CSTAT bit or VOLTSTAT bit is set (Refer to API documentation for
        // more details)
        //
        //Flash_Error(oReturnCheck);
    }

    //
    // Read FMSTAT register contents to know the status of FSM after
    // program command for any debug
    //
    oFlashStatus = Fapi_getFsmStatus();
    if (oFlashStatus!=0)
    {
        //Flash_Error(oReturnCheck);
    }
    //
    // Verify that SectorL is erased.  The Erase step itself does a
    // verify as it goes.  This verify is a 2nd verification that can be done.
    //
    oReturnCheck = Fapi_doBlankCheck((uint32 *)Bzero_SectorM_start,
                                     Bzero_16KSector_u32length,
                                     &oFlashStatusWord);
    while(Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
    if(oReturnCheck != Fapi_Status_Success)
    {
        Flash_Error(oReturnCheck);
    }
    //
    // Enable ECC
    //
    //Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0xA;

    EDIS;// protect set

    //
    // Leave control over flash pump
    //
    ReleaseFlashPump();
}


void Flash_read(uint32 *Buffer321)
{
    uint32 u32Index = 0;
    uint16 i = 0;

    Fapi_StatusType oReturnCheck;
    volatile Fapi_FlashStatusType oFlashStatus;
    Fapi_FlashStatusWordType oFlashStatusWord;

    //SeizeFlashPump();

    EALLOW;

#if 0
    for(i=0, u32Index = Bzero_SectorM_start;
       (u32Index < (Bzero_SectorM_start + WORDS_IN_FLASH_BUFFER)) &&
       (oReturnCheck == Fapi_Status_Success); i++, u32Index++)
    {
        oReturnCheck = Fapi_doMarginRead((uint32 *)u32Index, Buffer321+i, 1, Fapi_NormalRead);
    }

#else
    oReturnCheck = Fapi_doMarginRead((uint32 *)Bzero_SectorM_start, Buffer321, WORDS_IN_FLASH_BUFFER, Fapi_NormalRead);
    if(oReturnCheck != Fapi_Status_Success)
    {
        //
        // Check Flash API documentation for possible errors
        //
        Flash_Error(oReturnCheck);
    }

    oFlashStatus = Fapi_getFsmStatus();
    if(oFlashStatus != 0)
    {
    //Check FMSTAT and debug accordingly
        Flash_Error(oReturnCheck);
    }
#endif
    //
    // Enable ECC
    //
    //Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0xA;

    EDIS;// protect set

    //
    // Leave control over flash pump
    //
    //ReleaseFlashPump();
}

//
// Flash_Error - For this example, if an error is found just stop here
//

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

//
// Flash_Done - For this example, once we are done just stop here
//

void Flash_Done(void)
{
    //__asm("    ESTOP0");
}

//
// End of file
//
