#include "gd32f10x.h"
#include "boot.h"
#include "main.h"
#include "delay.h"
#include "fmc.h"
#include "w25q32.h"
#include <stdio.h>
#include "ota_message.h"
#include "ec800m.h"
#include "usart.h"
#define APP_PROGRAMMER_BLOCK 2   //程序在W25Q32中存放的位置

load_a load_A;       

//返回str在数组中的索引
static char* find_string(char *strs, char *str,int first, int len)
{
    int i = 0;
	char *start = NULL;
	strs = strs + first;
    while(i < len){
		start = strstr(strs, str);
        if(start != NULL){
            break;
        }
        i++;
        strs++;
    }
    if(i == len + 1){
        return NULL;
    }
    return start;
}


int WaitForReadData(uint8_t* data,int timeout,int datalen)
{
	uint32_t len = 0;
	bool timeoutFlag = false;
	if (timeout >= 0)
	{
		timeoutFlag = true;
	}
	while (1)
	{
		Delay_Ms(50);
		if ((UART0_RX_STAT > 0) && (find_string((char *)&UART0_RX_BUF, "\r\nOK\r\n",datalen, sizeof(UART0_RX_BUF))))
		{
			UART0_RX_STAT = 0;
			// char *p = strstr((char *)&UART0_RX_BUF, "CONNECT ");
			// if (p)
			// {
				// p += 8;
				// sscanf(p, "%u\r", &len);		// 读取长度
				// if(len == datalen)
				// {
					// p = strchr(p, '\n') + 1;		// 跳过换行
					memcpy(data,(char *)&UART0_RX_BUF,datalen);
					Clear_DMA_Buffer();
					return datalen;
				// }
				// else
				// {
				// 	Clear_DMA_Buffer();
				// 	return len;
				// }
		}
			
		
		timeout -= 50;
		if (timeoutFlag == true && timeout <= 0)
		{
			Clear_DMA_Buffer();
			return -1;
		}
		
	}
	
}

//进入bootloader更新
void BootLoader_Brance(uint32_t app_byte)
{
	GD32_EraseFlash(GD32_A_START_PAGE,GD32_A_PAGE_NUM);//擦除A区原有程序
	/* 打开UFS:otaDATA.txt */
	EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
	WaitResponse("QFCLOSE",1000);
	EC800MSendCmd(OPEN_otaDATA_FILE,strlen(OPEN_otaDATA_FILE));
	if(WaitResponse("QFOPEN:", 2000) == 0)
		return;
	for(uint8_t i=0;i<app_byte/1024;i++)				//1KB写一次
	{
		uint8_t app_programmer[1024];
		memset(app_programmer,0,1024);
		// uint32_t addr=APP_PROGRAMMER_BLOCK*64*1024+i*1024;   //其在w25q32中的地址
		// W25Q32_Read(app_programmer,addr,1024);
		while(1)
		{
			task_fwdgt_reload();
			int x = 0;
			EC800MSendCmd(READ_otaDATA_FILE,strlen(READ_otaDATA_FILE));
			Delay_Ms(200);
			x = WaitForReadData(app_programmer,2000,1024);
			// if((x != 1024) && (x != -1))
			// {
			// 	char* SEEK_otaDATA_FILE = "";
			// 	sprintf(SEEK_otaDATA_FILE,"AT+QFSEEK=1,%d,2\r\n",x);
			// 	EC800MSendCmd(SEEK_otaDATA_FILE,strlen(SEEK_otaDATA_FILE));	//出错的话文件指针向左偏移1024个字节
			// }
			// else 
			if(x == 1024)
			{
				break;
			}
		}
		GD32_WriteFlash(GD32_A_SADDR+i*1024,(uint32_t *)&app_programmer,1024); //将读出的数据按页写入数据
		Delay_Ms(50);
	}
	//将不满1024数据单独写入
	if(app_byte % 1024 != 0)
	{
		uint32_t startAddress=(app_byte/1024)*1024;
		uint8_t app_programmer[1024];
		memset(app_programmer,0,1024);
		// uint32_t addr=APP_PROGRAMMER_BLOCK*64*1024+(app_byte/1024)*1024;   														//其在w25q32中的地址
		// W25Q32_Read(app_programmer,addr,app_byte%1024);	
		while(1)
		{
			task_fwdgt_reload();
			int x = 0;
			EC800MSendCmd(READ_otaDATA_FILE,strlen(READ_otaDATA_FILE));
			Delay_Ms(200);
			x = WaitForReadData(app_programmer,2000,app_byte % 1024);
			// if(x != (app_byte % 1024) && (x != -1))
			// {
			// 	char* SEEK_otaDATA_FILE = "";
			// 	sprintf(SEEK_otaDATA_FILE,"AT+QFSEEK=1,%d,2\r\n",x);
			// 	EC800MSendCmd(SEEK_otaDATA_FILE,strlen(SEEK_otaDATA_FILE));	//出错的话文件指针向左偏移读取字节数
			// }
			// else 
			if(x == (app_byte % 1024))
			{
				break;
			}
		}																			
		GD32_WriteFlash(GD32_A_SADDR+(app_byte/1024)*1024,(uint32_t *)&app_programmer,app_byte % 1024);
		Delay_Ms(50);
	}
	// 保存UFS文件
	while(1)
	{
		EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
		if(WaitResponse("OK", 2000) == 1)
		{
			break;
		}
	}
	Delay_Ms(50);
	clear_ota_message_config_block();  
	LOAD_A(GD32_A_SADDR);
}


/*-------------------------------------------------*/
/*函数名：设置SP                                   */
/*参  数：addr：栈顶指针初始值                     */
/*返回值：无                                       */
/*-------------------------------------------------*/
__asm void MSR_SP(uint32_t addr)
{
	MSR MSP, r0      
	BX r14             
}
/*-------------------------------------------------*/
/*函数名：跳转到A区                                */
/*参  数：addr：A区的起始地址                      */
/*返回值：无                                       */
/*-------------------------------------------------*/
void LOAD_A(uint32_t addr)
{
	if((*(uint32_t *)addr>=0x20000000)&&(*(uint32_t *)addr<=0x20017FFF)){     
		MSR_SP(*(uint32_t *)addr);                                            
		load_A = (load_a)*(uint32_t *)(addr+4);                               
		BootLoader_Clear();                                                
		load_A();                                       
	}else ; 
}
/*-------------------------------------------------*/
/*函数名：清除B区使用的外设                        */
/*参  数：无                                       */
/*返回值：无                                       */
/*-------------------------------------------------*/
void BootLoader_Clear(void)
{
	gpio_deinit(GPIOA);    
	gpio_deinit(GPIOB);    
}













