/******************************************************************************
*                                                  
*  (c) copyright Freescale Semiconductor Ltd. 2007
*  ALL RIGHTS RESERVED
*                                                                       
*                                                                           
* FILE:        ICP_Flash.c	
*  
* DESCRIPTION: ICP Flash programming and Erasing 
*
*                                                  
* UPDATED HISTORY:
*
* REV   YYYY.MM.DD    AUTHOR         DESCRIPTION OF CHANGE
* ---   ----------  ------------     --------------------- 
* 0.1   2007.06.27  Patrick Yang     Initial version
* 
******************************************************************************/




#include "derivative.h"


#define gFlashSuccess  0x01
#define gFlashError    0xFF




 
//extern const unsigned char FLASHPGM_ROM[59]; 
const unsigned char FLASHPGM_ROM[59] = {  
0x87,0xC6,0x18,0x25,0xA5,0x10,0x27,0x08,0xC6,0x18,0x25,0xAA,0x10,0xC7,0x18,0x25,
0x9E,0xE6,0x01,0xF7,0xA6,0x20,0xC7,0x18,0x26,0x45,0x18,0x25,0xF6,0xAA,0x80,0xF7,
0x9D,0x9D,0x9D,0x9D,0x45,0x18,0x25,0xF6,0xF7,0xF6,0xA5,0x30,0x27,0x04,0xA6,0xFF,
0x20,0x07,0xC6,0x18,0x25,0xA5,0x40,0x27,0xF9,0x8A,0x81};


#define Page_Erase   FLASHPGM[21]=0x40; temp = ((unsigned char(*)(unsigned int))(FLASHPGM))
#define Program_Byte FLASHPGM[21]=0x20; temp = ((unsigned char(*)(unsigned int, unsigned char))(FLASHPGM))


/*********************************************************
* Name: FLASHPGM
*
* Desc: Flash program/erase routine, run in RAM   
*             
**********************************************************/
//Array of opcode instructions of the Erase/Program function in the HCS08 family
//volatile unsigned char FLASHPGM[59] = {  
//0x87,0xC6,0x18,0x25,0xA5,0x10,0x27,0x08,0xC6,0x18,0x25,0xAA,0x10,0xC7,0x18,0x25,
//0x9E,0xE6,0x01,0xF7,0xA6,0x20,0xC7,0x18,0x26,0x45,0x18,0x25,0xF6,0xAA,0x80,0xF7,
//0x9D,0x9D,0x9D,0x9D,0x45,0x18,0x25,0xF6,0xF7,0xF6,0xA5,0x30,0x27,0x04,0xA6,0xFF,
//0x20,0x07,0xC6,0x18,0x25,0xA5,0x40,0x27,0xF9,0x8A,0x81};

//Array of opcode instructions of the Erase/Program function in the HCS08 family
volatile unsigned char FLASHPGM[59]; 

/*  The opcode above represents this set of instructions  
    if (FSTAT&0x10){                     //Check to see if FACCERR is set
        FSTAT = FSTAT | 0x10;            //write a 1 to FACCERR to clear
    }
    (*((volatile unsigned char *)(Address))) = data;  //write to somewhere in flash
    FSTAT = 0x80;                        //Put FCBEF at 1.
    _asm NOP;                            //Wait 4 cycles
    _asm NOP;
    _asm NOP;
    _asm NOP;
    if (FSTAT&0x30){                     //check to see if FACCERR or FVIOL are set
    return 0xFF;                         //if so, error.
    }
    while ((FSTAT&0x40)==0){             //else wait for command to complete
        ;
    }*/
    
Tmp_Program_Byte(int dst_add,unsigned char data)
{
    if (FSTAT&0x10){                     //Check to see if FACCERR is set
        FSTAT = FSTAT | 0x10;            //write a 1 to FACCERR to clear
    }
    (*((volatile unsigned char *)(dst_add))) = data;  //write to somewhere in flash
    FSTAT = 0x80;                        //Put FCBEF at 1.
    _asm NOP;                            //Wait 4 cycles
    _asm NOP;
    _asm NOP;
    _asm NOP;
    if (FSTAT&0x30){                     //check to see if FACCERR or FVIOL are set
    return 0xFF;                         //if so, error.
    }
    while ((FSTAT&0x40)==0){             //else wait for command to complete
        ;
    }
 
}

/*********************************************************
* Name: Flash_Program
*
* Desc: Flash programming function   
*             
**********************************************************/
unsigned char Flash_Program(unsigned int dst_addr, unsigned int data_addr, unsigned char length) 
{
    static unsigned char data,temp;
    
    
    for(;length>0;length--) 
    {
      data=*(unsigned char *)data_addr;
      
      temp = Program_Byte(dst_addr,data);
      
      if(gFlashError == temp){
        return gFlashError;
      }
      
      dst_addr++;
      data_addr++;
    }
    
    return gFlashSuccess;
}



/*********************************************************
* Name: Flash_verify
*
* Desc: Flash verification
*             
**********************************************************/
unsigned char Flash_Verify(unsigned int dst_addr, unsigned int data_addr, unsigned char length) 
{
    unsigned char *flash, *ram;
    unsigned char status;
    
    
    flash = (unsigned char *)dst_addr;
	  ram = (unsigned char *)data_addr;
    
    do
	 {
		  if(*flash++ == *ram++)			        // compare two values
		{
		   status = gFlashSuccess;						// if same, continue to compare 
		}	
		else
		{
		    status = gFlashError;							// if different, break
		    break;
		 }
		 
	}	 
	while(--length);		
    
   return status;
}




/*********************************************************
* Name: Flash_Erase
*
* Desc: Flash earse function   
*             
**********************************************************/
unsigned char Flash_Erase(unsigned int addr) 
{
  unsigned char temp;
  
   
  temp=Page_Erase(addr);
  
  
  if(gFlashError == temp)
    return gFlashError;
  
  return gFlashSuccess;
}
 


/*********************************************************
* Name: FLASHPGM_Copy
*
* Desc: Copy flash routine to RAM   
*             
**********************************************************/
void FLASHPGM_Copy(void) 
{
  unsigned char *pSrc;
  unsigned char *pDst;
  unsigned char i;
  
  pSrc = (unsigned char *)FLASHPGM_ROM;
  pDst = (unsigned char *)FLASHPGM;
  
  
  for(i=59;i>0;i--) 
  {
     *pDst=*pSrc;
     pSrc++;
     pDst++;
  }
  
}
     