#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;       

/**
 * @brief ��strstr�����ҳ��ֽ������е�ָ���ַ�λ��,���û�з���NULL
 * 
 * @param strs �ֽ�����
 * @param str ָ���ַ���
 * @param first �ֽ�����ƫ����
 * @param len �ֽ����鳤��
 * @return char* ָ���ַ���ַ,���û�з���NULL
 */
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;
}

/**
 * @brief �ȴ��������ļ��������ķ�������
 * 
 * @param data �����������ݸ��Ƶ�data������
 * @param timeout ��ʱʱ��
 * @param datalen ��Ҫ���Ƶ������ֽڳ���
 * @return int �ɹ��򷵻ظ��Ƶ��ֽڳ��ȣ�ʧ�ܷ���-1
 */
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);		//��Ҫ��200ms�ӳ�
			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);		//��Ҫ��200ms�ӳ�
			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);    
}