/*****************************************************************************
File: Flash_API_R8C.c

CPU Re-write functions for R8C.

19.11.2009 RTA-CCB   Rev 1.4
*****************************************************************************/

#include "../typedefine.h"
#include "../iodefine.h"
#include "Flash_API_R8C.h"
#include "../main.h"

extern  tsBOOTLOADER	 BOOT;

//pokud je potreba znovu vygenerovat flashovaci kod, je potreba zavest definici REBUILD_FLASH_API_CODE


// adresy kde jsou ulozeny flashovaci rutiny v ROM
asm(".equ FLASH_WRITE_ADDRESS,	0xFC60");
asm(".equ FLASH_ERASE_ADDRESS,	0xFA80");


// definice chybovych kodu pro ret_value
#define	DF_ERROR_ERASE				0x01		// Erasing error
#define	DF_ERROR_ERASE_CMD_SEQ		0x02		// command Sequence Error		
#define	DF_ERROR_WR_CMD_SEQ			0x03		// write command Sequence Error		
#define	DF_ERROR_WR_ERROR			0x04		// write command Sequence Error		


//***************************************************************************
#if defined REBUILD_FLASH_API_CODE
// definice adres ROM + DATAFLASH	
unsigned long block_addresses[8] __attribute__ ((section (".page0const1")))  = \
		{0x0FFFF,0x0EFFF,0x0DFFF,0x0BFFF,0x33FF,0x37FF,0x3BFF,0x3FFF};
#endif
//***************************************************************************



/****************************************************************************
Name:	FlashEraseEW1 (Should be called using the name FlashErase)
Parameters:
		block
			The block number to erase (BLOCK_0, BLOCK_1, etc...)
Returns:
		0 = Erase Successful
		1 = Erase error reported by flash control
		2 = Command Sequence Error (locked block, incorrect command, etc)
Description:
		Erases an entire flash block.
*****************************************************************************/
tUInt FlashErase( void )
{
  unsigned char ret_value;
  
  #ifdef REBUILD_FLASH_API_CODE
   FlashEraseEW1();
  #else
   asm ("jsr.a	FLASH_ERASE_ADDRESS");	// skok na program 
  #endif
  
  ret_value = BOOT.status;				// navratova hodnota

  return ret_value;						// Return Pass/Fail
}



/*****************************************************************************/
#ifdef REBUILD_FLASH_API_CODE
__attribute__ ((section (".ferase"))) 
void FlashEraseEW1( void )
{
	unsigned char * flash_addr;
    unsigned char i, ret_value;
	unsigned char block;
    tUInt flags_reg;
    

	// pred parametry ze sdilene RAM
	block = BOOT.block;

	ret_value = NO_ERROR;

	// Get highest even block address
	flash_addr = (unsigned char *) block_addresses[ block ];

	//DISABLE_INTERRUPTS;	// Turn off maskable interrupts
    //asm("STC FLG, _flags_reg");
	asm("FCLR I");

	// R8C/3X Series 
	fmr01 = 0;
    asm("nop");
	fmr01 = 1;		// Set EW0 select bit

	fmr02 = 0;
    asm("nop");
	fmr02 = 1;		// Set to EW1 mode

	// povolit zapis do dataflash
	fmr13 = 0;		// Lock bit disable select bit
	fmr13 = 1;		// Must write a 0 then a 1 in succession to SET

	fmr14 = 1;		// odemknout blok A
	fmr14 = 0;		

	fmr15 = 1;		// odemknout blok B
	fmr15 = 0;		

	fmr16 = 0;		// zamknout blok C
	fmr16 = 1;		

	fmr17 = 0;		// zamknout blok D
	fmr17 = 1;		


    // Attempt to erase flash up to 3 times before returning failed 
    for( i = 0; i<3; i++)
     {
    	*flash_addr = 0x50;		// Clear status register
    	*flash_addr = 0x20;		// Send erase command
    	*flash_addr = 0xD0;		// Send erase confirm command

		// R8C/3X Series: 
		// For Data Flash areas, we have to wait for FST7 signal we are ready
		// which means we could go off and do other things. But when programming
		// non-Data Flash areas, the MCU is suspended until the operation completes.
		while(!fst7);
	
        // Check if operation was successful 
		// R8C/3X Series 
    	if( !fst5 )      	// Erasing Successful?
        {
			break;
        }
    }

	// Disable CPU rewriting commands by clearing EW entry bit 
	fmr0.byte = 0;


	// R8C/3X Series 
    if( fst4 && fst5 )	// Command Sequence Error?
    {
        ret_value =  DF_ERROR_ERASE_CMD_SEQ;
    }
	else if( fst5 )		// Erasing error?
	{
		ret_value =  DF_ERROR_ERASE;
	}
    else                // Erase Pass!!
    {
        ret_value =  NO_ERROR;          
    }

//	RESTORE_INTERRUPTS;         // Restore I flag to previsous setting
    //asm("LDC _flags_reg,FLG"); 
	asm("FSET I");
		
	BOOT.status = ret_value;
//	return ret_value;

}
#endif




/****************************************************************************
Name:	FlashWriteEW1 (Should be called using the name FlashWrite)
Parameters: 
		flash_addr
			Flash address location to write to.
		buffer_addr
			Address location of data buffer to write to flash
		bytes
			The number of bytes to write. An even or odd number of bytes is OK.
Returns:
		0 = Operation Successful
		1 = Write Error reported by flash control register
		2 = Invalid parameter passed
		3 = Command Sequence Error (locked block, incorrect command, etc)
Description:
		Writes bytes into flash.
****************************************************************************/
tUInt FlashWrite(void)
{
  unsigned char ret_value;

  #ifdef REBUILD_FLASH_API_CODE
   FlashWriteEW1();
  #else
   asm ("jsr.a	FLASH_WRITE_ADDRESS");	// skok na program 
  #endif
  

  ret_value = BOOT.status;
  return ret_value;				// Return Pass/Fail
}



/****************************************************************************/
#ifdef REBUILD_FLASH_API_CODE
__attribute__ ((section (".fwrite"))) 
void FlashWriteEW1(void)
{
	unsigned char ret_value;
	
	unsigned char * flash_addr;
	unsigned char * buffer_addr;
	unsigned int bytes;
	  
	// pred parametry ze sdilene RAM
	flash_addr = BOOT.address;
	buffer_addr = BOOT.buffer;
	bytes = BOOT.length;

	
	ret_value = NO_ERROR;

	//DISABLE_INTERRUPTS;	// Turn off maskable interrupts
   // asm("STC FLG, _flags_reg");
    asm("FCLR I");

	// R8C/3X Series 
	fmr01 = 0;
    asm("nop");
	fmr01 = 1;		// Set EW0 select bit

	fmr02 = 0;
    asm("nop");
	fmr02 = 1;		// Set to EW1 mode


	// povolit zapis do dataflash
	fmr13 = 0;		// Lock bit disable select bit
    asm("nop");
	fmr13 = 1;		// Must write a 0 then a 1 in succession to SET

	fmr14 = 1;		// odemknout blok A
	fmr14 = 0;		

	fmr15 = 1;		// odemknout blok B
	fmr15 = 0;		

	fmr16 = 0;		// zamknout blok C
	fmr16 = 1;		

	fmr17 = 0;		// zamknout blok D
	fmr17 = 1;		


	*flash_addr = 0x50;		// Clear status register
	while(bytes)
	{
		// Write to the flash sequencer by writting to that area of flash memory 
		*flash_addr = 0x40;				// Send write command
		*flash_addr = *buffer_addr;		// Write next word of data

		// R8C/3X Series: 
		// For Data Flash areas, we have to wait for FST7 signal we are ready
		// which means we could go off and do other things. But when programming
		// non-Data Flash areas, the MCU is suspended until the operation completes.
		while(!fst7);

		// R8C/3X Series 
		// Read flash program status flag 
		if( fst4 )					// Write error?
		{
            if( fst5 ) 				// Command Sequence error ?
    			ret_value = DF_ERROR_WR_CMD_SEQ;	// Signal a Command Sequence error
            else
    			ret_value = DF_ERROR_WR_ERROR;		// Signal the flash would not write
			break;					// Break out of while loop
		}

		flash_addr++;				// Advance to next flash write address
		buffer_addr++;				// Advance to next data buffer address

		// NOTE: The R8C writes to flash a 8 bits at a time where as the M16C
		// writes to flash 16 bits at a time. 
		bytes--;					// Subract 1 from byte counter
	}

	// Disable CPU rewriting commands by clearing EW entry bit 
	fmr0.byte = 0;					// (must be 16-bit write for M32C while in EW1 Mode)

// zase jakasi prasarna od japoncu
// je nutne pockat nejaou dobu pred povolenim interruptu, jinak neprobehne spravne zapis
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop");


	//RESTORE_INTERRUPTS;				// Restore I flag to previous setting
    //asm("LDC _flags_reg,FLG"); 
    asm("FSET I");
	
	BOOT.status = ret_value;
    
//	return ret_value;				// Return Pass/Fail
}
#endif




/****************************************************************************
Name:	BootEraseDF 
Parameters:
		block
			The block number to erase (BLOCK_0, BLOCK_1, etc...)
Returns:
		0 = Erase Successful
		1 = Erase error reported by flash control
		2 = Command Sequence Error (locked block, incorrect command, etc)
Description:
		Erases an entire flash block.
*****************************************************************************/
tUInt BootEraseDF(void)
{
  tUInt status;
  
  // v rezimu aplikace provadime pripravu pro zavedeni bootloaderu do DATAFLASH - bloky B+C
  status = ClearDF(BLOCK_B);				// BLOCK_B
  wait_ms(50);
  if (status != NO_ERROR) return (-1);				

  status = ClearDF(BLOCK_C);				// BLOCK_C
  wait_ms(50);
  if (status != NO_ERROR) return (-1);					
  
  return (NO_ERROR);
}




