#include <hidef.h>      /* common defines and macros */
#include <mc9s12p128.h>     /* derivative information */
#include "flash.h"

/************************* global const arrays **********************************/
/* logic address of one page of D-flash and four pages of P-flash */ 
const tU32 FlashPageStartAddrLogic[4] = { 0xc8000, 0xd8000, 0xe8000, 0xf8000 };  

/******************************************************************************
Function Name	:	FLASH_p_addr
Engineer		:	b19005
Date			:	03/12/08
Arguments	:	   
Return		: 0/success; others/fail 
Notes			:	This function programs all P-flash with the data from 0x30000 to 0x3FFFF   
            (step = 2), that means the serial {0x0000, 0x0002, ... 0xFFFE}
******************************************************************************/
#pragma CODE_SEG  VERI_SEG
tU16 FLASH_p_addr()
{ 
  tU16 sect,page;
  
  // Fill the range with its address 
  for (page = 0; page < FLASH_P_PAGENUM; page++) {
  
    for (sect = 0; sect < FLASH_P_PAGESECTNUM; sect++) {
    
      if (FLASH_OK != FLASH_p_addr_sector(page,sect))
        return FLASH_PROGRAM_ERROR;
    }
  }
  
  return FLASH_OK;
}

/******************************************************************************
Function Name	:	FLASH_p_addr_sector
Engineer		:	b19005
Date			:	03/12/08
Arguments	: page: 0,1,2,3
            sector: 0...31	   
Return		: 0/success; others/fail 
Notes			:	This function programs a selected sector of P-flash with the data from 
            sector start global address to the sector end global address with step  
            2
******************************************************************************/
#pragma CODE_SEG  VERI_SEG
tU16 FLASH_p_addr_sector(tU08 page, tU08 sector)
{
  tU16 base, addr, j;
  tU32 i;
  
  // Fill the range with its address 
  base = FLASH_P_SADDRGL + page*FLASH_P_PAGESIZE + sector*FLASH_P_SECTSIZE ;

  if(LaunchFlashCommand(2, ERASE_P_FLASH_SECTOR, FLASH_P_ADDRGH, base, 0, 0, 0, 0) != CCIF_MASK) 
    return FLASH_PROGRAM_ERROR;      
  if(LaunchFlashCommand(3, ERASE_VERIFY_P_FLASH_SECTION, FLASH_P_ADDRGH, base, FLASH_P_SECTSIZE>>3, 0, 0, 0) != CCIF_MASK) 
    return FLASH_PROGRAM_ERROR;      
	
	addr = base;
	for (j = 0; j < FLASH_P_SECTSIZE; j+=8) {
	    
	  if(LaunchFlashCommand(6, PROGRAM_P_FLASH, FLASH_P_ADDRGH, addr, addr, addr+2, addr+4, addr+6) != CCIF_MASK) 
      return FLASH_PROGRAM_ERROR;
	    
	  addr += 8;
	}
  
  // Verify the data
  return FLASH_p_check_sector_data(page, sector, PATTERN_ADDRESS, 0);
    
}


/******************************************************************************
Function Name	:	FLASH_p_check_sector_data
Engineer		:	b19005
Date			:	03/12/08
Arguments	: page: 0,1,2,3
            sector: 0...31	
            mode: PATTERN_VALUE or PATTERN_ADDRESS 
            val: data for mode == PATTERN_VALUE  
Return		: 0/success; others/fail 
Notes			:	This function verify the data in a selected sector of P-flash
******************************************************************************/
#pragma CODE_SEG  VERI_SEG
tU16 FLASH_p_check_sector_data(tU08 page, tU08 sector, tU08 mode, tU16 val)
{
  tU16 i;

  // Verify the data
  data_ptr = (tU16 __far *) (FlashPageStartAddrLogic[page]+sector*FLASH_P_SECTSIZE);
  
  if (mode == PATTERN_VALUE) {
    
    for (i = 0; i < FLASH_P_SECTSIZE; i+=2) {
      
      if (*data_ptr++ != val) 
        return FLASH_PROGRAM_ERROR;
    }
  } 
  else {
    for (i = 0; i < FLASH_P_SECTSIZE; i+=2) {
      
      if (*data_ptr++ != FLASH_P_SADDRGL+FLASH_P_PAGESIZE*page+FLASH_P_SECTSIZE*sector+i) 
        return FLASH_PROGRAM_ERROR;
    }
  }
    
  return FLASH_OK;
}

/******************************************************************************
Function Name	:	FLASH_p_check_block_data
Engineer		:	b19005
Date			:	03/12/08
Arguments	: mode: PATTERN_VALUE or PATTERN_ADDRESS 
            val: data for mode == PATTERN_VALUE  
Return		: 0/success; others/fail 
Notes			:	This function verify the data in a selected block of P-flash
******************************************************************************/
#pragma CODE_SEG  VERI_SEG
tU16 FLASH_p_check_block_data(tU08 mode, tU16 val)
{
  tU16 sect,page;
  
  for (page = 0; page < FLASH_P_PAGENUM; page++) {
  
    for (sect = 0; sect < FLASH_P_PAGESECTNUM; sect++) {
    
      if (FLASH_OK != FLASH_p_check_sector_data(page, sect, mode, val))
        return FLASH_PROGRAM_ERROR;
    }
  }
  
  return FLASH_OK;
}

