

#include "boot_jump.h"
#include "Uds_Service.h"
#include "device_registers.h"
#include "sdk_project_config.h"

volatile uint32_t appEntry, appStack;
static uint32_t eclipseTime=0;

#if 1
void shutdown_drivers(void)
{
	lpTMR_DRV_Deinit(0);
	FLEXCAN_DRV_Deinit(0);
	INT_SYS_DisableIRQ(lpTMR0_IRQn);
	INT_SYS_DisableIRQGlobal();
}
#else
extern void shutdown_drivers(void);
#endif

void System_Reset(void)
{
	SystemSoftwareReset();
}

void Boot_TimeService(void) {
    /* just keep to 1min*/
    if(eclipseTime<60000U) {
        eclipseTime++;
    }
}
void udsRxCallback(uds_channel_t channel, uds_u8_t* data, uds_u16_t dataLength)
{
    /*If we received any uds frame when startup < KEEP_IN_BOOT_TIME ms, we will keep in boot */
    // if(eclipseTime<KEEP_IN_BOOT_TIME) {
    //     forceKeepInBoot=true;
    // }
	DCM_m_t_PollingTimer = ECU_m_num_SysTick;
	DCM_m_t_StayInTimer = ECU_m_num_SysTick;
}

void bootup_application(uint32_t appEntry, uint32_t appStack)
{
	static void (*jump_to_application)(void);
	static uint32_t stack_pointer; 
	jump_to_application = (void (*)(void))appEntry;
	stack_pointer = appStack;
	
	SCB->VTOR = APP_IMAGE_START;

	__set_PSP(stack_pointer);
	__set_MSP(stack_pointer);

	/* shutdown_drivers() masked the global interrupts (PRIMASK=1).
	 * Restore them here, otherwise the app boots with all interrupts
	 * masked and its CAN RX interrupt never fires -> host cannot
	 * communicate with the app after the jump. */
	INT_SYS_EnableIRQGlobal();

	jump_to_application();
}

 void JumpTo_Application(void)
 {
	shutdown_drivers();
 	appStack = *(volatile uint32_t*) APP_IMAGE_START;  /* setup app jump */
	appEntry = *(volatile uint32_t*)(APP_IMAGE_START + 4);
	bootup_application(appEntry,appStack);

	while(1){};
}



__attribute__((section(".fbl_bss"))) volatile uint32_t KeepInBootVar;


void StayInBoot_Init(void)
{
    uint8_t mark_data[8]={0};
    uds_global_ip_api.readFlash(APP_IMAGE_START-MCU_SECTOR_SIZE,mark_data,0x08);
    if (mark_data[0] == 1)
    {
        Uds_SetSession(0,UDS_SESSION_PROGRAMMING);
    }
    else 
	{
        if (KeepInBootVar == 1)
        {
			Uds_SetSession(0,UDS_SESSION_PROGRAMMING);
		}
    }
}



void StayInBoot_Task(void)
{
	uint8_t session = Uds_GetSession(0);

	if (session == UDS_SESSION_DEFAULT)
	{
		uint8_t mark_data[8]={0};
		uds_global_ip_api.readFlash(APP_IMAGE_START-MCU_SECTOR_SIZE,mark_data,0x08);
		if (mark_data[0] != 0)
		{
			Uds_SetSession(0,UDS_SESSION_PROGRAMMING);
			return;
		}
		else
		{
			if ((ECU_m_num_SysTick - DCM_m_t_PollingTimer) >= DCM_C_T_FBL_POLLING)
			{
	#if 1
				KeepInBootVar = 0;
				JumpTo_Application();
	#endif
			}
		}
	}
#if 1
/* jump out programming session when timeout */
	else if (session == UDS_SESSION_PROGRAMMING)
	{
		uint8_t mark_data[8]={0};
		uds_global_ip_api.readFlash(APP_IMAGE_START-MCU_SECTOR_SIZE,mark_data,0x08);
		if (mark_data[0] == 0)
		{
			if ((ECU_m_num_SysTick - DCM_m_t_StayInTimer) >= DCM_C_T_FBL_STAYINBOOT)
			{
	#if 1
				KeepInBootVar = 0;
				JumpTo_Application();
	#endif
			}
		}
	}
#endif
}

