#include "stddef.h"
#include "string.h"
#include "r_typedefs.h"
#include "dr7f701441.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);
	}
}
