#include "stddef.h"
#include "string.h"
#include "r_typedefs.h"
#include "dr7f701401.dvf.h"
#include "r_dev_api.h"
#include "Internal_Flash.h"
#include "rh850_macros.h"
typedef enum
{
    INT_DATA_FLASH_READ = 0U,
    INT_DATA_FLASH_WRITE,
    INT_DATA_FLASH_ERASE,
} Int_Data_Flash_Mode_en_t;

typedef struct
{
    Int_Data_Flash_Mode_en_t enMode;
    uint8_t                  u8Error;
    uint16_t                 u16Ptr;
    uint32_t                 u32Addr;
    uint32_t                 u32DstAddr;
    Int_Flash_Cb_Func_t      pfnCompleteCb;
} Int_Data_Flash_Ctrl_st_t;

typedef struct
{
    uint16_t u16Word [ 128 ];
} Int_Code_Flash_Buffer_st_t;

#define INT_FLASH_FACI_CMD_ISSUE(c) (*(( volatile uint8_t * )0xFFA20000UL) = (c))
#define INT_FLASH_FACI_DAT_ISSUE(c) (*(( volatile uint16_t * )0xFFA20000UL) = (c))
#define INT_FLASH_FACI_CMD_READ( )  (*(( volatile uint8_t * )0xFFA20000UL))

#define INT_FLASH_CMD_PROG          (0xE8U)
#define INT_FLASH_CMD_DMA_PROG      (0xEAU)
#define INT_FLASH_CMD_ERASE         (0x20U)
#define INT_FLASH_CMD_SUSPEND       (0xB0U)
#define INT_FLASH_CMD_RESUME        (0xD0U)
#define INT_FLASH_CMD_STAT_CLR      (0x50U)
#define INT_FLASH_CMD_STOP          (0xB3U)
#define INT_FLASH_CMD_BLANK_CHK     (0x71U)
#define INT_FLASH_CMD_CFG_PROG      (0x40U)
#define INT_FLASH_CMD_LOCK_BIT_PROG (0x77U)
#define INT_FLASH_CMD_LOCK_BIT_READ (0x71U)
#define INT_FLASH_CMD_OTP_SET       (0x45U)
#define INT_FLASH_END_OF_CMD        (0xD0U)

#define INT_FLASH_AUTH_ID0 (0xFFFFFFFFUL)
#define INT_FLASH_AUTH_ID1 (0xFFFFFFFFUL)
#define INT_FLASH_AUTH_ID2 (0xFFFFFFFFUL)
#define INT_FLASH_AUTH_ID3 (0xFFFFFFFFUL)

#define INT_DATA_FLASH_MAX_WAIT (0xFFFFFFFFUL)

#define INT_DATA_FLASH_BLOCK_ADDR_MASK (0xFFFFFFC0UL)
#define INT_DATA_FLASH_DWORD_ADDR_MASK (0xFFFFFFFCUL)

#define INT_CODE_FLASH_UNLOCK_TIME_OUT (0x00000400UL)
#define INT_CODE_FLASH_ERASE_TIME_OUT  (0x00A00000UL)
#define INT_CODE_FLASH_WRITE_TIME_OUT  (0x00A00000UL)

#define INT_CODE_FLASH_8k_BLOCK_ADDR_MASK  (0xFFFFE000UL)
#define INT_CODE_FLASH_32k_BLOCK_ADDR_MASK (0xFFFF8000UL)
#define INT_CODE_FLASH_DWORD_ADDR_MASK     (0xFFFFFFFCUL)

Int_Data_Flash_Ctrl_st_t g_stIntDataFlashCtrl;
uint32_t                 g_u32IntDataFlashBuffer [ INT_DATA_FLASH_BUFFER_SIZE ];

void Int_Flash_Init(void)
{
    uint32_t u32Timer;

    /* Pull FLMD0 pin low */
    u32Timer = INT_CODE_FLASH_UNLOCK_TIME_OUT;
    do
    {
        FLMDPCMD = 0x000000A5UL;
        FLMDCNT  = 0x00000000UL;
        FLMDCNT  = 0xFFFFFFFFUL;
        FLMDCNT  = 0x00000000UL;
        u32Timer--;
    } while ( ((FACIFPMON & 0x80U) == 0x80U) && (u32Timer != 0UL) );

    g_stIntDataFlashCtrl.enMode        = INT_DATA_FLASH_READ;
    g_stIntDataFlashCtrl.u8Error       = 0U;
    g_stIntDataFlashCtrl.pfnCompleteCb = NULL;
}

/*
u32Addr: 4-byte aligned address
u32Data: DWord(32-bit) buffer
u32Len : DWord(32-bit) number to be read
*/
void Int_Data_Flash_Read(uint32_t u32Addr, uint32_t u32Data [], uint32_t u32Len)
{
    uint32_t i;

    if ( ((u32Addr & 0x00000003UL) == 0UL) && (u32Data != NULL) && (u32Len != 0UL) && (INT_DATA_FLASH_START_ADDR <= u32Addr) && (u32Addr + ((u32Len - 1UL) << 2U) < INT_DATA_FLASH_END_ADDR) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        g_stIntDataFlashCtrl.u8Error = 0U;

        DCIBEEPRDCYCL = 9U;
        for ( i = 0U; i < u32Len; i++ )
        {
            u32Data [ i ] = *(( volatile uint32_t * )u32Addr);
            u32Addr += 4UL;
        }
    }
}

void Int_Data_Flash_Erase(uint32_t u32StartAddr, uint32_t u32EndAddr)
{
    if ( (INT_DATA_FLASH_START_ADDR <= u32StartAddr) && (u32StartAddr <= u32EndAddr) && (u32EndAddr <= INT_DATA_FLASH_END_ADDR) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        g_stIntDataFlashCtrl.enMode     = INT_DATA_FLASH_ERASE;
        g_stIntDataFlashCtrl.u8Error    = 0U;
        g_stIntDataFlashCtrl.u32Addr    = u32StartAddr & INT_DATA_FLASH_BLOCK_ADDR_MASK;
        g_stIntDataFlashCtrl.u32DstAddr = u32EndAddr;

        FACIFENTRYR = 0xAA80U; /* Enter data flash P/E mode */

        R_DEV_IntClearFlag(R_DEV_INT_FLENDNM);
        R_DEV_IntEnable(R_DEV_INT_FLENDNM, 1U); /* Enable interrupt */

        FACIFCPSR  = 0x0001U;
        FACIFSADDR = g_stIntDataFlashCtrl.u32Addr;

        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_ERASE);
        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);
    }
}

/*
retval : offset of the first blank byte in the area to be checked
         !!! ATTENTION !!! offset!!! blank byte !!!
         0xFFFF FFFF is returned if no blank byte is found
*/
uint32_t Int_Data_Flash_Blank_Check(uint32_t u32StartAddr, uint32_t u32EndAddr)
{
    uint32_t u32Addr;
    uint32_t u32Continue;

    u32Addr = 0xFFFFFFFFUL;
    if ( (INT_DATA_FLASH_START_ADDR <= u32StartAddr) && (u32StartAddr <= u32EndAddr) && (u32EndAddr <= INT_DATA_FLASH_END_ADDR) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        g_stIntDataFlashCtrl.u8Error = 0U;

        FACIFENTRYR = 0xAA80U; /* Enter data flash P/E mode */

        FACIFBCCNT = 0x01U;
        FACIFSADDR = u32EndAddr & INT_DATA_FLASH_DWORD_ADDR_MASK;
        FACIFEADDR = u32StartAddr & INT_DATA_FLASH_DWORD_ADDR_MASK;

        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_BLANK_CHK);
        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);

        u32Continue = INT_DATA_FLASH_MAX_WAIT;
        while ( (FACIFRDY == 0U) && (u32Continue != 0UL) )
        {
            u32Continue--;
        }

        if ( u32Continue )
        {
            if ( FACIFASTAT & 0x98U )
            {
                FACIFASTAT = 0x00U; /* Clear  FACICFAE / FACIDFAE */
                Int_Data_Flash_Force_Stop( );
            }
            else
            {
                if ( FACIBCST == 0U )
                {
                    u32Addr = 0UL;
                }
                else
                {
                    u32Addr = FACIFPSADDR + 4UL;
                }

                FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
            }
        }
        else
        {
            Int_Data_Flash_Force_Stop( );
        }
    }

    return u32Addr;
}

/*
u32Addr: 4-byte aligned address
u32Data: DWord(32-bit) buffer
u32Len : DWord(32-bit) number to be written (<= 16, )
*/
void Int_Data_Flash_Write(uint32_t u32Addr, uint32_t u32Data [], uint32_t u32Len)
{
    uint32_t i;
    uint16_t u16Word;
    uint32_t u32DWord;

    if ( ((u32Addr & 0x00000003UL) == 0UL) && (u32Data != NULL) && (u32Len != 0UL) && (u32Len <= INT_DATA_FLASH_BUFFER_SIZE) && (INT_DATA_FLASH_START_ADDR <= u32Addr) && (u32Addr + ((u32Len - 1UL) << 2U) < INT_DATA_FLASH_END_ADDR) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        g_stIntDataFlashCtrl.enMode     = INT_DATA_FLASH_WRITE;
        g_stIntDataFlashCtrl.u8Error    = 0U;
        g_stIntDataFlashCtrl.u16Ptr     = 0U;
        g_stIntDataFlashCtrl.u32Addr    = u32Addr;
        g_stIntDataFlashCtrl.u32DstAddr = u32Addr + ((u32Len - 1UL) << 2U);

        for ( i = 0U; i < u32Len; i++ )
        {
            g_u32IntDataFlashBuffer [ i ] = u32Data [ i ];
        }

        FACIFENTRYR = 0xAA80U; /* Enter data flash P/E mode */

        R_DEV_IntClearFlag(R_DEV_INT_FLENDNM);
        R_DEV_IntEnable(R_DEV_INT_FLENDNM, 1U); /* Enable interrupt */

        u32DWord   = g_u32IntDataFlashBuffer [ g_stIntDataFlashCtrl.u16Ptr ];
        FACIFSADDR = g_stIntDataFlashCtrl.u32Addr;

        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_PROG);
        INT_FLASH_FACI_CMD_ISSUE(2U);
        u16Word = ( uint16_t )(u32DWord & 0x0000FFFFUL);
        INT_FLASH_FACI_DAT_ISSUE(u16Word);
        u16Word = ( uint16_t )((u32DWord >> 16U) & 0x0000FFFFUL);
        INT_FLASH_FACI_DAT_ISSUE(u16Word);
        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);
    }
}

Int_Data_Flash_Status_en_t Int_Data_Flash_Status_Get(void)
{
    Int_Data_Flash_Status_en_t enStatus;

    if ( g_stIntDataFlashCtrl.enMode != INT_DATA_FLASH_READ )
    {
        enStatus = INT_DATA_FLASH_BUSY;
    }
    else
    {
        if ( g_stIntDataFlashCtrl.u8Error )
        {
            enStatus = INT_DATA_FLASH_ERROR;
        }
        else
        {
            enStatus = INT_DATA_FLASH_IDLE;
        }
    }

    return enStatus;
}

void Int_Data_Flash_Register_P_E_Complete_Cb(Int_Flash_Cb_Func_t pfnCmpleteCb)
{
    g_stIntDataFlashCtrl.pfnCompleteCb = pfnCmpleteCb;
}

void Int_Data_Flash_Force_Stop(void)
{
    uint32_t u32Wait;

    do
    {
        FACIFENTRYR = 0xAA80U; /* Enter data flash P/E mode */
        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_STOP);
        u32Wait = INT_DATA_FLASH_MAX_WAIT;
        while ( (FACIFRDY == 0U) && (u32Wait != 0UL) )
        {
            u32Wait--;
        }
        FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
    } while ( FACICMDLK != 0U );
}

/******************************************************************************
Code Flash
******************************************************************************/

/*
u32Addr: 4-byte aligned address
u32Data: DWord(32-bit) buffer
u32Len : DWord(32-bit) number to be read
*/
Int_Flash_Result_en_t Int_Code_Flash_Read(uint32_t u32Addr, uint32_t u32Data [], uint32_t u32Len)
{
    uint32_t              i;
    Int_Flash_Result_en_t enResult;

    enResult = INT_FLASH_FAIL;
    if ( ((u32Addr & 0x00000003UL) == 0UL) && (u32Data != NULL) && (0UL < u32Len) && (u32Len <= INT_CODE_FLASH_SIZE / 4UL) && (u32Addr >= INT_CODE_FLASH_START_ADDR) && (u32Addr + ((u32Len - 1UL) << 2U) < INT_CODE_FLASH_END_ADDR) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        for ( i = 0U; i < u32Len; i++ )
        {
            u32Data [ i ] = *(( volatile uint32_t * )u32Addr);
            u32Addr += 4UL;
        }
        enResult = INT_FLASH_PASS;
    }

    return enResult;
}

#pragma ghs section text = ".ramfunc"

Int_Flash_Result_en_t Int_Code_Flash_Erase(uint32_t u32StartAddr, uint32_t u32EndAddr)
{
    uint8_t               u8Loop;
    uint32_t              u32Addr;
    uint32_t              u32Timer;
    Int_Flash_Result_en_t enResult;

    if ( (u32StartAddr >= INT_CODE_FLASH_START_ADDR) && (u32StartAddr <= u32EndAddr) && (u32EndAddr <= INT_CODE_FLASH_END_ADDR) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        /* ID Authentication */
        u32Timer = INT_CODE_FLASH_UNLOCK_TIME_OUT;
        while ( (SELFIDST != 0UL) && (u32Timer != 0UL) )
        {
            SELFID0 = INT_FLASH_AUTH_ID0;
            SELFID1 = INT_FLASH_AUTH_ID1;
            SELFID2 = INT_FLASH_AUTH_ID2;
            SELFID3 = INT_FLASH_AUTH_ID3;

            SELFID3;
        }

        /* Pull FLMD0 pin high */
        do
        {
            FLMDPCMD = 0x000000A5UL;
            FLMDCNT  = 0x00000001UL;
            FLMDCNT  = 0xFFFFFFFEUL;
            FLMDCNT  = 0x00000001UL;
            u32Timer--;
        } while ( ((FACIFPMON & 0x80U) == 0U) && (u32Timer != 0UL) );

        if ( u32Timer != 0UL )
        {
            u32Addr = u32StartAddr;
            if ( u32Addr < INT_CODE_FLASH_32k_BLOCK_START )
            {
                u32Addr &= INT_CODE_FLASH_8k_BLOCK_ADDR_MASK;
            }
            else
            {
                u32Addr &= INT_CODE_FLASH_32k_BLOCK_ADDR_MASK;
            }

            FACIFENTRYR = 0xAA01U; /* Enter code flash P/E mode */
            FACIFPROTR  = 0x5501U; /* Disables protection through lock bits */
            FACIFCPSR   = 0x0001U;

            u8Loop = 1U;
            while ( u8Loop )
            {
                FACIFSADDR = u32Addr;

                INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_ERASE);
                INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);

                u32Timer = INT_CODE_FLASH_ERASE_TIME_OUT;
                while ( (FACIFRDY == 0U) && (u32Timer != 0UL) )
                {
                    WDTA1WDTE = 0xACU;
                    u32Timer--;
                }

                if ( u32Timer )
                {
                    if ( FACIFASTAT & 0x98U ) /* Command lock status */
                    {
                        FACIFASTAT = 0x00U; /* Clear  FACICFAE / FACIDFAE */
                        Int_Code_Flash_Force_Stop( );
                        u8Loop = 0U;
                    }
                    else
                    {
                        if ( u32Addr < INT_CODE_FLASH_32k_BLOCK_START )
                        {
                            u32Addr += INT_CODE_FLASH_BLOCK_0_7_SIZE;
                        }
                        else
                        {
                            u32Addr += INT_CODE_FLASH_BLOCK_8_133_SIZE;
                        }

                        if ( u32Addr > u32EndAddr )
                        {
                            FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
                            enResult    = INT_FLASH_PASS;
                            u8Loop      = 0U;
                        }
                    }
                }
                else
                {
                    Int_Code_Flash_Force_Stop( );
                    u8Loop = 0U;
                }
            }
        }

        /* Pull FLMD0 pin low */
        u32Timer = INT_CODE_FLASH_UNLOCK_TIME_OUT;
        do
        {
            FLMDPCMD = 0x000000A5UL;
            FLMDCNT  = 0x00000000UL;
            FLMDCNT  = 0xFFFFFFFFUL;
            FLMDCNT  = 0x00000000UL;
            u32Timer--;
        } while ( ((FACIFPMON & 0x80U) == 0x80U) && (u32Timer != 0UL) );

        /* Lock code flash by ID */
        SELFID0 = 0x00000000UL;
        SELFID1 = 0x00000000UL;
        SELFID2 = 0x00000000UL;
        SELFID3 = 0x00000000UL;
    }

    return enResult;
}

/*
retval : offset of the first blank byte in the area to be checked
         !!! ATTENTION !!! offset!!! blank byte !!!
         0xFFFF FFFF is returned if no blank byte is found
*/
uint32_t Int_Code_Flash_Blank_Check(uint32_t u32StartAddr, uint32_t u32EndAddr)
{
    uint32_t u32Addr;
    uint32_t u32Continue;

    u32Addr = 0xFFFFFFFFUL;
    if ( (u32StartAddr >= INT_CODE_FLASH_START_ADDR) && (u32StartAddr <= u32EndAddr) && (u32EndAddr <= INT_CODE_FLASH_END_ADDR) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        FACIFENTRYR = 0xAA01U; /* Enter code flash P/E mode */

        FACIFBCCNT = 0x01U;
        FACIFSADDR = u32EndAddr & INT_CODE_FLASH_DWORD_ADDR_MASK;
        FACIFEADDR = u32StartAddr & INT_CODE_FLASH_DWORD_ADDR_MASK;

        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_BLANK_CHK);
        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);

        u32Continue = INT_DATA_FLASH_MAX_WAIT;
        while ( (FACIFRDY == 0U) && (u32Continue != 0UL) )
        {
            u32Continue--;
        }

        if ( u32Continue )
        {
            if ( FACIFASTAT & 0x98U )
            {
                FACIFASTAT = 0x00U; /* Clear  FACICFAE / FACIDFAE */
                Int_Code_Flash_Force_Stop( );
            }
            else
            {
                if ( FACIBCST == 0U )
                {
                    u32Addr = 0UL;
                }
                else
                {
                    u32Addr = FACIFPSADDR + 4UL;
                }

                FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
            }
        }
        else
        {
            Int_Code_Flash_Force_Stop( );
        }
    }

    return u32Addr;
}

/*
u32Addr: 256-byte aligned address
u32Data: DWord(32-bit) buffer
u32Len : DWord(32-bit) number to be written (Must be a multiple of 64)
*/
Int_Flash_Result_en_t Int_Code_Flash_Write(uint32_t u32Addr, uint32_t u32Data [], uint32_t u32Len)
{

    uint8_t  i;
    uint8_t  u8Loop;
    uint32_t u32Cnt;
    uint32_t u32Timer;

    Int_Code_Flash_Buffer_st_t *pstBuffer;
    Int_Flash_Result_en_t       enResult;

    enResult = INT_FLASH_FAIL;
    if ( ((u32Addr & 0x000000FFUL) == 0UL) && ((u32Len & 0x0000003FUL) == 0UL) && (u32Data != NULL) && (0UL < u32Len) && (u32Len <= INT_CODE_FLASH_SIZE / 4UL) && (INT_CODE_FLASH_START_ADDR <= u32Addr) && (u32Addr + ((u32Len - 1UL) << 2U) < INT_CODE_FLASH_END_ADDR) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        /* ID Authentication */
        u32Timer = INT_CODE_FLASH_UNLOCK_TIME_OUT;
        while ( (SELFIDST != 0UL) && (u32Timer != 0UL) )
        {
            SELFID0 = INT_FLASH_AUTH_ID0;
            SELFID1 = INT_FLASH_AUTH_ID1;
            SELFID2 = INT_FLASH_AUTH_ID2;
            SELFID3 = INT_FLASH_AUTH_ID3;

            SELFID3;
        }

        /* Pull FLMD0 pin high */
        do
        {
            FLMDPCMD = 0x000000A5UL;
            FLMDCNT  = 0x00000001UL;
            FLMDCNT  = 0xFFFFFFFEUL;
            FLMDCNT  = 0x00000001UL;
            u32Timer--;
        } while ( ((FACIFPMON & 0x80U) == 0U) && (u32Timer != 0UL) );

        if ( u32Timer != 0UL )
        {
            FACIFENTRYR = 0xAA01U; /* Enter code flash P/E mode */
            FACIFPROTR  = 0x5501U; /* Disables protection through lock bits */

            u8Loop = 1U;
            u32Cnt = 0UL;
            while ( u8Loop )
            {
                WDTA1WDTE = 0xACU;

                pstBuffer  = ( Int_Code_Flash_Buffer_st_t  *)(&u32Data [ u32Cnt ]);
                FACIFSADDR = u32Addr;
                INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_PROG);
                INT_FLASH_FACI_CMD_ISSUE(0x80U);

                i = 0U;
                while ( (u8Loop != 0U) && (i < 128U) )
                {
                    INT_FLASH_FACI_DAT_ISSUE(pstBuffer->u16Word [ i ]);

                    u32Timer = INT_CODE_FLASH_UNLOCK_TIME_OUT;
                    while ( (FACIDBFULL != 0U) && (u32Timer != 0UL) )
                    {
                        u32Timer--;
                    }

                    if ( u32Timer )
                    {
                        i++;
                    }
                    else
                    {
                        INT_FLASH_FACI_CMD_READ( );
                        Int_Code_Flash_Force_Stop( );
                        u8Loop = 0U;
                    }
                }

                if ( u8Loop )
                {
                    INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);

                    u32Timer = INT_CODE_FLASH_WRITE_TIME_OUT;
                    while ( (FACIFRDY == 0U) && (u32Timer != 0UL) )
                    {
                        u32Timer--;
                    }

                    if ( u32Timer )
                    {
                        if ( FACIFASTAT & 0x98U ) /* Command lock status */
                        {
                            FACIFASTAT = 0x00U; /* Clear  FACICFAE / FACIDFAE */
                            Int_Code_Flash_Force_Stop( );
                            u8Loop = 0U;
                        }
                        else
                        {
                            u32Addr += 256UL;
                            u32Cnt += 64UL;

                            if ( u32Cnt >= u32Len )
                            {
                                FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
                                enResult    = INT_FLASH_PASS;
                                u8Loop      = 0U;
                            }
                        }
                    }
                    else
                    {
                        Int_Code_Flash_Force_Stop( );
                        u8Loop = 0U;
                    }
                }
            }
        }

        /* Pull FLMD0 pin low */
        u32Timer = INT_CODE_FLASH_UNLOCK_TIME_OUT;
        do
        {
            FLMDPCMD = 0x000000A5UL;
            FLMDCNT  = 0x00000000UL;
            FLMDCNT  = 0xFFFFFFFFUL;
            FLMDCNT  = 0x00000000UL;
            u32Timer--;
        } while ( ((FACIFPMON & 0x80U) == 0x80U) && (u32Timer != 0UL) );

        /* Lock code flash by ID */
        SELFID0 = 0x00000000UL;
        SELFID1 = 0x00000000UL;
        SELFID2 = 0x00000000UL;
        SELFID3 = 0x00000000UL;
    }

    return enResult;
}

void Int_Code_Flash_Force_Stop(void)
{
    uint32_t u32Timer;

    do
    {
        FACIFENTRYR = 0xAA01U; /* Enter code flash P/E mode */
        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_STOP);
        u32Timer = INT_CODE_FLASH_WRITE_TIME_OUT;
        while ( (FACIFRDY == 0U) && (u32Timer != 0UL) )
        {
            u32Timer--;
        }
        FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
    } while ( FACICMDLK != 0U );
}

Int_Flash_Result_en_t Int_Config_Set_Read(uint32_t u32Addr, uint16_t u16Data [], uint32_t u32Len)
{
    uint32_t i = 0UL;

    Int_Flash_Result_en_t enResult = INT_FLASH_FAIL;

    if ( (u32Addr >= 0XFF300040UL) && (u32Addr <= 0XFF30008FUL) && (u16Data != NULL) && (u32Len <= 40UL) && (u32Len > 0UL) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        SYSCTRLFCUFAREA = 0x01U;
        nop( );
        nop( );
        nop( );
        nop( );
        nop( );
        for ( i = 0U; i < u32Len; i++ )
        {
            u16Data [ i ] = *(( volatile uint16_t * )u32Addr);
            u32Addr += 2UL;
        }

        SYSCTRLFCUFAREA = 0x00U;
        enResult        = INT_FLASH_PASS;
        nop( );
        nop( );
        nop( );
        nop( );
        nop( );
    }

    return enResult;
}
#pragma ghs section text = default
/*
u32Len must be 0x08
*/
Int_Flash_Result_en_t Int_Config_Program_Set_Write(uint32_t u32Addr, uint16_t u16Data [], uint32_t u32Len)
{
    uint32_t              u32Timer = INT_DATA_FLASH_MAX_WAIT;
    Int_Flash_Result_en_t enResult = INT_FLASH_FAIL;

    if ( (u32Addr >= 0XFF300040UL) && (u32Addr <= 0XFF30008FUL) && (u16Data != NULL) && (g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_READ) )
    {
        do
        {
            FACIFENTRYR = 0xAA80U; /* Enter data flash P/E mode */
            u32Timer--;
        } while ( (FACIFENTRYR != 0x0080U) && (u32Timer) );

        FACIFSADDR = u32Addr;

        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_CFG_PROG);
        INT_FLASH_FACI_CMD_ISSUE(0x08U);

        INT_FLASH_FACI_DAT_ISSUE(u16Data [ 0 ]);
        INT_FLASH_FACI_DAT_ISSUE(u16Data [ 1 ]);
        INT_FLASH_FACI_DAT_ISSUE(u16Data [ 2 ]);
        INT_FLASH_FACI_DAT_ISSUE(u16Data [ 3 ]);
        INT_FLASH_FACI_DAT_ISSUE(u16Data [ 4 ]);
        INT_FLASH_FACI_DAT_ISSUE(u16Data [ 5 ]);
        INT_FLASH_FACI_DAT_ISSUE(u16Data [ 6 ]);
        INT_FLASH_FACI_DAT_ISSUE(u16Data [ 7 ]);

        INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);

        u32Timer = INT_DATA_FLASH_MAX_WAIT;
        while ( (FACIFRDY == 0U) && (u32Timer != 0UL) )
        {
            u32Timer--;
        }
        if ( u32Timer )
        {
            if ( FACIFASTAT & 0x98U )
            {
                FACIFASTAT = 0x00U; /* Clear  FACICFAE / FACIDFAE */
                Int_Data_Flash_Force_Stop( );
            }
            else
            {
                FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
                enResult    = INT_FLASH_PASS;
            }
        }
        else
        {
            Int_Data_Flash_Force_Stop( );
        }
    }

    return enResult;
}
/**************************************************************************/ /**
                                                                              * \brief      Internal flash ready interrupt service routines
                                                                              * \retval     None
                                                                              ******************************************************************************/
void Int_Flash_Ready_ISR(void)
{
    uint16_t u16Word;
    uint32_t u32DWord;

    R_DEV_IntClearFlag(R_DEV_INT_FLENDNM);

    if ( FACIFASTAT & 0x98U )
    {
        FACIFASTAT = 0x00U; /* Clear  FACICFAE / FACIDFAE */
        Int_Data_Flash_Force_Stop( );
        g_stIntDataFlashCtrl.enMode  = INT_DATA_FLASH_READ;
        g_stIntDataFlashCtrl.u8Error = 1U;
        R_DEV_IntEnable(R_DEV_INT_FLENDNM, 0U);
        if ( g_stIntDataFlashCtrl.pfnCompleteCb != NULL )
        {
            g_stIntDataFlashCtrl.pfnCompleteCb( );
        }
    }
    else
    {
        if ( g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_ERASE )
        {
            g_stIntDataFlashCtrl.u32Addr += INT_DATA_FLASH_BLOCK_SIZE;
            if ( g_stIntDataFlashCtrl.u32Addr <= g_stIntDataFlashCtrl.u32DstAddr )
            {
                FACIFSADDR = g_stIntDataFlashCtrl.u32Addr;

                INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_ERASE);
                INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);
            }
            else
            {
                FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
                R_DEV_IntEnable(R_DEV_INT_FLENDNM, 0U);
                g_stIntDataFlashCtrl.enMode = INT_DATA_FLASH_READ;
                if ( g_stIntDataFlashCtrl.pfnCompleteCb != NULL )
                {
                    g_stIntDataFlashCtrl.pfnCompleteCb( );
                }
            }
        }
        else if ( g_stIntDataFlashCtrl.enMode == INT_DATA_FLASH_WRITE )
        {
            g_stIntDataFlashCtrl.u16Ptr++;
            g_stIntDataFlashCtrl.u32Addr += 4UL;
            if ( g_stIntDataFlashCtrl.u32Addr <= g_stIntDataFlashCtrl.u32DstAddr )
            {
                u32DWord   = g_u32IntDataFlashBuffer [ g_stIntDataFlashCtrl.u16Ptr ];
                FACIFSADDR = g_stIntDataFlashCtrl.u32Addr;

                INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_CMD_PROG);
                INT_FLASH_FACI_CMD_ISSUE(2U);
                u16Word = ( uint16_t )(u32DWord & 0x0000FFFFUL);
                INT_FLASH_FACI_DAT_ISSUE(u16Word);
                u16Word = ( uint16_t )((u32DWord >> 16U) & 0x0000FFFFUL);
                INT_FLASH_FACI_DAT_ISSUE(u16Word);
                INT_FLASH_FACI_CMD_ISSUE(INT_FLASH_END_OF_CMD);
            }
            else
            {
                FACIFENTRYR = 0xAA00U; /* Enter flash read mode */
                R_DEV_IntEnable(R_DEV_INT_FLENDNM, 0U);
                g_stIntDataFlashCtrl.enMode = INT_DATA_FLASH_READ;
                if ( g_stIntDataFlashCtrl.pfnCompleteCb != NULL )
                {
                    g_stIntDataFlashCtrl.pfnCompleteCb( );
                }
            }
        }
        else
        {
            Int_Data_Flash_Force_Stop( );
            g_stIntDataFlashCtrl.enMode  = INT_DATA_FLASH_READ;
            g_stIntDataFlashCtrl.u8Error = 1U;
            R_DEV_IntEnable(R_DEV_INT_FLENDNM, 0U);
            if ( g_stIntDataFlashCtrl.pfnCompleteCb != NULL )
            {
                g_stIntDataFlashCtrl.pfnCompleteCb( );
            }
        }
    }
}

static uint32_t CodeAddrStart = 0x1f8000;
static uint32_t CodeAddrEnd   = 0x1fffff;
static uint8_t  easedflag     = 0;
static uint8_t  ReadBuff [ 4096 ];
void            TestCodeFlashSer(void)
{
    uint32_t              datacnt;
    uint32_t              j;
    Int_Flash_Result_en_t estatus;
    uint8_t               data [ 5120 ];

    datacnt = CodeAddrEnd - CodeAddrStart + 1;

    for ( j = 0; j < 4096; j++ )
    {
        ReadBuff [ j ] = 0;
    }
    for ( j = 0; j < 1024; j++ )
    {
        data [ j ] = 0xaa;
    }

    for ( j = 0; j < 1024; j++ )
    {
        data [ j + 1024 ] = 0xbb;
    }

    for ( j = 0; j < 1024; j++ )
    {
        data [ j + 2048 ] = 0x55;
    }

    for ( j = 0; j < 1024; j++ )
    {
        data [ j + 3072 ] = 0x66;
    }

    if ( easedflag == 0 )
    {
        estatus   = Int_Code_Flash_Erase(CodeAddrStart, CodeAddrEnd);
        easedflag = 1;
    }

    // datacnt = 4096/1024;
    //  while(datacnt)
    {
        Int_Code_Flash_Write(CodeAddrStart, ( uint32_t * )&data [ 0 ], 256);
        Int_Code_Flash_Read(CodeAddrStart, ( uint32_t * )&ReadBuff [ 0 ], 320);

        CodeAddrStart += 1024;
        Int_Code_Flash_Write(CodeAddrStart, ( uint32_t * )&data [ 1024 ], 256);
        Int_Code_Flash_Read(CodeAddrStart, ( uint32_t * )&ReadBuff [ 1024 ], 320);

        CodeAddrStart += 1024;
        Int_Code_Flash_Write(CodeAddrStart, ( uint32_t * )&data [ 2048 ], 256);
        Int_Code_Flash_Read(CodeAddrStart, ( uint32_t * )&ReadBuff [ 2048 ], 320);
        CodeAddrStart += 1024;
        Int_Code_Flash_Write(CodeAddrStart, ( uint32_t * )&data [ 3072 ], 256);
        Int_Code_Flash_Read(CodeAddrStart, ( uint32_t * )&ReadBuff [ 3072 ], 256);
    }
}
