/** ###################################################################
**     THIS BEAN MODULE IS GENERATED BY THE TOOL. DO NOT MODIFY IT.
**     Filename  : IFsh1.C
**     Project   : QG8_test
**     Processor : MC9S08QG8CFQ
**     Beantype  : IntFLASH
**     Version   : Bean 02.173, Driver 01.15, CPU db: 2.87.095
**     Compiler  : CodeWarrior HCS08 C Compiler
**     Date/Time : 3/29/2007, 7:02 AM
**     Abstract  :
**         This bean "IntFLASH" implements an access to internal FLASH.
**         The bean support reading/writing data into FLASH, erasing of
**         selected sector.
**         The bean supports events if the write interrupt is supported.
**         The bean supports following modes of write operations:
**           - Write - writing without any test.
**           - Destructive write - sector is erased if necessary.
**           - Safe write - user event is invoked to save and resore data
**                          from the current sector.
**         The bean requires on-chip FLASH memory (not used/allocated by
**         other beans).
**     Settings  :
**         Total FLASH memory size       : 0x2000 bytes
**         Write method                  : Write
**         Wait in RAM                   : yes
**         Save buffer                   : Disabled
**         Virtual page                  : Disabled
**         CPU clock/speed selection
**           FLASH clock                 : 181 kHz
**           High speed mode             : This bean enabled
**     Contents  :
**         SetByteFlash - byte IFsh1_SetByteFlash(dword Addr,byte Data);
**         SetWordFlash - byte IFsh1_SetWordFlash(dword Addr,word Data);
**
**     (c) Copyright UNIS, spol. s r.o. 1997-2006
**     UNIS, spol. s r.o.
**     Jundrovska 33
**     624 00 Brno
**     Czech Republic
**     http      : www.processorexpert.com
**     mail      : info@processorexpert.com
** ###################################################################*/

/* MODULE IFsh1. */

#include "IFsh1.h"
#include "MC9S08QG8.h"


/* Internal method prototypes */
static void FnCmdInRam_(byte Comand_,word Addr_,byte Value_);
static void FnBurstProgCmdInRam_(word src, word dst, word size);
byte LaunchCmdEndTestError(byte Command_,word Addr_,byte Value_);
byte NonDestructiveUnsecureWrite(word src, word dst, word size);

#define FCMD_BLANK_CHECK    0x05       /* Flash command code */
#define FCMD_PROGRAM        0x20       /* Flash command code */
#define FCMD_BURST_PROGRAM  0x25       /* Flash command code */
#define FCMD_PAGE_ERASE     0x40       /* Flash command code */
#define FCMD_MASS_ERASE     0x41       /* Flash command code */
#define BM_FLASH_ERR_MASK   0x30       /* Bit mask to get FLASH error bits */

/*lint -save -e970 Disable MISRA rule (13) checking. */
typedef struct {
  unsigned char code[35];              /* Structure required to copy code to ram memory */
  /* Size of this structure needs to be at least (but best) the size of the FnCmdInRam_ */
} FnCmdInRamStruct;
typedef struct {
  unsigned char code[110];             /* Structure required to copy code to ram memory */
  /* Size of this structure needs to be at least (but best) the size of the FnBurstProgCmdInRam_ */
} FnBurstProgCmdInRamStruct;
/*lint -restore */


#pragma MESSAGE DISABLE C1805    /* Disable message: Non standard conversion used */

/*
** ===================================================================
**     Method      :  IFsh1_FnCmdInRam_ (bean IntFLASH)
**
**     Description :
**         This code burns one byte. It is copied to the RAM.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void FnCmdInRam_(byte Comand_,word Addr_,byte Value_)
{
  *(volatile byte *) (Addr_) = Value_; /* Write data to the flash memory */
  FCMD = Comand_;                      /* Initiate command */
  FSTAT = 0x80;                        /* Launch the command */
  if(!(FSTAT & BM_FLASH_ERR_MASK)) {   /* Protection violation or access error detected ? */
    while(!FSTAT_FCCF) {}              /* Wait to command complete */
  }
  return;
}
/*
** ===================================================================
**     Method      :  IFsh1_FnBurstProgCmdInRam_ (bean IntFLASH)
**
**     Description :
**         This code burns block of bytes. It is copied to the RAM.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void FnBurstProgCmdInRam_(word src, word dst, word size)
{
  while(size--) {                      /* For all written bytes do: */
    if(*(byte *)dst != *(byte *)src) { /* Is the src. byte equal to the dest. byte? */
      *(byte *)dst = *(byte *)src;     /* No, write byte to the flash memory */
      FCMD = FCMD_BURST_PROGRAM;       /* Initiate burst write command */
      FSTAT = 0x80;                    /* Launch the command */
      if(FSTAT & BM_FLASH_ERR_MASK) {  /* Error detected? */
        return;                        /* Yes, return */
      }
      dst++;                           /* Increment dest. pointer */
      src++;                           /* Increment src. pointer */
      while(!FSTAT_FCCF) {}            /* Wait for command buffer empty */
    } else {
      dst++;                           /* Increment dest. pointer */
      src++;                           /* Increment src. pointer */
    }
  } /* while */
}
/*
** ===================================================================
**     Method      :  IFsh1_LaunchCmdEndTestError (bean IntFLASH)
**
**     Description :
**         This method copies code to ram, executes it and test result.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
byte LaunchCmdEndTestError(byte Command_,word Addr_,byte Value_)
{
FnCmdInRamStruct FnCmdInRam=*(FnCmdInRamStruct *)(FnCmdInRam_);

  SaveStatusReg();                     /* Save the PS register */
  FSTAT=0x00;                          /* Init. flash engine */
  if(FSTAT & BM_FLASH_ERR_MASK) {      /* Protection violation or access error? */
    FSTAT = BM_FLASH_ERR_MASK;         /* Clear FPVIOL & FACERR flag */
  }
  ((pFnCmdInRam)&FnCmdInRam)(Command_,Addr_,Value_); /* Call code in RAM */
  if(FSTAT & BM_FLASH_ERR_MASK) {      /* Error detected? */
    RestoreStatusReg();                /* Yes, restore status information and interrupt state */
    if(FSTAT_FPVIOL) {                 /* Protect violation? */
      return ERR_PROTECT;              /* Return error code ERR_PROTECT */
    } else {
      return ERR_NOTAVAIL;             /* Return error code ERR_NOTAVAIL */
    }
  }
  while(!FSTAT_FCCF) {}                /* Wait for command completion */
  RestoreStatusReg();                  /* Restore the PS register */
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  IFsh1_NonDestructiveUnsecureWrite (bean IntFLASH)
**
**     Description :
**         This method performs Non-destructive unsecure write.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
byte NonDestructiveUnsecureWrite(word src, word dst, word size)
{
word x;                                /* Tmp. var. */
FnBurstProgCmdInRamStruct FnBurstProgCmdInRam=*(FnBurstProgCmdInRamStruct *)(FnBurstProgCmdInRam_); /* Copy function into the stack */

  if(dst < 0xE000) {                   /* Check addres */
    return ERR_RANGE;                  /* Address is out of FLASH memory */
  }
  if((size > 0x2000) || (dst+size-1 < 0xE000)) { /* Check block size and last addres of the block */
    return ERR_RANGE;                  /* Block is out of FLASH memory */
  }
  if(!FSTAT_FCCF) {                    /* Is previous command completed ? */
    return ERR_BUSY;                   /* If no then error */
  }
  SaveStatusReg();                     /* Save status information and disable interrupts(if enabled) */
  FSTAT=0x00;                          /* Init. flash engin */
  if(FSTAT & BM_FLASH_ERR_MASK) {      /* Protection violation or access error? */
    FSTAT = BM_FLASH_ERR_MASK;         /* Clear FPVIOL & FACERR flag */
  }
  ((pFnBurstProgCmdInRam)&FnBurstProgCmdInRam)(src,dst,size); /* Call code in ram */
  if(FSTAT & BM_FLASH_ERR_MASK) {      /* Error detected? */
    RestoreStatusReg();                /* Yes, restore status information and interrupt state */
    if(FSTAT_FPVIOL) {                 /* Protect violation? */
      return ERR_PROTECT;              /* Return error code ERR_PROTECT */
    } else {
      return ERR_NOTAVAIL;             /* Return error code ERR_NOTAVAIL */
    }
  }
  RestoreStatusReg();                  /* Restore status information and interrupt state */
  for(x=0x00;x<size;x++) {             /* Compare src. and written block */
    if(((byte*)src)[x] != ((byte*)dst)[x]) { /* Compare source byte and written byte */
      return ERR_VALUE;                /* Source value is different from dest. value, return error */
    }
  }
  return ERR_OK;
}

/*
** ===================================================================
**     Method      :  IFsh1_SetByteFlash (bean IntFLASH)
**
**     Description :
**         Write byte to address in FLASH.
**     Parameters  :
**         NAME            - DESCRIPTION
**         Addr            - Address to FLASH.
**         Data            - Data to write.
**     Returns     :
**         ---             - Error code, possible codes:
**                           - ERR_OK - OK
**                           - ERR_NOTAVAIL - Desired program/erase
**                           operation is not available
**                           - ERR_RANGE - Address is out of range
**                           - ERR_VALUE - Read value is not equal to
**                           written value
**                           - ERR_SPEED - This device does not work
**                           in the active speed mode
** ===================================================================
*/
byte IFsh1_SetByteFlash(word Addr,byte Data)
{
  return NonDestructiveUnsecureWrite((word)&Data,Addr,(word)0x01); /* Write data to the flash */
}

/*
** ===================================================================
**     Method      :  IFsh1_SetWordFlash (bean IntFLASH)
**
**     Description :
**         Write word to address in FLASH.
**     Parameters  :
**         NAME            - DESCRIPTION
**         Addr            - Address to FLASH.
**         Data            - Data to write.
**     Returns     :
**         ---             - Error code, possible codes:
**                           - ERR_OK - OK
**                           - ERR_NOTAVAIL - Desired program/erase
**                           operation is not available
**                           - ERR_RANGE - Address is out of range
**                           - ERR_VALUE - Read value is not equal to
**                           written value
**                           - ERR_SPEED - This device does not work
**                           in the active speed mode
** ===================================================================
*/
byte IFsh1_SetWordFlash(word Addr,word Data)
{
  return NonDestructiveUnsecureWrite((word)&Data,Addr,(word)0x02); /* Write data to the flash */
}

/*
** ===================================================================
**     Method      :  IFsh1_EraseSector (bean IntFLASH)
**
**     Description :
**         Erase sector to which address Addr belongs.
**     Parameters  :
**         NAME            - DESCRIPTION
**         Addr            - Address in FLASH.
**     Returns     :
**         ---             - Error code, possible codes:
**                           - ERR_OK - OK
**                           - ERR_NOTAVAIL - Desired program/erase
**                           operation is not available
**                           - ERR_RANGE - Address is out of range
**                           - ERR_SPEED - This device does not work
**                           in the active speed mode
** ===================================================================
*/
byte IFsh1_EraseSector(word Addr)
{
  if(Addr < 0xE000) {                  /* Check addres */
    return ERR_RANGE;                  /* Address is out of FLASH memory */
  }
  if(!FSTAT_FCCF) {                    /* Is previous command complete ? */
    return ERR_BUSY;                   /* If no then error */
  }
  return LaunchCmdEndTestError((byte)FCMD_PAGE_ERASE,Addr,(byte)0x00); /* Run command and return result */
}
/*
** ===================================================================
**     Method      :  IFsh1_Init (bean IntFLASH)
**
**     Description :
**         Description_Init - Initializes the associated peripheral(s) 
**         and the bean's internal variables. The method is called 
**         automatically as a part of the application initialization code.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
void IFsh1_Init(void)
{
  FSTAT = 0x30;                        /* Clear FPVIOL & FACERR flag */
  FCDIV = 0x16;                        /* Initialize FCDIV register */
}

/* END IFsh1. */
/*
** ###################################################################
**
**     This file was created by UNIS Processor Expert 2.98 [03.80]
**     for the Freescale HCS08 series of microcontrollers.
**
** ###################################################################
*/
