//#include "../app_Headers/g_includes.h"


#include "Include.h"

 /*
const INT8U Send_Command[]=
{
  0x1C, 0x01, 0x06, 0x80, 0x1F, 0x01, 0x06, 0x80, 0xFB, 0x3D

};
  */
#define Read_near(Addr)  ((unsigned int)(*(volatile unsigned int *__near)(Addr)))
#define Read_far(Addr)   ((unsigned int)(*(volatile unsigned int *__far)(Addr)))
/*************************************************************/
/*   注意: ADDR32即为Global address                          */
/*         ADDR32的取值范围 0x007E_0000-0x7F_FFFF            */
/*************************************************************/
INT16U PFlash_Read (INT32U ADDR32)
{                           
      uint data;
      data = Read_far(ADDR32);  
      return(data);              //返回一个字
}

INT32U PFlash_Near_Read (INT32U ADDR32)
{                           
      uint data;
      data = Read_near(ADDR32);  
      return(data);              //返回一个字
}

uint8_t DFLASH_Read_Word(uint32_t Adrr, uint8_t *Data,uint8_t len)
{
  uint8_t epage,i;
  uint8_t eStatus;
  uint16_t *DataTmp;
  uint8_t PageTmp;  
  uint32_t LogicAddr;
  
  eStatus =OK;

  if(len > 256)
  {
     eStatus = LENGTH_OUT_OF_RANGE;
  }

  len = len / 2;

  if(eStatus == OK)
  {
      PageTmp = (uint8_t)( Adrr / 0x400); 
      EPAGE =(uint8_t )(PageTmp & 0xff);
      DataTmp = (uint16_t*)Data;
      LogicAddr = (Adrr - D_Flash_Block_1) % 0x400 + 0x800;
      for(i =0;i<len;i++)
      {
          *DataTmp = (*(volatile unsigned short * )(LogicAddr + (i * 2)));
          DataTmp++;
      }
  }
  
  return eStatus;	/**/
}
    

typedef struct {
   uint8_t code[15];             /* Structure required to copy code to ram memory */
   
} FnCmdInRamStruct;

typedef void (* near pFnCmdInRam)(void);
 


#pragma CODE_SEG __NEAR_SEG NON_BANKED

static void FnCmdInRam_(void)
{
  FSTAT = 0x80U;                       /* Clear flag command buffer empty */
  while (FSTAT_CCIF == 0U) {}          /* Wait to command complete */
  return;
}

#pragma MESSAGE DISABLE C1805          /* Disable warning C1805 "Non-standard conversion used" */
/*lint -save  -e740 -e931 Disable MISRA rule (1.2) checking. */
static void CallFnCmdInRam()
{
  FnCmdInRamStruct FnCmdInRam = *(FnCmdInRamStruct *)(FnCmdInRam_); /* Create a copy of Wait in RAM routine on stack */

  ((pFnCmdInRam)&FnCmdInRam)();        /* Call code in RAM */
  return;
}

#pragma CODE_SEG DEFAULT


//DFLASH  擦除操作
INT8U DFLASH_Erase_Sector(INT32U address)
{
	//size of sector is 256 BYTE
	//check if address is aligned (global address [0] != 0)
	if ((address & 0x00000001) != 0)
		return MISALIGNED_ADDRESS;

	while (FSTAT_CCIF == 0)
		; //wait if command in progress

	FSTAT = 0x30; //clear ACCERR and PVIOL
	FCCOBIX = 0x00;
	FCCOB = 0x1200 | ((address & 0x007F0000) >> 16); //0x00030000
	//FCCOB =0x1210;

	FCCOBIX = 0x01;
	FCCOB = (unsigned int)address;

	cli();
	CallFnCmdInRam(); //asm JSR Send_Command;   //equal to    FSTAT_CCIF=1;   while(FSTAT_CCIF==0)asm JSR Send_Command;   //equal to    FSTAT_CCIF=1;   while(FSTAT_CCIF==0)

	sei();

	if ((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0)
		return ACCESS_ERROR;

	if (FSTAT_MGSTAT != 0)
		return VERIFICATION_FAILED;

	return OK;
}
//==============================================================================
//DFLASH_Erase_Verify_Section
//
//入口:address 为全局地址, number_of_words 为要校验的字单元个数
//==============================================================================
INT8U DFLASH_Erase_Verify_Section(INT32U address, INT16U number_of_words)
{
	if ((address & 0x00000007) != 0)
		return MISALIGNED_ADDRESS;
	while (FSTAT_CCIF == 0)
		;		  //wait if command in progress
	FSTAT = 0x30; //clear ACCERR and PVIOL
	FCCOBIX = 0x00;
	FCCOB = 0x1000 | ((address & 0x00FF0000) >> 16);
	FCCOBIX = 0x01;
	FCCOB = (address & 0x0000FFFF);
	FCCOBIX = 0x02;
	FCCOB = number_of_words;
	cli();
	CallFnCmdInRam(); //asm JSR Send_Command;   //equal to    FSTAT_CCIF=1;   while(FSTAT_CCIF==0)asm JSR Send_Command;   //equal to    FSTAT_CCIF=1;   while(FSTAT_CCIF==0)

	sei();
	if ((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0)
		return ACCESS_ERROR;
	if (FSTAT_MGSTAT != 0)
		return NON_ERASED;
	else
		return ERASED;
}

INT8U DFLASH_Program(INT32U address, INT16U *ptr, INT8U number_of_words)
{
	unsigned int i;

	if ((number_of_words < 1) || (number_of_words > 4))
		return LENGTH_OUT_OF_RANGE;

	//check if address is aligned (global address [0] != 0)
	if ((address & 0x00000001) != 0)
		return MISALIGNED_ADDRESS;

	//check if the word(s) is/are erased
	if ((DFLASH_Erase_Verify_Section(address, number_of_words)) == NON_ERASED)
		return NON_ERASED;

	while (FSTAT_CCIF == 0)
		; //wait if command in progress

	FSTAT = 0x30; //clear ACCERR and PVIOL
	FCCOBIX = 0x00;
	FCCOB = 0x1100 | ((address & 0x007F0000) >> 16); //0x00030000

	FCCOBIX = 0x01;
	FCCOB = (address & 0x0000FFFF);

	for (i = 1; i <= number_of_words; i++) //fill appropriate number of words to FCCOB
	{
		FCCOBIX = i + 1;
		FCCOB = *ptr;
		ptr++;
	}

	cli();
	CallFnCmdInRam(); //asm JSR Send_Command;   //equal to    FSTAT_CCIF=1;   while(FSTAT_CCIF==0)asm JSR Send_Command;   //equal to    FSTAT_CCIF=1;   while(FSTAT_CCIF==0)

	sei();

	if ((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0)
		return ACCESS_ERROR;

	if (FSTAT_MGSTAT != 0)
		return VERIFICATION_FAILED;

	return OK;
}
//DFLASH  写入函数
// //==============================================================================
// //入口:address 为全局地址
//  1<=number_of_words<=128
// //==============================================================================
 INT8U DFLASH_N_Program(INT32U address, INT8U *ptr, INT8U number_of_words)
 {
 	/*INT8U mRUL;

 	for (;;)
 	{
 		__RESET_WATCHDOG();
 		if (number_of_words >= 4)
 		{
 			mRUL = DFLASH_Program(address, ptr, 4);

 			if (mRUL != OK)
 				return mRUL;
 			ptr = ptr + 4;
 			address = address + 8;
 			number_of_words = number_of_words - 4;
 		}
 		else
 		{
 			if (number_of_words == 0)
 				return OK;

 			mRUL = DFLASH_Program(address, ptr, number_of_words);

 			return mRUL;
 		}
 	}*/
 	
    uint8_t eStatus,eProgramStatus;
    uint16_t *Datatptr;
    uint32_t Addr;
    uint8_t Length;

    eStatus = OK;
    eProgramStatus = OK;

    if(number_of_words>256u)
    {
        eStatus  = LENGTH_OUT_OF_RANGE;
    } 
    else
    {
        Length = (number_of_words / 2) - 2;
        Datatptr = ((uint16_t*)ptr) + 2;
        Addr = address + 4;  
        while(Length !=0u)         
        {
            if(Length>=4u)
            {
                eProgramStatus =DFLASH_Program(Addr ,Datatptr, 4);
                if(eProgramStatus == OK)
                {
                    Datatptr=Datatptr+4;

                    Addr=Addr+8u;

                    Length=Length-4u;
                } 
                else
                {
                    eStatus = ACCESS_ERROR;
                    break;
                }
            } 
            else
            {
                if(Length != 0u)
                {
                    eProgramStatus =DFLASH_Program(Addr ,Datatptr, Length);
                    if(eProgramStatus == OK)
                    {
                        Length = 0;
                        break;
                    } 
                    else
                    {
                        Length=0u;
                        eStatus = ACCESS_ERROR;
                        break;
                    }
                } 
                else
                {
                    Length = 0u;
                    break;
                }
            }
        }
        if(eProgramStatus == OK)
        {
            eProgramStatus =DFLASH_Program(address ,ptr, 2);
            if(eProgramStatus != OK)
            {
                eStatus = ACCESS_ERROR;
            }
        }
    } 
    return eStatus;  	
 }


#pragma DEFAULT
