/******************************************************************************
 * $Revision: 423 $
 * $Date:: 2017-04-07 16:03:30 +0900#$
 *****************************************************************************/
/* __DISCLAIMER_START__                                                      */
/******************************************************************************
* (c)2017, Cypress Semiconductor Corporation
* or a subsidiary of Cypress Semiconductor Corporation. All rights
* reserved.
*
* This software, including source code, documentation and related
* materials ( "Software" ), is owned by Cypress Semiconductor
* Corporation or one of its subsidiaries ( "Cypress" ) and is protected by
* and subject to worldwide patent protection (United States and foreign),
* United States copyright laws and international treaty provisions.
* Therefore, you may use this Software only as provided in the license
* agreement accompanying the software package from which you
* obtained this Software ( "EULA" ).
*
* If no EULA applies, Cypress hereby grants you a personal, nonexclusive,
* non-transferable license to copy, modify, and compile the
* Software source code solely for use in connection with Cypress' s
* integrated circuit products. Any reproduction, modification, translation,
* compilation, or representation of this Software except as specified
* above is prohibited without the express written permission of Cypress.
*
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. Cypress reserves the right to make
* changes to the Software without notice. Cypress does not assume any
* liability arising out of the application or use of the Software or any
* product or circuit described in the Software. Cypress does not
* authorize its products for use in any products where a malfunction or
* failure of the Cypress product may reasonably be expected to result in
* significant property damage, injury or death ( "High Risk Product" ). By
* including Cypress' s product in a High Risk Product, the manufacturer
* of such system or application assumes all risk of such use and in doing
* so agrees to indemnify Cypress against all liability.
******************************************************************************/
/* __DISCLAIMER_END__                                                        */
/*****************************************************************************
 ** \file workflash.c
 **
 ** A detailed description is available at
 ** @link WorkFlashGroup Work FLash functions description @endlink
 **
 ** History:
 **   - 2014-06-02  0.01  HS  Initial version for Traveo
 **   - 2014-06-27  0.02  HS  Fix bug in WFLASH_MAXIMUM_SECTOR_NUM
 *****************************************************************************/


/*****************************************************************************/
/* Include files                                                             */
/*****************************************************************************/
#include "workflash.h"

/**
 *****************************************************************************
 ** \addtogroup WorkFlashGroup Work FLash functions (WFlash)
 **
 *****************************************************************************/
/*!@{ */


/*****************************************************************************/
/* Local pre-processor symbols/macros ('define')                             */
/*****************************************************************************/
/*! Base address of Work Flash */
#define WFLASH_BASE_ADDRESS         (MCU_WORKFLASH_BASE_ADDRESS)

/*! Number of bytes in Work Flash  */
#define WFLASH_BYTE_SIZE            (MCU_WORKFLASH_SIZE_BYTE)

/*! Mirror area offset address from work flash base address. */
#define WFLASH_MIRROR_AREA1_OFFSET  (0x00000000)
#define WFLASH_MIRROR_AREA3_OFFSET  (0x00200000)

#define WFLASH_SECTOR_SIZE          (1024u * 4u)    /*! Size of each sector */
#define WFLASH_MAXIMUM_SECTOR_NUM   (WFLASH_BYTE_SIZE / WFLASH_SECTOR_SIZE - 1)
                                                    /*! Maximum Sector Number(0-NUM) */
#define WFLASH_UNLOCK_KEY           (0xCF6DF1A5)    /*! Unlock key code */

/*! Flash Sequencer commands */
#define WFLASH_COMMAND_READ_RESET   (1u)
#define WFLASH_COMMAND_ERASE        (2u)

/*****************************************************************************/
/* Global variable definitions (declared in header file with 'extern')       */
/*****************************************************************************/

/*****************************************************************************/
/* Local type definitions ('typedef')                                        */
/*****************************************************************************/

/*****************************************************************************/
/* Local variable definitions ('static')                                     */
/*****************************************************************************/

/*****************************************************************************/
/* Local function prototypes ('static')                                      */
/*****************************************************************************/
static void WFlash_Unlock(void);
static en_result_t WFlashVerifyAddress(uint8_t u8SizeByte, uint32_t u32OffsetAddress);
static en_result_t WFlashWaitUntilRdy(void);
static boolean_t WFlashCanBeWritten(void);

/*****************************************************************************/
/* Function implementation - global ('extern') and local ('static')          */
/*****************************************************************************/

/**
 *****************************************************************************
 ** \brief Unlocks the Work Flash configuration registers for one write access.
 **
 ** \return None
 *****************************************************************************/
static void WFlash_Unlock()
{
    WFCFG_CPR = WFLASH_UNLOCK_KEY;
}

/**
 *****************************************************************************
 ** \brief Check if Work Flash can be written.
 **
 ** \retval TRUE  Work Flash macro is ready to write.
 ** \retval FALSE Work Flash macro is not ready to write.
 *****************************************************************************/
static boolean_t WFlashCanBeWritten(void)
{
    boolean_t bCanBeWritten = TRUE;
    en_wflash_status_t enStatus;

    /* Write enable? */
    if (WFCFG_CR_WE == 0)
    {
        bCanBeWritten = FALSE;
    }
    else
    {
        /* Check if flash status is ready */
        enStatus = WFlash_GetStatus();
        if (enStatus != WFlashReady)
        {
            bCanBeWritten = FALSE;
        }
    }

    return bCanBeWritten;
}


/**
 *****************************************************************************
 ** \brief Wait until Work Flash macro is ready for new commands
 ** 
 ** \retval Ok    Work Flash macro is ready to accept new commands.
 ** \retval Error Work Flash macro is hanging.
 **               If hanging, this function issue read/reset command to
 **               clear hanging status.
 *****************************************************************************/
static en_result_t WFlashWaitUntilRdy(void)
{
    en_result_t enResult = Ok;
    en_wflash_status_t enStatus;
	uint32_t i = 0;

    /* wait until ready or hang */
    do{
		i++;
        enStatus = WFlash_GetStatus();
        /* Call user hook */
        //PDL_WAIT_LOOP_HOOK();
    }while ((enStatus == WFlashNotReady) && (i < 50000000));

    /* Check if flash macro is hanging */
    if ((enStatus == WFlashHang) || (enStatus == WFlashNotReady))
    {
        /* Issue read/reset command */
        (void)WFlash_ReadResetCmd();
        enResult = Error;
    }

    return enResult;
}


/**
 *****************************************************************************
 ** \brief Check if destination address is valid.
 **
 ** \param  u8SizeByte              Data size of byte to write
 ** \param  u32OffsetAddress        Offset address from Work Flash base address
 **
 ** \retval Ok                      Destination address is valid.
 ** \retval ErrorInvalidParameter   Destination address is over Work Flash memory space.
 ** \retval ErrorAddressAlignment   Destination address alignment is not match data size to write.
 *****************************************************************************/
static en_result_t WFlashVerifyAddress(uint8_t u8SizeByte, uint32_t u32OffsetAddress)
{
    en_result_t enResult;

    if ((u32OffsetAddress + u8SizeByte) > WFLASH_BYTE_SIZE)
    {
        /* Check if address is in the workflash area */
        enResult = ErrorInvalidParameter;
    }
    else if ((u32OffsetAddress & (uint32_t)(u8SizeByte - 1u)) != 0)
    {
        /* Check if address alignment is valid */
        enResult =  ErrorAddressAlignment;
    }
    else
    {
        enResult = Ok;
    }

    return enResult;
}

/**
 *****************************************************************************
 ** \brief Issue read/reset command
 **
 ** \retval ErrorInvalidMode    If following conditions are met:
 **                                 - Write access is disabled.
 **                                 - Flash erasing has been suspended.
 ** \retval Ok                  successfully done.
 *****************************************************************************/
en_result_t WFlash_ReadResetCmd(void)
{
    en_wflash_status_t enStatus;

    /* ---- Parameter and Condition Check ---- */
    /* Write enable? */
    if (WFCFG_CR_WE == 0)
    {
        return ErrorInvalidMode;
    }

    /* Check erase suspend status  */
    /* read/reset command can not be issued when erase has been suspended. */
    if (WFCFG_SR_ESPS != 0)
    {
        return ErrorInvalidMode;
    }

    /* ---- Do operations ---- */
    /* Write read/reset command. */
    /* Read modify write not to change ERS bit */
    WFCFG_SEQCM_OPC = WFLASH_COMMAND_READ_RESET;

    /* Wait until ready */
    do{
        /* read/reset command will complete in about 10 FCLK cycle or so. */
        /* Therefore no WDG handling required. */
        enStatus = WFlash_GetStatus();
    }while (enStatus != WFlashReady);

    /* Clear hangup status bit */
    WFCFG_ICR_HANGIC = 1;

    return Ok;
}

/**
 *****************************************************************************
 ** \brief Get status of the Work Flash memory
 **
 ** \retval WFlashReady         Ready
 ** \retval WFlashNotReady      Operation on going
 ** \retval WFlashHang          Operation has failed
 *****************************************************************************/
en_wflash_status_t WFlash_GetStatus(void)
{
    en_wflash_status_t enStatus;
    un_wfcfg_sr_t unSR = { 0 };

    /* Read status register */
    unSR.u32Register = WFCFG_SR;

    /* Determine flash status */
    if (unSR.stcField.u1RDY != 0)
    {
        /* Ready */
        enStatus = WFlashReady;
    }
    else if (unSR.stcField.u1HANGINT != 0)
    {
        /* Operation has failed */
        enStatus = WFlashHang;
    }
    else
    {
        /* Operation on going */
        enStatus = WFlashNotReady;
    }

    return enStatus;
}

/**
 *****************************************************************************
 ** \brief Reset the Flash memory and the command sequencer.
 **
 ** \pre Must be run from privileged mode and after WFlash_EnableWriteAccess().
 ** 
 ** \retval Ok                  Reset successfully done.
 ** \retval ErrorAccessRights   Call of function was not done in privileged mode.
 **         ErrorInvalidMode    Call of function was done before enabling
 **                             the write access.
 *****************************************************************************/
en_result_t WFlash_Reset(void)
{
    en_wflash_status_t enStatus;

    /* ---- Parameter and Condition Check ---- */
    /* Check CPU mode. */
    if (FALSE == Cpu_CpuIsInPrivilegedMode())
    {
        return ErrorAccessRights;
    }

    /* Check if the write is enabled */
    if (WFCFG_CR_WE == 0)
    {
        return ErrorInvalidMode;
    }

    /* ---- Do operations ---- */
    /* Disable IRQ for protected sequence */
    IRQ_DISABLE_LOCAL();

    /* Write unlock before each write access to configuration register. */
    WFlash_Unlock();
    /* Software reset */
    WFCFG_CR_SWFRST = 1;

    /* Restore IRQ state */
    IRQ_RESTORE();

    /* Wait until ready */
    do{
        /* Software reset will complete in about 90 FCLK cycle or so. */
        /* Therefore no WDG handling required. */
        enStatus = WFlash_GetStatus();
    }while (enStatus != WFlashReady);

    /* Clear hangup status bit */
    WFCFG_ICR_HANGIC = 1;

    return Ok;
}

/**
 *****************************************************************************
 ** \brief Enables write access to WorkFlash.
 **
 ** \pre Must be run from privileged mode.
 ** 
 ** \retval Ok                  Write access enabled.
 ** \retval ErrorAccessRights   Call of function was not done in privileged mode. 
 ** \retval ErrorInvalidMode    Can not get write permission.
 *****************************************************************************/
en_result_t WFlash_EnableWriteAccess(void)
{
    en_result_t enResult = Ok;

    /* ---- Parameter and Condition Check ---- */
    /* Check CPU mode. */
    if (FALSE == Cpu_CpuIsInPrivilegedMode()) 
    {
        enResult = ErrorAccessRights;
    }else
    {
        /* ---- Do operations ---- */
        /* Disable IRQ */
        IRQ_DISABLE_LOCAL();

        /* Check if can get the write permission */
        if (WFCFG_WARBR_WERSTS != 1)
        {
            enResult = ErrorInvalidMode;
        }
        else
        {
            /* Write unlock before each write access to configuration register. */
            WFlash_Unlock();
            /* Work Flash write enable */
            WFCFG_CR_WE = 1;
        }

        /* Restore IRQ state */
        IRQ_RESTORE();
    }

    return enResult;
}


/**
 *****************************************************************************
 ** \brief Disables write access to WorkFlash.
 **
 ** \pre Must be run from privileged mode.
 ** 
 ** \retval Ok                Write access disabled.
 ** \retval ErrorAccessRights Call of function was not done in privileged mode. 
 *****************************************************************************/
en_result_t WFlash_DisableWriteAccess(void)
{
    en_result_t enResult = Ok;

    /* ---- Parameter and Condition Check ---- */
    /* Check CPU mode. */
    if (FALSE == Cpu_CpuIsInPrivilegedMode()) 
    {
        enResult = ErrorAccessRights;
    }
    else
    {
        /* ---- Do operations ---- */
        /* Disable IRQ for protected sequence */
        IRQ_DISABLE_LOCAL();

        /* Write unlock before each write access to configuration register. */
        WFlash_Unlock();
        /* Work Flash write disable. */
        WFCFG_CR_WE = 0;

        /* Restore IRQ state */
        IRQ_RESTORE();
    }

    return enResult;
}


/**
 *****************************************************************************
 ** \brief Write 8bit data to WorkFlash
 **
 ** \pre Must be run in ready state and after write access is enabled.
 **
 ** \param u32OffsetAddress [in]    Offset address from Work Flash base address.
 ** \param u8Data       [in]        Data to write.
 ** \param enMirrorArea [in]        Mirror area to be written.
 **                                 see description of #en_wflash_mirror_area_t
 ** \param  bBlocking   [in]        If TRUE, synchronously wait until
 **                                 operation completed.
 **                                 If FALSE, return immediately.
 **
 ** \retval ErrorInvalidParameter   Destination address is over Work Flash memory space.
 ** \retval ErrorAddressAlignment   Destination address alignment is not match data size to write.
 ** \retval ErrorInvalidMode        If following conditions are met:
 **                                    - Write access is disabled.
 **                                    - Flash status is not ready.
 ** \retval Error                   Flash macro is hanging.
 **                                 (read/reset command was already issued and
 **                                  already restored to ready state.)
 ** \retval Ok                      Successfully done.
 *****************************************************************************/
en_result_t WFlash_Write8(uint32_t u32OffsetAddress,
                          uint8_t u8Data,
                          en_wflash_mirror_area_t enMirrorArea,
                          boolean_t bBlocking)
{
    boolean_t           bCanBeWritten;
    en_result_t         enResult;
    volatile uint8_t*   pu8DestinationAddress;
    uint32_t            u32MirrorOffset = 0;

    /* ---- Parameter and Condition Check ---- */
    /* Work Flash is ready and write enable? */
    bCanBeWritten = WFlashCanBeWritten();
    if (bCanBeWritten == FALSE)
    {
        return ErrorInvalidMode;
    }

    /* Check if destination address is valid */
    enResult = WFlashVerifyAddress(sizeof(uint8_t), u32OffsetAddress);
    if (enResult != Ok)
    {
        return enResult;
    }

    /* Calc mirror area offset address */
    if (enMirrorArea == WFlashMirror1)
    {
        u32MirrorOffset = WFLASH_MIRROR_AREA1_OFFSET;
    }
    else if (enMirrorArea == WFlashMirror3)
    {
        u32MirrorOffset = WFLASH_MIRROR_AREA3_OFFSET;
    }
    else
    {
        return ErrorInvalidParameter;   /* should never see the daylight */
    }

    /* ---- Do operations ---- */
    /* Calc destination address */
    pu8DestinationAddress =
            (volatile uint8_t*)(WFLASH_BASE_ADDRESS + u32MirrorOffset + u32OffsetAddress);

    /* write data */
    *pu8DestinationAddress = u8Data;

    if (bBlocking != FALSE)
    {
        /* wait until ready */
        enResult = WFlashWaitUntilRdy();
    }
    else
    {
        /* Do not wait */
        enResult = Ok;
    }

    return enResult;
}

/**
 *****************************************************************************
 ** \brief Write 16bit data to WorkFlash
 **
 ** \pre Must be run in ready state and after write access is enabled.
 **
 ** \param u32OffsetAddress [in]    Offset address from Work Flash base address.
 ** \param u16Data      [in]        Data to write.
 ** \param enMirrorArea [in]        Mirror area to be written.
 **                                 see description of #en_wflash_mirror_area_t
 ** \param  bBlocking   [in]        If TRUE, synchronously wait until
 **                                 operation completed.
 **                                 If FALSE, return immediately.
 **
 ** \retval ErrorInvalidParameter   Destination address is over Work Flash memory space.
 ** \retval ErrorAddressAlignment   Destination address alignment is not match data size to write.
 ** \retval ErrorInvalidMode        If following conditions are met:
 **                                    - Write access is disabled.
 **                                    - Flash status is not ready.
 ** \retval Error                   Flash macro is hanging.
 **                                 (read/reset command was already issued and
 **                                  already restored to ready state.)
 ** \retval Ok                      Successfully done.
 *****************************************************************************/
en_result_t WFlash_Write16(uint32_t u32OffsetAddress,
                           uint16_t u16Data,
                           en_wflash_mirror_area_t enMirrorArea,
                           boolean_t bBlocking)
{
    boolean_t           bCanBeWritten;
    en_result_t         enResult;
    volatile uint16_t*  pu16DestinationAddress;
    uint32_t            u32MirrorOffset = 0;

    /* ---- Parameter and Condition Check ---- */
    /* Work Flash is ready and write enable? */
    bCanBeWritten = WFlashCanBeWritten();
    if (bCanBeWritten == FALSE)
    {
        return ErrorInvalidMode;
    }

    /* Check if destination address is valid */
    enResult = WFlashVerifyAddress(sizeof(uint16_t), u32OffsetAddress);
    if (enResult != Ok)
    {
        return enResult;
    }

    /* Calc mirror area offset address */
    if (enMirrorArea == WFlashMirror1)
    {
        u32MirrorOffset = WFLASH_MIRROR_AREA1_OFFSET;
    }
    else if (enMirrorArea == WFlashMirror3)
    {
        u32MirrorOffset = WFLASH_MIRROR_AREA3_OFFSET;
    }
    else
    {
        return ErrorInvalidParameter;   /* should never see the daylight */
    }

    /* ---- Do operations ---- */
    /* Calc destination address */
    pu16DestinationAddress =
            (volatile uint16_t*)(WFLASH_BASE_ADDRESS + u32MirrorOffset + u32OffsetAddress);

    /* write data */
    *pu16DestinationAddress = u16Data;

    if (bBlocking != FALSE)
    {
        /* wait until ready */
        enResult = WFlashWaitUntilRdy();
    }
    else
    {
        /* Do not wait */
        enResult = Ok;
    }

    return enResult;
}

/**
 *****************************************************************************
 ** \brief Write 32bit data to WorkFlash
 **
 ** \pre Must be run in ready state and after write access is enabled.
 **
 ** \param u32OffsetAddress [in]    Offset address from Work Flash base address.
 ** \param u32Data      [in]        Data to write.
 ** \param enMirrorArea [in]        Mirror area to be written.
 **                                 see description of #en_wflash_mirror_area_t
 ** \param  bBlocking   [in]        If TRUE, synchronously wait until
 **                                 operation completed.
 **                                 If FALSE, return immediately.
 **
 ** \retval ErrorInvalidParameter   Destination address is over Work Flash memory space.
 ** \retval ErrorAddressAlignment   Destination address alignment is not match data size to write.
 ** \retval ErrorInvalidMode        If following conditions are met:
 **                                    - Write access is disabled.
 **                                    - Flash status is not ready.
 ** \retval Error                   Flash macro is hanging.
 **                                 (read/reset command was already issued and
 **                                  already restored to ready state.)
 ** \retval Ok                      Successfully done.
 *****************************************************************************/
en_result_t WFlash_Write32(uint32_t u32OffsetAddress,
                           uint32_t u32Data,
                           en_wflash_mirror_area_t enMirrorArea,
                           boolean_t bBlocking)
{
    boolean_t           bCanBeWritten;
    en_result_t         enResult;
    volatile uint32_t*  pu32DestinationAddress;
    uint32_t            u32MirrorOffset = 0;

    /* ---- Parameter and Condition Check ---- */
    /* Work Flash is ready and write enable? */
    bCanBeWritten = WFlashCanBeWritten();
    if (bCanBeWritten == FALSE)
    {
        return ErrorInvalidMode;
    }

    /* Check if destination address is valid */
    enResult = WFlashVerifyAddress(sizeof(uint32_t), u32OffsetAddress);
    if (enResult != Ok)
    {
        return enResult;
    }

    /* Calc mirror area offset address */
    if (enMirrorArea == WFlashMirror1)
    {
        u32MirrorOffset = WFLASH_MIRROR_AREA1_OFFSET;
    }
    else if (enMirrorArea == WFlashMirror3)
    {
        u32MirrorOffset = WFLASH_MIRROR_AREA3_OFFSET;
    }
    else
    {
        return ErrorInvalidParameter;   /* should never see the daylight */
    }

    /* ---- Do operations ---- */
    /* Calc destination address */
    pu32DestinationAddress =
            (volatile uint32_t*)(WFLASH_BASE_ADDRESS + u32MirrorOffset + u32OffsetAddress);

    /* write data */
    *pu32DestinationAddress = u32Data;

    if (bBlocking != FALSE)
    {
        /* wait until ready */
        enResult = WFlashWaitUntilRdy();
    }
    else
    {
        /* Do not wait */
        enResult = Ok;
    }

    return enResult;
}


/* \todo
 * Currently can not force 64bit access with GHS compiler.
 * Hence the function to write with 64bit access can not be used.
 */
#if 0
/**
 *****************************************************************************
 ** \brief Write 64bit data to WorkFlash
 **
 ** \pre Must be run in ready state and after write access is enabled.
 **
 ** \param u32OffsetAddress [in]    Offset address from Work Flash base address.
 ** \param u64Data      [in]        Data to write.
 ** \param enMirrorArea [in]        Mirror area to be written.
 **                                 see description of #en_wflash_mirror_area_t
 ** \param  bBlocking   [in]        If TRUE, synchronously wait until
 **                                 operation completed.
 **                                 If FALSE, return immediately.
 **
 ** \retval ErrorInvalidParameter   Destination address is over Work Flash memory space.
 ** \retval ErrorAddressAlignment   Destination address alignment is not match data size to write.
 ** \retval ErrorInvalidMode        If following conditions are met:
 **                                    - Write access is disabled.
 **                                    - Flash status is not ready.
 ** \retval Error                   Flash macro is hanging.
 **                                 (read/reset command was already issued and
 **                                  already restored to ready state.)
 ** \retval Ok                      Successfully done.
 *****************************************************************************/
en_result_t WFlash_Write64(uint32_t u32OffsetAddress,
                           uint64_t u64Data,
                           en_wflash_mirror_area_t enMirrorArea,
                           booleant_t bBlocking)
{
    boolean_t           bCanBeWritten;
    en_result_t         enResult;
    volatile uint64_t * pu64DestinationAddress;
    uint32_t            u32MirrorOffset = 0;

    /* ---- Parameter and Condition Check ---- */
    /* Work Flash is ready and write enable? */
    bCanBeWritten = WFlashCanBeWritten();
    if (bCanBeWritten == FALSE)
    {
        return ErrorInvalidMode;
    }

    /* Check if destination address is valid */
    enResult = WFlashVerifyAddress(sizeof(uint64_t), u32OffsetAddress);
    if (enResult != Ok)
    {
        return enResult;
    }

    /* Calc mirror area offset address */
    if (enMirrorArea == WFlashMirror1)
    {
        u32MirrorOffset = WFLASH_MIRROR_AREA1_OFFSET;
    }
    else if (enMirrorArea == WFlashMirror3)
    {
        u32MirrorOffset = WFLASH_MIRROR_AREA3_OFFSET;
    }
    else
    {
        return ErrorInvalidParameter;   /* should never see the daylight */
    }

    /* ---- Do operations ---- */
    /* Calc destination address */
    pu64DestinationAddress =
            (volatile uint64_t*)(WFLASH_BASE_ADDRESS + u32MirrorOffset + u32OffsetAddress);

    /* write data */
    *pu64DestinationAddress = u64Data;

    if (bBlocking != FALSE)
    {
        /* wait until ready */
        enResult = WFlashWaitUntilRdy();
    }
    else
    {
        /* Do not wait */
        enResult = Ok;
    }

    return enResult;
}
#endif

/**
 *****************************************************************************
 ** \brief Erase a sector
 **
 ** \pre Must be run in ready state and after write access is enabled.
 **
 ** \param  u8SectorNum [in]        Sector number to erase.
 ** \param  bBlocking   [in]        If TRUE, synchronously wait until
 **                                 operation completed.
 **                                 If FALSE, return immediately.
 **
 ** \retval ErrorInvalidMode        If following conditions are met:
 **                                 - Write access is disabled.
 **                                 - Flash macro has hanged.
 **                                 - Flash macro operation is on going.
 ** \retval ErrorInvalidParameter   u8SectorNum is over maximum sector number.
 ** \retval Ok                      Erase is successfully done.
 *****************************************************************************/
en_result_t WFlash_Erase(uint8_t u8SectorNum, boolean_t bBlocking)
{
    boolean_t           bCanBeWritten;
    en_result_t         enResult;
    un_wfcfg_seqcm_t    unSEQCM = { 0 };

    /* ---- Parameter and Condition Check ---- */
    /* Work Flash is ready and write enable? */
    bCanBeWritten = WFlashCanBeWritten();
    if (bCanBeWritten == FALSE)
    {
        return ErrorInvalidMode;
    }

    /* Sector number is valid? */
    if (u8SectorNum > WFLASH_MAXIMUM_SECTOR_NUM)
    {
        return ErrorInvalidParameter;
    }

    /* ---- Do operations ---- */
    /* Write erase command. */
    unSEQCM.stcField.u4OPC = WFLASH_COMMAND_ERASE;
    unSEQCM.stcField.u8ERS = u8SectorNum;
    WFCFG_SEQCM = unSEQCM.u32Register;

    if (bBlocking != FALSE)
    {
        /* wait until ready */
        enResult = WFlashWaitUntilRdy();
    }
    else
    {
        /* Do not wait */
        enResult = Ok;
    }

    return enResult;
}

/*! @} */

/*****************************************************************************/
/* EOF (not truncated)                                                       */
/*****************************************************************************/
