//-------------------------------------------------------------------------------
// File Name:	boottasks.c
// Brief:
// Version:		1.1.0
// Create Date: 2020/07/31
// Create by: 	Marshal Lee
// Copyright:
//				Copyright (c)  2019, GetonAgain Co., LTD.
//				All rights reserved.
//
// Modify by:	Marshal Lee
// Modify Date:	2020/07/31
//-------------------------------------------------------------------------------

#include "boottasks.h"

#if (CUR_CORE_BOARD	== CORE_BOARD_BOOT)

#include "trigger.h"
#include "shell.h"
#include "delay.h"
#include "xmodem.h"
#include "serial.h"
#include "inout.h"
#include "norflash.h"
#include "stiap.h"
#include "stapp.h"
#include "smec98sp.h"
#include "operator.h"

void InitBootloader(void);
int WaitForInput(void);

void BootMainTask(void)
{
	int rslt;

	InitTrigger();		// 初始化定时触发功能

	InitShell();		// 初始化Shell命令

	printf("\r\n================== Bootloader ==================\r\n");

	do
	{// 上电2秒内,检测加密芯片是否正常
#if (USE_SMEC != 0)
		rslt = SMEC_Detection();
#else
		rslt = 0;
#endif
		if (rslt == 0)
		{
			break;
		}
		else
		{// 加密芯片不正常,指示灯1长3短
			printf("Err: Encryption chip access failed!\r\n");

			SetLedOn();
			DelayMs(2000);
			SetLedOff();

			DelayMs(300);

			SetLedOn();
			DelayMs(200);
			SetLedOff();

			DelayMs(300);

			SetLedOn();
			DelayMs(200);
			SetLedOff();

			DelayMs(300);

			SetLedOn();
			DelayMs(200);
			SetLedOff();

			DelayMs(2000);
		}
	}while(1);

	InitBootloader();

	printf("Bootloader init ok\r\n");

	rslt = WaitForInput();

	if (rslt == 0)			// 没有输入
	{
		UpdateApp();		// 升级主控文件
		JumpToApp();		// 进入APP
	}
	else
	{
		DelayMs(100);
		printf("Get input, enter update\r\n");
	}

	//----------------------------

	InitOperator();		// 初始化操作箱

	do
	{
		TriggerTask();	//

		ShellTask();

		OperatorTaskWhenBoot();

#if (0)		// 测试循环速度
		static u32 timer = 0;
		static u32 temp;
		static 	int runcount = 0;

		runcount++;
		temp = GetMsSoftTimer();
		if (temp - timer >= 1000)
		{
			timer = temp;
			printf("run circle = %d/s\r\n", runcount);
			runcount = 0;
		}
#endif
	}while(1);

}


//--------------------------------------------------

int WaitForInput(void)
{
	int rslt;
	int timer, tptimer;
	int steps;

	printf("Press ENTER into bootloader\r\n");

	DelayMs(100);

	rslt = 0;
	steps = 0;
	timer = GetMsSoftTimer();

	do
	{
		TriggerTask();	//
		if (ShellTask() >= 0)		// 如果串口有命令，那么执行响应
		{
#if (0)
			if (GetHistoryNum() > 0)
			{
				char input[20];
				int tmprst = GetHistoryCmd(0, &input[0]);
				if (tmprst == 0 && strcmp(input, "ver") == 0)
				{
					rslt = 1;
					break;
				}
			}
#else
			rslt = 1;
			break;
#endif
		}

		tptimer = GetMsSoftTimer();
		if (tptimer - timer > steps)
		{
			PutChar('.');
			steps += 100;
		}

		if (tptimer - timer > 1000)	// 1秒内没有输入
		{
			rslt = 0;
			break;
		}
	}while(1);
	printf("\r\n");
	return rslt;
}

//--------------------------------------------------

void LoadApp(char * para1, char * para2);
void JpToApp(char * para1, char * para2);

//---------------------------------------------------

void InitBootloader(void)
{
	printf("Begin bootloader task\r\n");

	InitNorSpi();			// 初始化 nor flash 访问 SPI
	SNFlashInit(SetNorSpiNssOn, SetNorSpiNssOff, NorSpiReadByte, NorSpiWriteByte);	// 初始化nor flash 并注册读写函数

	AddShellCmd("LOADAPP", "load the app", LoadApp);
	AddShellCmd("JUMPTOAPP", "jump to app", JpToApp);

	AddTriggerToList(100, SetLedToggle, NULL);		// 100ms 闪灯任务
}


#if (CONSOLE_PORT == COMM_USART1)

#define CLEAN_RS_BUFF		Usart1CleanRsBuf
#define IS_SDBUF_EMPTY		IsUsart1SendBufEmpty
#define GET_DATA			Usart1GetData
#define SEND_DATA			Usart1SendData
#define GET_RS_LEN			Usart1GetRsLen

#endif



// 从串口，网络或存储器 下载APP
void LoadApp(char * para1, char * para2)
{
	int rsv = 'x';
	int com = 1;
	int rslt = 0;

//	IAPCleanUpdateArea();	// 擦除nand APP 存储区域，

	if (para1 != NULL)
	{
		if (strcmp(para1, "") == 0 ||
			strcmp(para1, "x") == 0 ||
			strcmp(para1, "X") == 0 ||
			0	)
		{
			rsv = 'x';		// xmodem
			if (para2 != NULL)
			{
				com = atoi(para2);
				if (com <= 0 || com > 2)
				{
					com = 1;
				}
			}
		}
		else if (strcmp(para1, "t") == 0 ||
				 strcmp(para1, "T") == 0 ||
				 0	)
		{
			rsv = 't';		// 网络
		}
		else if (strcmp(para1, "s") == 0 ||
				 strcmp(para1, "S") == 0 ||
				 0	)
		{
			rsv = 's';		// 串口
		}
		else
		{

		}
	}

	if (rsv == 'x')
	{
		int timer;
		XmodemCtrl xctrl;
		printf("receive by xmodem start\r\n");

		if (com == 1)
		{
			SetPauseStatus(1);		// 关闭终端
			CLEAN_RS_BUFF();			// 读空接收buff

			// 等到发送buff为空
			timer = GetMsSoftTimer();	// 记录时间
			do
			{
				if (IS_SDBUF_EMPTY() == TRUE)
				{
					break;
				}

				if (GetMsSoftTimer() - timer > 2000)		// 判断是否超时
				{
					SetPauseStatus(0);		// 打开终端
				}
			}while(1);

			// 注册函数
			xctrl.XmodemInBuff = GET_DATA;
			xctrl.XmodemOutBuff = SEND_DATA;
			xctrl.XmodemGetInBuffLen = GET_RS_LEN;
			xctrl.XmodemCleanBuff = CLEAN_RS_BUFF;
			xctrl.InitSave = InitSaveApp;
			xctrl.SaveData = SaveAppData;
			xctrl.savedsize = 0;

			rslt = XmodemReceive(&xctrl);

			// 等到发送buff为空
			timer = GetMsSoftTimer();	// 记录时间
			do
			{
				if (IS_SDBUF_EMPTY() == TRUE)
				{
					break;
				}

				if (GetMsSoftTimer() - timer > 2000)		// 判断是否超时
				{
					SetPauseStatus(0);		// 打开终端
				}
			}while(1);

			CLEAN_RS_BUFF();		// 读空接收buff
			SetPauseStatus(0);		// 打开终端

			OutDebugBufInfo();
		}
		else
		{
			// 暂时不支持
			printf("1. not support com port=%d\r\n", com);
		}

		printf("\r\nreceive by xmodem end\r\n");

		if (rslt == 1)
		{
			printf("receive done, check is save data correct\r\n");

			rslt = IsAppReceiveDone();		// 判断是否接收完成，并读取数据量

			if (rslt == xctrl.savedsize)
			{
				StartAppUpdate(0);	// 验证是否保存成功
			}
			else
			{
				printf("receive size not equ, xctrl.savedsize=%d, received=%d\r\n", xctrl.savedsize, rslt);
			}
		}
		else
		{
			printf("receive not finish\r\n");
		}
	}
	else
	{
		// 暂时不支持
		printf("2. not support comm type=%c\r\n", rsv);
	}
}

void JpToApp(char * para1, char * para2)
{
	JumpToApp();		// 进入APP
}

#endif

