/*******************************************************************************
 *
 *  Module:         bootloader.c
 *  Description:    
 *
 ******************************************************************************/

#include "includes.h"
#include "boot.h"
#include "dataflash.h"
#include "Flash_API/Flash_API_R8C.h"


  
unsigned long userAppAddr;   				// obsahuje adresu zacatku USER APLIKACE
tUChar parsePos;

extern tUChar ramBuffer[RAM_BUFFER_SIZE];					// globalni rx a write buffer pro bootloader - stranka EEPROM ma 1024B
extern tsConstant  cfgsystem; 								// prostor v RAM pro strukturu CONSTANT 
extern tUChar gDataType[MAX_MESSAGE_LEN-SYS_HEADER_LEN-2];	// uchovava datovy obsah pro zpracovani DLL, RDI
extern tsOPER	 OPER;




  
  
/************************************************************************************
// CheckBootMode
// return: TRUE=Bootloader, FALSE=main
// vsechny varianty krome EDK4-RS a POW staruji hned do main()
// tato funkce musi byt v DATAFLASH abz se nesmazala a byla vzdy spustitelna
************************************************************************************/

//************************************************************************************
asm (".equ BOOT_MAIN_ADDRESS,			0x3080");	// toto je zacatek bootloaderu, pred tim zustava struct OPER 
asm (".equ BOOT_VARIABLE_VECT_ADDRESS,	0x3c00");	// tabulka vektoru pro bootloader - zapisuje se do registru INTB
//************************************************************************************
 __attribute__ ((section (".checkBoot"))) 
unsigned int CheckBootMode(void)
{
  #if defined INTERFACE_RS || defined INTERFACE_POW

  tUInt status;
  
  if ( OPER.BFL == BOOT_CHECK_BYTE)				// kontrolni bajt v DATAFLASH ze je bootloader nahrany a lze jej spustit 
   {
	 ALL_InterruptDisable;								// zakazat veskere preruseni
	 asm ("ldc 	#0x0, intbh");							// zmenit tabulku vektoru	
	 asm ("ldc 	#BOOT_VARIABLE_VECT_ADDRESS, intbl");	// tabulka vektoru bootloaderu
 	 asm ("jsr.a   BOOT_MAIN_ADDRESS");					// prejit na adresu bootloaderu
   }
  #endif  
}
	
	
	
/************************************************************************************/
// RestartToBootloader
// input: podle parametru staruje bud do rezimu bootloaderu nebo aplikace
// return: 1:OK/0:ERR								 																			*/ 
/************************************************************************************/
unsigned int RestartToBootloader(void)
{
#if defined INTERFACE_RS || defined INTERFACE_POW

 tUInt status;

 // smazat celou stranku DATAFLASH
 status = ClearDF(BLOCK_A);			
 if (status) return (-1);				// nepovedlo se smazat stranku, vypadnout s chybou

 // aktivace/deaktivace rezimu
 OPER.BFL = BOOT_CHECK_BYTE;			// zmenit kontrolni bajt v bufferu BOOT.frame

 write_Oper();							// zapsat zpet struktutu OPER do Dataflash
 wait_ms(20);							// pocklat po zapisu    
 if (status != NO_ERROR) return (-1);	// nepovedlo se zapsat, vypadnout s chybou   
 
 appCB.mode |= SYSBUSY_MASK;			// nastavit flag aby se neobsluhovaly zadne udalosti z fronty uloh
 SwReset();								// zapis ok, vyvola reset a nasledny vstup do BOOT rezimu
 while(1);

#endif
}



/************************************************************************************/
// InitBootFrame
// return: 
/************************************************************************************/
__attribute__ ((section (".page0f18"))) 
tUInt BootInitFrame(tUInt adrs, tUInt no)
{
#if defined INTERFACE_RS || defined INTERFACE_POW
   tUInt delay;
   tUInt status;
   
   LED_GRN_OFF;	
   LED_RED_ON;	
   
   // inicializovat celou strukturu BOOT
   my_memset((tUChar*)&BOOT, 0, sizeof (BOOT));
   	 
   my_memcpy (&ramBuffer[0], &gDataType[6], no);	// zkopirovat data do BOOT bufferu, ale jen data 
   
   BOOT.buffer = ramBuffer;			// 
   BOOT.address = adrs;				// pocatecni adresa na kterou ramec prijde ulozit
   BOOT.length = no;				// delka ulozeneho ramce


   LED_GRN_ON;	
   LED_RED_OFF;	

   
   return (status);								// pokud mazani probehlo OK, tak pokracovat
#endif
}




/************************************************************************************/
// CopyBootFrame
// return: 
/************************************************************************************/
__attribute__ ((section (".page0f19")))
void BootCopyFrame( tUInt bytes)
{	
#if defined INTERFACE_RS || defined INTERFACE_POW

   tUInt status;
   tUChar *ptr8;


   LED_GRN_OFF;	

   my_memcpy ( (tUChar*)&ramBuffer[0]+BOOT.length, (tUChar*)&gDataType[6], bytes);	// zkopirovat data do BOOT bufferu, ale jen data 
   
   BOOT.length += bytes;													// celkova delka jiz prijateho ramce


   wait_ms(100);
   
   LED_GRN_ON;	
   
#endif
}	



 
/************************************************************************************/
// WriteBootFrame
// return: 
/************************************************************************************/
__attribute__ ((section (".page0f20")))
tUInt BootWriteFrame(void)
{	
#if defined INTERFACE_RS || defined INTERFACE_POW

   tUInt status;

   LED_GRN_OFF;	
   LED_RED_ON;	

   FlashWrite();	   
   status = BOOT.status;

   wait_ms(100);
   
   LED_GRN_ON;	
   LED_RED_OFF;	

   return (status);	 

#endif
}	

