/******************************************************************************
													            Copyright (c) Freescale 2009
File Name    : $RCSfile: main.c,v $

Current Revision :	$Revision: 2.0 $

PURPOSE: main program entry.                       
                                                                          
                                                                       
DESCRIPTION:  function main() providing initial program entry.
              flashfill() fills flash with known parameters
              flash_addr() fills the flash with the addresses
              MDelay() provides a software delay
              
              This program demo has been written to perfom flash operations on the 
              16-bit MCU S12P. It demonstrates how to write and erase to 
              the D-flash and P-flash.
                                                         
                                                                          
UPDATE HISTORY                                                            
REV  AUTHOR    DATE        DESCRIPTION OF CHANGE                          
---  ------    --------    ---------------------                          
1.0  r28318    09/06/09    - initial coding
2.0  b06320    08/06/09    - Flash program/erase example code

     ******************************************************************************
     * File created by: Freescale, East Kilbride, Scotland MSG Applications Group *
     ******************************************************************************

                                                                          
******************************************************************************/
/*===========================================================================*/
/* Freescale reserves the right to make changes without further notice to any*/
/* product herein to improve reliability, function, or design. Freescale does*/
/* not assume any  liability arising  out  of the  application or use of any */
/* product,  circuit, or software described herein;  neither  does it convey */
/* any license under its patent rights  nor the  rights of others.  Freescale*/
/* products are not designed, intended,  or authorized for use as components */
/* in  systems  intended  for  surgical  implant  into  the  body, or  other */
/* applications intended to support life, or  for any  other application  in */
/* which the failure of the Freescale product  could create a situation where*/
/* personal injury or death may occur. Should Buyer purchase or use Freescale*/
/* products for any such intended  or unauthorized  application, Buyer shall */
/* indemnify and  hold  Freescale  and its officers, employees, subsidiaries,*/
/* affiliates,  and distributors harmless against all claims costs, damages, */
/* and expenses, and reasonable  attorney  fees arising  out of, directly or */
/* indirectly,  any claim of personal injury  or death  associated with such */
/* unintended or unauthorized use, even if such claim alleges that  Freescale*/
/* was negligent regarding the  design  or manufacture of the part. Freescale*/
/* and the Freescale logo* are registered trademarks of Freescale Ltd.       */
/*****************************************************************************/

/************************* Include Files *************************************/
/*general includes */
#include <hidef.h>  /* also includes boolean definitions in stdtypes.h     */
#include <MC9S12P128.h>     /* derivative information */
//#include "target.h" 
//#include "S12P_peripherals.h" /* includes peripherals definitions and FSL data types */
#include "flash.h"


/************************* global const arrays **********************************/

const tU08 FlashPageNum[2] = {1, 4};/* D-flash:1 page; P-flash:8 pages (S12P has pages 08-0f but demo only includes 4 pages) */
/* logic address of one page of D-flash and four pages of P-flash */ 
const tU32 DPFlashPageStartAddrLogic[5] = { 0x10400,0xc8000, 0xd8000, 0xe8000, 0xf8000 };  

const tU32 FlashPageSize[2] = { 0x1000, 0x4000 }; /* 4k for D-flash, 16k for P-flash */

const tU16 FlashSectNum[2] = { 16, 256 }; /* totally, 16 sectors for D-flash, and 256 sectors for P-flash */
const tU16 FlashSectSize[2] = { 256, 512 }; // 256 sector size in bytes for D-flash, 512 for P-flash */
/* Global address D:0x0_4400~0x0_53ff; P: 0x3_0000~0x3_ffff */
const tU16 FlashStartAddrGL[2] = { 0x4400, 0x0000 }; /* bit15~0 of global address for D&P flash */ 
const tU16 FlashStartAddrGH[2] = { 0x0000, 0x0003 }; /* bit17~16 of global address for D&P flash */

const tU08 EraseFlashSector[2] = {
  ERASE_D_FLASH_SECTOR, ERASE_P_FLASH_SECTOR
};

const tU08 EraseVerifyFlashSector[2] = {
  ERASE_VERIFY_D_FLASH_SECTION, ERASE_VERIFY_P_FLASH_SECTION
};

const tU08 ProgramFlash[2] = {
  PROGRAM_D_FLASH, PROGRAM_P_FLASH
};


/******************************************************************************/

/************************* typedefs ******************************************/

/************************* #defines ******************************************/


/************************* Global Variables **********************************/
tU16 * __far data_ptr;
tU08 * __far byte_ptr;


/************************* function prototypes *******************************/
#pragma CODE_SEG DEFAULT
static tU08 LaunchFlashCommand(char params, tU08 command, tU08 ccob0, tU16 ccob1, 
                               tU16 ccob2, tU16 ccob3, tU16 ccob4, tU16 ccob5);
static tU16 FLASH_fill(tU08 type, tU16 val);
static tU16 FLASH_addr(tU08 type);
void MDelay(int delaytime);
/************************* Functions *****************************************/


/******************************************************************************
Function Name	:	FLASH_fill
Engineer		:	
Date			:	
Arguments	:	type:D-Flash or P-flash
            val: data pattern 
Return		: 0/success; others/fail 
Notes			:	This function writes known data pattern to flash and then reads the data 
            back before data checking
******************************************************************************/
tU16 FLASH_fill(tU08 type, tU16 val) 
{
  tU16 base, addr, j;
  tU32 i;
  
  // Fill D/P flash with a value 
  
  asm BGND; /* Software Breakpoint 1 - The function 'LaunchFlashCommand' is responsible for exercising the flash*/            
  base = FlashStartAddrGL[type];
  for (i = 0; i < FlashSectNum[type]; i++) 
  {
    
    if(LaunchFlashCommand(2, EraseFlashSector[type], FlashStartAddrGH[type], base, 0, 0, 0, 0) != CCIF_MASK) /* erase the flash block again*/
      return FLASH_ACCESS_ERROR;
    if(LaunchFlashCommand(3, EraseVerifyFlashSector[type], FlashStartAddrGH[type], base, FlashSectSize[type]>>3, 0, 0, 0) != CCIF_MASK) /* timing sector erase command */
      return FLASH_ACCESS_ERROR;
    	
	  addr = base;
	  for (j = 0; j < FlashSectSize[type]; j+=8) 
	  {
	    
	    if(LaunchFlashCommand(6, ProgramFlash[type], FlashStartAddrGH[type], addr, val, val, val, val) != CCIF_MASK) /* timing 1 word program command */
        return FLASH_ACCESS_ERROR;
      
	    addr += 8;
	  }
	  
	  base += FlashSectSize[type];
  }
  
  asm BGND;   /* Software Breakpoint 2 - by running to here the erase, erase verify and program commands have all been launched. The
                 flash has now been programmed as shown in the memory maps*/ 
  return FLASH_OK;
}


tU16 FLASH_addr(tU08 type)
{
  tU16 base, addr, j;
  tU32 i;
  
  // Fill the range with its address 
   
   asm BGND;   /* Software Breakpoint 3 - by running to here the erase, erase verify and program commands have all been launched. The P
                 flash has now been programmed with the addresses as shown in the memory maps*/  
  base = FlashStartAddrGL[type];
  for (i = 0; i < FlashSectNum[type]; i++) {
    
    if(LaunchFlashCommand(2, EraseFlashSector[type], FlashStartAddrGH[type], base, 0, 0, 0, 0) != CCIF_MASK) /* erase the flash block again*/
      return FLASH_ACCESS_ERROR;      
    if(LaunchFlashCommand(3, EraseVerifyFlashSector[type], FlashStartAddrGH[type], base, FlashSectSize[type]>>3, 0, 0, 0) != CCIF_MASK) /* timing sector erase command */
      return FLASH_ACCESS_ERROR;      
	
	  addr = base;
	  for (j = 0; j < FlashSectSize[type]; j+=8) {
	    
	    if(LaunchFlashCommand(6, ProgramFlash[type], FlashStartAddrGH[type], addr, addr, addr+2, addr+4, addr+6) != CCIF_MASK) /* timing 1 word program command */
        return FLASH_ACCESS_ERROR;
	    
	    addr += 8;
	  }
	  
	  base += FlashSectSize[type];
  }
    
  return FLASH_OK;
}
 
/******************************************************************************
Function Name	:	LaunchFlashCommand
Engineer		:	  b06320
Date			:	    08/06/09
Arguments	:	
Return		:
Notes			:	This function does not check if the Flash is erased.
            This function does not explicitly verify that the data has been 
					  sucessfully programmed.
					  This function must be located in RAM or a flash block not 
					  being programmed.
******************************************************************************/


tU08 LaunchFlashCommand(char params, tU08 command, tU08 ccob0, tU16 ccob1, tU16 ccob2, tU16 ccob3, tU16 ccob4, tU16 ccob5)
{
  if(FSTAT_CCIF == 1)
	{																	
		/* Clear any error flags*/	
	  FSTAT = (FPVIOL_MASK | ACCERR_MASK); 

    /* Write the command id / ccob0 */
		FCCOBIX = 0;
		FCCOBHI = command;
		FCCOBLO = ccob0;

    if(++FCCOBIX != params) {
      FCCOB = ccob1; 			/* Write next data word to CCOB buffer. */ 
      if(++FCCOBIX != params) {
  		  FCCOB = ccob2; 			/* Write next data word to CCOB buffer. */
        if(++FCCOBIX != params) {
   		    FCCOB = ccob3; 			/* Write next data word to CCOB buffer. */
          if(++FCCOBIX != params) {
            FCCOB = ccob4; 			/* Write next data word to CCOB buffer. */
            if(++FCCOBIX != params) 
         		  FCCOB = ccob5; 			/* Write next data word to CCOB buffer. */
          } 											
        }  
	    }
    }
	  FCCOBIX = params-1;
	  
	 	/* Clear command buffer empty flag by writing a 1 to it */
		FSTAT = CCIF_MASK;
    while (!FSTAT_CCIF) {					/* wait for the command to complete */
      /* Return status. */
    }
    return(FSTAT);							/* command completed */
  } 
  
	return(FLASH_BUSY);								   /* state machine busy */
}

/******************************************************************************
Function Name	: FLASH_access_test
Engineer	:	b19005
Date			:	30/11/08
Arguments	:	
Return		: 0/success; others/fail  
Note      : This function verify all the flash(D&P) location are accessable. we 
            disable any protection, and program known data patterns in unprotected 
            areas.
Test step : Run the App in special single chip mode
State     : Passed            
******************************************************************************/
tU16 FLASH_access_test(tU08 type)
{
  tU16 ret = 0;
    
  /* Run the fill tests */
  ret |= FLASH_fill(type, 0xAAAA);
  
  /* Run the address tests */
  ret |= FLASH_addr(type);
        
  return ret;
}

/******************************************************************************
Function Name	:	MDelay
Engineer		:	
Date			:	08/07/2009

Parameters		:	none
Returns			:	none
Notes			:	. 
******************************************************************************/

void MDelay(int delayTime)					
  {
    int x;				 //outer loop counter 
    char y;									 //inner loop counter 

    for (x=0; x<delayTime; x++){for (y=0; y<100; y++){}}
  }
  
/******************************************************************************
Function Name	: MAIN
Engineer	:	b19005, updated by b06320
Date			:	30/11/08, 08/07/09
Arguments	:	
Return		: 0/success; others/fail  
Note      : 

Test step : 
State     : Passed            
******************************************************************************/
void main(void) 
{   
  volatile tU16 status = 0;

  PORTA = 0x00;                    /* clear port A */
  DDRAB=0xFFFF;                    /* set port A and B to output*/
  CPMUCOP = 0x40;                  /* disable cop, stop COP and RTI counters when part is in active BDM mode. */
  ECLKCTL = 0x00;                  /* enable bus clock (ECLK) on PE4 - probe pin 27 with scope */
  
   
  /* initialise the system clock */
  CPMUSYNR = 0x5F;                 /* configure the PLL - 32 MHz bus clock */  
  CPMUREFDIV = 0x00;
  CPMUPOSTDIV = 0x00;
   
  while(!CPMUFLG_LOCK)          	 /* wait for PLL to lock */
  {
  }
	CPMUCLKS_PLLSEL = 1;             /*select the PLL as the clock source */
    		
  /* initialise the memory controller prior to any commands being launched or EEE data access */
  while (!FSTAT_CCIF) {					/* wait for FTM reset to complete */
  }
  FCLKDIV = 0x1F;                  /* BUSCLK 32MHz - Vital that this is correct for porper flash operation  */
          
  FPROT = 0xFF;	                   /* Disable any Protection that might be set */    
  DFPROT = 0xFF;
   
  asm BGND;                        /* Software breakpoint 0 - the following provide flash programming and erasing 
                                   /* on the P-flash*/ 
  status = FLASH_access_test(FLASH_TYPE_P);
     
  asm BGND;                        /* Software breakpoint 4 - the following provide flash programming and erasing 
                                   /* on the D-flash*/ 
  status = FLASH_access_test(FLASH_TYPE_D);
   
  
   /* output an indicator */
  OUTPUT_DDR = 1;
  if (status == 0)                 /* PASSED */
    OUTPUT_INDICATOR = 1;
  else
    OUTPUT_INDICATOR = 0;          /* FAILED */
   
   
  for(;;) 
  {
     PORTA ^=0xFF;                  /* flash LEDs to indicate end of program*/
     MDelay(10000);      
  
  } /* wait forever */
  /* please make sure that you never leave this function */
}
