/******************************************************************************/
/* Williams Advanced Engineering Limited                     Copyright(C) 2021*/
/* Grove                                                  All rights reserved */
/*                                                                            */
/******************************************************************************/



#include "FBL_DataMCfg.h"
#include "FBL_PortUserCode.h"
#include "DcmDspUds_RequestDownload_Prot.h"

// Removing of compiler warnings and errors because of type re-declaration between hal_stdtypes.h and Std_Types.h
#define _BOOLEAN_DECLARED
#define _UINT8_DECLARED
#define _UINT16_DECLARED
#define _UINT32_DECLARED
#define _UINT64_DECLARED
#define _SINT8_DECLARED
#define _SINT16_DECLARED
#define _SINT32_DECLARED
#define _SINT64_DECLARED
#define _FLOAT32_DECLARED
#define _FLOAT64_DECLARED
#define _STD_RETURN_TYPE_DECLARED
#define _STDVERSION_DECLARED

#include "Ios_Flash.h"
#include "sys_core.h"
#include "Ios_Std.h"
#include "Ios_Terminal.h"


//#define DEBUG_FLASH 1

FlashMngrStatusType g_tFlashMngrStatus =
{
 .CurrentFlashJobReq = FlsJobReqNone,
 .CurrentFlashJobStatus = FlsJobComplete,
};

uint32 g_ulBankInitialized;
uint8 g_bStartSector, g_bEndSector, g_bStartBank, g_bEndBank;


const SECTORS flash_sector[NUMBEROFSECTORS]=
{
 (void *)0x00000000, 0x08000, 0,  0, 0xFFF87000,
 (void *)0x00008000, 0x08000, 0,  1, 0xFFF87000,
 (void *)0x00010000, 0x08000, 0,  2, 0xFFF87000,
 (void *)0x00018000, 0x08000, 0,  3, 0xFFF87000,
 (void *)0x00020000, 0x20000, 0,  4, 0xFFF87000,
 (void *)0x00040000, 0x20000, 0,  5, 0xFFF87000,
 (void *)0x00060000, 0x20000, 0,  6, 0xFFF87000,
 (void *)0x00080000, 0x20000, 0,  7, 0xFFF87000,
 (void *)0x000A0000, 0x20000, 0,  8, 0xFFF87000,
 (void *)0x000C0000, 0x20000, 0,  9, 0xFFF87000,
 (void *)0x000E0000, 0x20000, 0, 10, 0xFFF87000,
 (void *)0x00100000, 0x20000, 0, 11, 0xFFF87000,
 (void *)0x00120000, 0x20000, 0, 12, 0xFFF87000,
 (void *)0x00140000, 0x20000, 0, 13, 0xFFF87000,
 (void *)0x00160000, 0x20000, 0, 14, 0xFFF87000,
 (void *)0x00180000, 0x20000, 1,  0, 0xFFF87000,
 (void *)0x001A0000, 0x20000, 1,  1, 0xFFF87000,
 (void *)0x001C0000, 0x20000, 1,  2, 0xFFF87000,
 (void *)0x001E0000, 0x20000, 1,  3, 0xFFF87000,
 (void *)0x00200000, 0x20000, 1,  4, 0xFFF87000,
 (void *)0x00220000, 0x20000, 1,  5, 0xFFF87000,
 (void *)0x00240000, 0x20000, 1,  6, 0xFFF87000,
 (void *)0x00260000, 0x20000, 1,  7, 0xFFF87000,
 (void *)0x00280000, 0x20000, 1,  8, 0xFFF87000,
 (void *)0x002A0000, 0x20000, 1,  9, 0xFFF87000,
 (void *)0x002C0000, 0x20000, 1, 10, 0xFFF87000,
 (void *)0x002E0000, 0x20000, 1, 11, 0xFFF87000

};

const BANKS flash_bank[NUMBEROFBANKS]=
{
 (void *) 0x00000000, 0x180000, 0, 0xFFF87000, 15,
 (void *) 0x00180000, 0x180000, 1, 0xFFF87000, 12,
};


//#define DEBUG_FLS

/* Initialise the flash bank and activate the sectors */
uint8 Fapi_Init(uint32 ulBankToInit) //, uint32 ucEndBank)
{
    //uint32 i;

    if(ulBankToInit < NUMBEROFBANKS)
    {
        /*PLL1_FREQ is defined in system.h */
        if ((Fapi_initializeFlashBanks((uint32)PLL1_FREQ)) == Fapi_Status_Success)
        {
            (void)Fapi_setActiveFlashBank((Fapi_FlashBankType) ulBankToInit);
            (void)Fapi_enableMainBankSectors(0xFFFF);                    /* used for API 2.01*/
            while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady );
            if( FAPI_GET_FSM_STATUS == Fapi_Status_Success )
            {
                g_ulBankInitialized = TRUE;
            }
            else
            {
                g_ulBankInitialized = FALSE;
                return (1);
            }
        }
        else
        {
            return (1);
        }
    }
    else
    {
        return (1);
    }
    return (0); //success
}

uint8 Fls_PgmFlashEraseCheck(uint32 Start_Address, uint32 Bytes)
{
    uint32 ulerror=0;
    register uint32 *ulptr_dst1 = (uint32*) Start_Address;
    register uint32 ulbytes = Bytes;

    while(ulbytes > 0)
    {
        if(*ulptr_dst1++ != 0xFFFFFFFF)
        {
            ulerror = 2;
        }
        ulbytes -= 0x4;
    }
    return(ulerror);
}


uint8 Fls_PgmFlashErase( uint32 ulTargetAddress, uint32 ulLength )
{
    uint8  i=0;
    uint32 ulEndAddr, ulstatus;

    ulEndAddr = ulTargetAddress + ulLength;

    for (i = 0; i < NUMBEROFSECTORS; i++)
    {
        if (ulTargetAddress < (uint32_t)(flash_sector[i].start))
        {
            g_bStartBank  = flash_sector[i-1].bankNumber;
            g_bStartSector   = i-1;
            break;
        }
    }

    for (i = g_bStartSector; i < NUMBEROFSECTORS; i++)
    {
        if (ulEndAddr <= (((uint32_t)flash_sector[i].start) + flash_sector[i].length))
        {
            g_bEndBank   = flash_sector[i].bankNumber;
            g_bEndSector = i;
            break;
        }
    }

    //ulstatus = Fapi_Init(g_bStartBank, g_bEndBank);

    for (i=g_bStartSector; i<(g_bEndSector+1); i++)
    {
        ulstatus = Fapi_Init(flash_sector[i].bankNumber);
        Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, flash_sector[i].start);
        while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
        while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);
    }

    ulstatus =  Fls_PgmFlashEraseCheck((uint32_t)ulTargetAddress, ulLength);

    return (ulstatus);

}


uint8 Fls_PgmFlashWrite( uint32 TargetAddress, const uint8* SourceAddressPtr, uint32 Length )
{
    register uint32 ulsrc = (uint32)SourceAddressPtr;
    register uint32 uldst = TargetAddress;
    uint32 ulbytes, ulbytesSplitWriting, i;
    uint8 Status = 0; //Success
    uint8 bStartBank, bEndBank, bStartSector, bEndSector;
    uint32 ulLength = Length;
    Fapi_StatusType tFApiStatus;
    Fapi_FlashStatusWordType poFlashStatusWord;

    if (ulLength < FLASH_BANK_WIDTH_BYTES)
        ulbytes = ulLength;
    else
        ulbytes = FLASH_BANK_WIDTH_BYTES;


#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
    wcu_printf("Dest: 0x%x -Data Length : 0x%x\n", uldst, ulLength);
#endif

    _coreDisableFlashEcc_();

    while( ulLength > 0)
    {
        // find which bank and which sector the target address belongs to
        for (i = 0; i < NUMBEROFSECTORS; i++)
        {
            if ((uldst >= (uint32)(flash_sector[i].start)) && (uldst < ((uint32)(flash_sector[i].start) + flash_sector[i].length)))
            {
                bStartBank  = flash_sector[i].bankNumber;
                bStartSector= i;
                break;
            }
        }
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
        wcu_printf("Dest: 0x%x - SBank: 0x%x - SSect: 0x%x - i: %d\n", uldst, bStartBank, bStartSector, i);
#endif
        for (i = bStartSector; i < NUMBEROFSECTORS; i++)
        {
            if ((uldst+ulbytes) <= (((uint32)flash_sector[i].start) + flash_sector[i].length))
            {
                bEndBank   = flash_sector[i].bankNumber;
                bEndSector = i;

                break;
            }
        }

#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
        wcu_printf("Dst: 0x%x - EB: 0x%x  - ES: 0x%x - i: %d\n", uldst, bEndBank, bEndSector, i);
        fnIosFlushTxQueue();
#endif


        if(flash_sector[bStartSector].bankNumber != flash_sector[bEndSector].bankNumber)
        {
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
            wcu_printf("Need to Write data across banks!\n");
#endif

            //number of bytes to be written in the last sector of the current bank
            ulbytesSplitWriting = ((uint32)flash_sector[bStartSector].length + (uint32)flash_sector[bStartSector].start) - uldst;

#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
            wcu_printf("Dest: 0x%x -Total length: 0x%x - Partial: 0x%x\n", uldst, ulbytes, ulbytesSplitWriting);
            fnIosFlushTxQueue();
#endif

            // Initialise first bank
            Fapi_Init(flash_sector[bStartSector].bankNumber);
            //Write bytes in flash and wait for operation completion
            Status = (uint8) Fapi_issueProgrammingCommand((uint32 *)uldst, (uint8 *)ulsrc, (uint32)ulbytesSplitWriting, 0, 0, Fapi_AutoEccGeneration);
            while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
            while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);

            tFApiStatus = Fapi_doVerifyByByte((uint8*)uldst, ulbytesSplitWriting, (uint8*) ulsrc, &poFlashStatusWord);
            while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
            while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);

            if(Fapi_Status_Success != tFApiStatus)
            {
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
                wcu_printf("Verify failed at address : 0x%x - Data Read: 0x%x - RefData: 0x%x\n", poFlashStatusWord.au32StatusWord[0], poFlashStatusWord.au32StatusWord[1], poFlashStatusWord.au32StatusWord[2]);
#endif
                Status = 1;
                break;
                //while(1);
            }
            else
            {
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
                wcu_printf("Verify OK: %d\n", (tFApiStatus == Fapi_Status_Success));
#endif
            }

            // Update indexes
            ulsrc   += ulbytesSplitWriting;
            uldst   += ulbytesSplitWriting;
            ulLength  -= ulbytesSplitWriting;
            if (ulLength < FLASH_BANK_WIDTH_BYTES)
            {
                ulbytes = ulLength;
            }
            //number of bytes to be written in the first sector of the new bank
            ulbytesSplitWriting = ulbytes - ulbytesSplitWriting;

#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
            wcu_printf("Dest: 0x%x -Total length: 0x%x - Partial: 0x%x\n", uldst, ulbytes, ulbytesSplitWriting);
            fnIosFlushTxQueue();
#endif

            // Initialise second bank
            Fapi_Init(flash_sector[bEndSector].bankNumber);
            //Write bytes in flash and wait for operation completion
            Status = (uint8) Fapi_issueProgrammingCommand((uint32 *)uldst, (uint8 *)ulsrc, (uint32)ulbytesSplitWriting, 0, 0, Fapi_AutoEccGeneration);
            while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
            while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);

            tFApiStatus = Fapi_doVerifyByByte((uint8*)uldst, ulbytesSplitWriting, (uint8*) ulsrc, &poFlashStatusWord);
            while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
            while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);

            if(Fapi_Status_Success != tFApiStatus)
            {
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
                wcu_printf("Verify failed at address : 0x%x - Data Read: 0x%x - RefData: 0x%x\n", poFlashStatusWord.au32StatusWord[0], poFlashStatusWord.au32StatusWord[1], poFlashStatusWord.au32StatusWord[2]);
#endif
                Status = 1;
                break;
                //while(1);
            }
            else
            {
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
                wcu_printf("Verify OK: %d\n", (tFApiStatus == Fapi_Status_Success));
#endif
            }


            ulsrc   += ulbytesSplitWriting;
            uldst   += ulbytesSplitWriting;
            ulLength  -= ulbytesSplitWriting;
            if (ulLength < FLASH_BANK_WIDTH_BYTES)
            {
                ulbytes = ulLength;
            }
            //number of bytes to be written in the first sector of the new bank
            ulbytesSplitWriting = ulbytes - ulbytesSplitWriting;
        }
        else
        {
            // Initialise correct bank
            Fapi_Init(flash_sector[bStartSector].bankNumber);

            //Write bytes in flash and wait for operation completion
            Status = (uint8) Fapi_issueProgrammingCommand((uint32 *)uldst, (uint8 *)ulsrc, (uint32)ulbytes, 0, 0, Fapi_AutoEccGeneration);
            while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
            while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);

            tFApiStatus = Fapi_doVerifyByByte((uint8*)uldst, ulbytes, (uint8*) ulsrc, &poFlashStatusWord);
            while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
            while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);

            if(Fapi_Status_Success != tFApiStatus)
            {
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
                wcu_printf("Verify failed at address : 0x%x - Data Read: 0x%x - RefData: 0x%x\n", poFlashStatusWord.au32StatusWord[0], poFlashStatusWord.au32StatusWord[1], poFlashStatusWord.au32StatusWord[2]);
#endif
                Status = 1;
                break;
                //while(1);
            }
            else
            {
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
                wcu_printf("Verify OK: %d\n", (tFApiStatus == Fapi_Status_Success));
#endif
            }

            // Update indexes
            ulsrc   += ulbytes;
            uldst   += ulbytes;
            ulLength  -= ulbytes;
            if (ulLength < FLASH_BANK_WIDTH_BYTES)
            {
                ulbytes = ulLength;
            }
        }
#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
        wcu_printf("Dest: 0x%x -Data Length : 0x%x\n", uldst, ulLength);
        fnIosFlushTxQueue();
#endif

    }

#if defined(DEBUG_FLASH) &&  (DEBUG_FLASH == 1)
    fnIosFlushTxQueue();
#endif

    _coreEnableFlashEcc_();

    return (Status);
}


uint8 Fls_PgmFlashCompare(uint32 SourceAddress, const uint8* TargetAddressPtr, uint32 Length)
{
    register uint32* ulptrsrc1 = (uint32 *) TargetAddressPtr;
    register uint32* ulptrdst1 = (uint32 *) SourceAddress;
    register uint32 ulbytes = Length;

    while(ulbytes > 0)
    {
        if(*ulptrdst1++ != *ulptrsrc1++)
            return (1);   //error

        ulbytes -= 0x4;
    }
    return(0);
}


uint32_t Fls_PgmFlashRead( uint32 SourceAddress, uint8* TargetAddressPtr, uint32 Length)
{
    register uint32 ulsrc = (uint32)TargetAddressPtr;
    register uint32 uldst = SourceAddress;
    register uint32 ulbytes_remain = Length;
    uint32 ulbytes;

    if (Length < 16)
        ulbytes = Length;
    else
        ulbytes = 16;

    while( ulbytes_remain > 0)
    {
        Fapi_doMarginReadByByte((uint8 *)ulsrc,
                                (uint8 *)uldst,
                                (uint32) ulbytes,                //16
                                Fapi_NormalRead);
        ulsrc += ulbytes;
        uldst += ulbytes;
        ulbytes_remain -= ulbytes;
    }
    return (0);
}


void fnIosFlsJobSetRqst(FlashJobType FlashJobReq)
{
    g_tFlashMngrStatus.CurrentFlashJobReq = FlashJobReq;
}


FlashJobType fnIosFlsJobGetRqst(void)
{
    return(g_tFlashMngrStatus.CurrentFlashJobReq);
}


FlashJobStatusType fnIosFlsJobGetCurrentJobStatus(void)
{
    return(g_tFlashMngrStatus.CurrentFlashJobStatus);
}

void fnIosFlsJobResetCurrentJobStatus(void)
{
    g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobComplete;
}

void fnIosFlsJobRqstManager(void)
{
    uint8  i=0;
    uint32 ulstatus;
    static uint8  bSectorIndex=0, bBlanCheckCntr = 0;
    static uint32 ulEndAddr, ulTargetAddress, ulLength, ulEraseTimeout;
    static Fapi_FlashStatusWordType tFlashStatusWord;

    if(FlsJobComplete == g_tFlashMngrStatus.CurrentFlashJobStatus)
    {
        if(FlsJobReqNone != g_tFlashMngrStatus.CurrentFlashJobReq)
        {
            switch(g_tFlashMngrStatus.CurrentFlashJobReq)
            {
            case(FlsJobReqEraseCal):
                // Initialize operation for calibration section erase
                ulTargetAddress = Fbl_DataM_Cfg_CalibRegions[0]->dataRequestDownloadMemoryRangeLow_u32; //FBL_DATAM_CALIBRATION_REGION_0_START_ADDRESS;
                //ulLength = FBL_DATAM_LOGICAL_BLOCK_CAL_SIZE-1;
                ulLength = Fbl_DataM_Cfg_CalibRegions[0]->dataRequestDownloadMemoryRangeHigh_u32 -
                Fbl_DataM_Cfg_CalibRegions[0]->dataRequestDownloadMemoryRangeLow_u32 + 1;
                //ulEndAddr = ulTargetAddress + ulLength;
                ulEndAddr = Fbl_DataM_Cfg_CalibRegions[0]->dataRequestDownloadMemoryRangeHigh_u32;
                g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobInit;
                wcu_printf("Start erase cal region\n");
            break;

            case(FlsJobReqEraseApp):
                // Initialize operation for application section erase
                ulTargetAddress = Fbl_DataM_Cfg_AppRegions[0]->dataRequestDownloadMemoryRangeLow_u32; // FBL_DATAM_APPLICATION_REGION_0_START_ADDRESS;
                //ulLength = FBL_DATAM_LOGICAL_BLOCK_APP_SIZE-1;
                ulLength = Fbl_DataM_Cfg_AppRegions[0]->dataRequestDownloadMemoryRangeHigh_u32 -
                Fbl_DataM_Cfg_AppRegions[0]->dataRequestDownloadMemoryRangeLow_u32 + 1;
                //ulEndAddr = ulTargetAddress + ulLength;
                ulEndAddr = Fbl_DataM_Cfg_AppRegions[0]->dataRequestDownloadMemoryRangeHigh_u32;
                g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobInit;
                wcu_printf("Start erase App region\n");
            break;

            case(FlsJobReqEraseAppAndCal):
                // Initialize operation for application section erase
                ulTargetAddress = Fbl_DataM_Cfg_AppAndCalibRegions[0]->dataRequestDownloadMemoryRangeLow_u32; // FBL_DATAM_APPLICATION_REGION_0_START_ADDRESS;
                //ulLength = FBL_DATAM_LOGICAL_BLOCK_APP_SIZE-1;
                ulLength = Fbl_DataM_Cfg_AppAndCalibRegions[0]->dataRequestDownloadMemoryRangeHigh_u32 -
                Fbl_DataM_Cfg_AppAndCalibRegions[0]->dataRequestDownloadMemoryRangeLow_u32 + 1;
                //ulEndAddr = ulTargetAddress + ulLength;
                ulEndAddr = Fbl_DataM_Cfg_AppAndCalibRegions[0]->dataRequestDownloadMemoryRangeHigh_u32;
                g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobInit;
                wcu_printf("Start erase App+Cal region\n");
            break;

            case(FlsJobReqProgram):
                g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobComplete;
                g_tFlashMngrStatus.CurrentFlashJobReq = FlsJobReqNone;
            break;

            default:
                break;
            }
        }
        else
        {
            // do nothing - Wait for previous request to be completed
        }
    }
    else
    {
        switch(g_tFlashMngrStatus.CurrentFlashJobStatus)
        {
        case(FlsJobInit):
            // Initialize job by finding which sectors to erase
            for (i = 0; i < NUMBEROFSECTORS; i++)
            {
                if (ulTargetAddress < (uint32)(flash_sector[i].start))
                {
                    g_bStartBank  = flash_sector[i-1].bankNumber;
                    g_bStartSector   = i-1;
                    break;
                }
            }

            for (i = g_bStartSector; i < NUMBEROFSECTORS; i++)
            {
                if (ulEndAddr <= (((uint32)flash_sector[i].start) + flash_sector[i].length))
                {
                    g_bEndBank   = flash_sector[i].bankNumber;
                    g_bEndSector = i;
                    break;
                }
            }
            bSectorIndex=g_bStartSector;
            bBlanCheckCntr = 0;
            g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobEraseSectorStart;

        break;

        case(FlsJobEraseSectorStart):
            ulstatus = Fapi_Init(flash_sector[bSectorIndex].bankNumber);
            if(!ulstatus)
            {
                if(bSectorIndex<(g_bEndSector+1))
                {
                    //#if defined(DEBUG_FLS)
                    wcu_printf("Erase sector %d - address 0x%x\n", bSectorIndex, flash_sector[bSectorIndex].start);
                    //#endif
                    // reset erase timeout
                    ulEraseTimeout = 0;
                    // Trigger Erase command
                    Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, flash_sector[bSectorIndex].start);
                    while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady )
                    {
                        if(ulEraseTimeout >= FLASH_ERASE_TIMEOUT )
                        {
                            break;
                        }
                        else
                        {
                            ulEraseTimeout++;
                        }
                    }

                    // Go to check erase result
                    Fapi_flushPipeline();
                    g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobCheckEraseRslt;

                }
                else // erase sequence complete
                {
                    wcu_printf("Erase Complete\n");
                    g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobComplete;
                    g_tFlashMngrStatus.CurrentFlashJobReq = FlsJobReqNone;
                }
            }
            else
            {
                g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobFailed;
            }
            break;

        case(FlsJobCheckEraseRslt):
            //wcu_printf("Rdy-Bsy : 0x%x - Stat: 0x%x - timeou: %d \n", FAPI_CHECK_FSM_READY_BUSY, FAPI_GET_FSM_STATUS, ulEraseTimeout);

            if( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady )
            {

                if((FAPI_GET_FSM_STATUS == Fapi_Status_Success) && (ulEraseTimeout <= FLASH_ERASE_TIMEOUT))
                {
                    // Go back to start erase
                    g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobEraseBlanckCheck;
                }
                else
                {
                    if((FAPI_GET_FSM_STATUS & 0x4010) != 0 )
                    {
                        wcu_printf("Erase sector %d failed - Fls Ctlr Error.\n",bSectorIndex);
                        g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobFailed;
                    }
                    else if(ulEraseTimeout > FLASH_ERASE_TIMEOUT)
                    {
                        wcu_printf("Erase sector %d failed - Timeout\n",bSectorIndex);
                        g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobFailed;
                    }
                    else
                    {
                        // should not go here
                    }
                }
            }
            else
            {
                g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobFailed;
            }
            break;

        case(FlsJobEraseBlanckCheck):
            //ulstatus =  Fls_PgmFlashEraseCheck((uint32)ulTargetAddress, ulLength);
#if defined(DEBUG_FLS)
            wcu_printf("Blank check sector: %d - start 0x%x - length: 0x%x\n", bSectorIndex, flash_sector[bSectorIndex].start, flash_sector[bSectorIndex].length);
#endif
            _coreDisableFlashEcc_();

            //!!! flash_sector[bSectorIndex].length is in byte but Fapi_doBlankCheck takes 32bits words !!!!
            // flash_sector[bSectorIndex].length must be divided by 4
            ulstatus = Fapi_doBlankCheck(flash_sector[bSectorIndex].start, (flash_sector[bSectorIndex].length>>2), &tFlashStatusWord);

            _coreEnableFlashEcc_();

#if defined(DEBUG_FLS)
        if(Fapi_Status_Success == ulstatus)
            wcu_printf("Blank check sector: %d - Ok!\n", bSectorIndex);
        else
            wcu_printf("Blank check sector: %d - %d - Failed - @0x%x - Val: 0x%x\n", bSectorIndex, ulstatus, tFlashStatusWord.au32StatusWord[0],  tFlashStatusWord.au32StatusWord[1]);
#endif
            if(Fapi_Status_Success == ulstatus)
            {
                // increment to next sector to erase
                bSectorIndex++;
                bBlanCheckCntr = 0;
                g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobEraseSectorStart;
            }
            else
            {
                if(bBlanCheckCntr < NUM_FAILED_BLANK_CHECK_ALLOWED)
                {
                    // Go back to try to erase the sector
                    wcu_printf("Blank check failed sector: %d - @: 0x%x - Val: 0x%x\n", bSectorIndex, tFlashStatusWord.au32StatusWord[0],  tFlashStatusWord.au32StatusWord[1]);
                    wcu_printf("Retrying erase\n");
                    bBlanCheckCntr++;
                    g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobEraseSectorStart;
                }
                else
                {
                    wcu_printf("Blank check failed sector: %d - @: 0x%x - Val: 0x%x\n", bSectorIndex, tFlashStatusWord.au32StatusWord[0],  tFlashStatusWord.au32StatusWord[1]);
                    bBlanCheckCntr = 0;
                    g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobFailed;
                    g_tFlashMngrStatus.CurrentFlashJobReq = FlsJobReqNone;
                }
            }
            break;

        case(FlsJobFailed):
            g_tFlashMngrStatus.CurrentFlashJobStatus = FlsJobFailed;
            g_tFlashMngrStatus.CurrentFlashJobReq = FlsJobReqNone;
            break;

        default:
            break;
        }

    }

}

//void fnIosTestFlashJobs(const uint8* bDataToProgram, uint32 ulDataToProgramLengthBytes)
//{
//
//    switch(g_tTestFlashJob)
//    {
//    case FlsJobNone:
//        break;
//
//    case FlsJobErase:
//        Fls_Erase(APP_START_ADDRESS, 0x1000);
//        g_tTestFlashJob = FlsJobNone;
//        break;
//
//    case FlsJobProgram:
//        Fls_Write(APP_START_ADDRESS, bDataToProgram, ulDataToProgramLengthBytes);
//        Fls_Compare(APP_START_ADDRESS, bDataToProgram, ulDataToProgramLengthBytes);
//        g_tTestFlashJob = FlsJobNone;
//        break;
//
//    default:
//        g_tTestFlashJob = FlsJobNone;
//        break;
//    }
//}
