#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "string.h"
#include "stmflash.h"
#include "iap.h" 
//////////////////////////////////////////////////////////////////////////////////	 
// 			2023/8/X GHz_ljw
//////////////////////////////////////////////////////////////////////////////////  

iapfun jump2app; 
u32 iapbuf[512]; 	//2K字节缓存  

void iap_ReadBootWriteInfo(struct BootWriteFlashInfoStruct * info)
{
	STMFLASH_Read(FLASH_ADDR_BOOTWRITE_INFO_START,(u32 *)info,sizeof(struct BootWriteFlashInfoStruct)/sizeof(u32));
}
void iap_UpdateBootWriteInfo(struct BootWriteFlashInfoStruct * info)
{
	STMFLASH_Write(FLASH_ADDR_BOOTWRITE_INFO_START,(u32 *)info,sizeof(struct BootWriteFlashInfoStruct)/sizeof(u32));
}

void iap_write_data(u32 appxaddr,u8 *appbuf,u32 appsize)
{
	u32 t;
	u16 i=0;
	u32 temp;
	u32 fwaddr=appxaddr;//当前写入的地址
	u8 *dfu=appbuf;
	for(t=0;t<appsize;t+=4)
	{						   
		temp=(u32)dfu[3]<<24;   
		temp|=(u32)dfu[2]<<16;    
		temp|=(u32)dfu[1]<<8;
		temp|=(u32)dfu[0];	  
		dfu+=4;//偏移4个字节
		iapbuf[i++]=temp;	    
		if(i==512)
		{
			i=0; 
			STMFLASH_Write(fwaddr,iapbuf,512);
			fwaddr+=2048;//偏移2048  512*4=2048
		}
	} 
	if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.  
}
//appxaddr:应用程序的起始地址
//appbuf:应用程序CODE.
//appsize:应用程序大小(字节).
void iap_write_appbin_at_tempArea(u32 receivedBytes,u8 *appbuf,u32 appsize)
{
	 iap_write_data(FLASH_ADDR_UPDATE_TEMP_AREA+receivedBytes,appbuf,appsize);
}
void iap_write_bootbin(u32 receivedBytes,u8 *appbuf,u32 appsize)
{
	 iap_write_data(FLASH_BOOT_ADDR+receivedBytes,appbuf,appsize);
}
//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
{
	if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.
	{ 
		jump2app=(iapfun)*(vu32*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		
		MSR_MSP(*(vu32*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		jump2app();									//跳转到APP.
	}
}		 

//检查固件有效性
int iap_check_appstate()
{
	struct BootWriteFlashInfoStruct bootWriteFlashInfo;
	iap_ReadBootWriteInfo(&bootWriteFlashInfo);
	
	return bootWriteFlashInfo.App_State == FLASH_APP_STATE_OK ? 1 : 0;
}
//清除固件有效标志
void iap_clear_appstate()
{
		struct BootWriteFlashInfoStruct bootWriteFlashInfo;
		iap_ReadBootWriteInfo(&bootWriteFlashInfo);
	
		bootWriteFlashInfo.App_State=0xFFFFFFFF;
	
		iap_UpdateBootWriteInfo(&bootWriteFlashInfo);
		delay_ms(10);
}
//设置固件有效标志
void iap_set_appstate()
{
		struct BootWriteFlashInfoStruct bootWriteFlashInfo;
		iap_ReadBootWriteInfo(&bootWriteFlashInfo);
	
		bootWriteFlashInfo.App_State=FLASH_APP_STATE_OK;

		iap_UpdateBootWriteInfo(&bootWriteFlashInfo);
		delay_ms(10);
}
void iap_WriteBootVersionInfo()
{
		struct BootWriteFlashInfoStruct bootWriteFlashInfo;
		iap_ReadBootWriteInfo(&bootWriteFlashInfo);
		if (bootWriteFlashInfo.BootVersion.Version_MainNo==0xff || bootWriteFlashInfo.BootVersion.Version_SubNo==0xff)
		{
			VersionInfo* versionInfo=GetVersion();
			bootWriteFlashInfo.BootVersion.Version_MainNo=versionInfo->Version_MainNo;
			bootWriteFlashInfo.BootVersion.Version_SubNo=versionInfo->Version_SubNo;
			bootWriteFlashInfo.BootVersion.Version_ModifyNo=versionInfo->Version_ModifyNo;
			bootWriteFlashInfo.BootVersion.Version_Revision_Number=versionInfo->Version_Revision_Number;
			memcpy(bootWriteFlashInfo.BootVersion.Version_Date,versionInfo->Version_Date,Version_DateLength);
			memcpy(bootWriteFlashInfo.BootVersion.Version_ModelName,versionInfo->Version_ModelName,Version_ModelNameMaxLength);
			memcpy(bootWriteFlashInfo.BootVersion.Version_ModifierName,versionInfo->Version_ModifierName,Version_DateLength);
			memcpy(bootWriteFlashInfo.BootVersion.Version_Comment,versionInfo->Version_Comment,Version_Comment_MaxLength);			
			iap_UpdateBootWriteInfo(&bootWriteFlashInfo);
			delay_ms(10);
		}
}





