//=====================================================================
//文件名称：ueupdate.c
//功能概要：终端程序更新构件源文件
//=====================================================================

#include "ueupdate.h"

uint_8 uStartNo;    //用户程序起始扇区号
uint_8 uEndNo;      //用户程序结束扇区号
uint_16 uSectSize;  //MCU扇区大小
uint_8 uSectNo;     //需更新的代码所占扇区数
uint_16 uFrameNum;  //总帧数
uint_16 uCurFrame;  //当前接收帧号
uint_8 uStyle;      //更新方式，0：整体替换更新；1：整体保留更新；2：增量保留更新
uint_8 uCheck[32];  //帧接收状态数组，每一位表示一帧接收状态，一共可表示32*8（256）个帧状态
uint_8 uCheckFlag;  //更新检查标志，必须检查过后才能进行更新操作
uint_8 uUpdateFlag; //更新接收标志，0：更新接收操作成功；其他：更新接收操作失败

//========================内部函数声明处=====================================
uint_8 ueupdate_replaceRecv(uint_8 *buf,uint_16 len);
uint_8 ueupdate_reserveRecv(uint_8 *buf,uint_16 len);
void flagSet(uint_8 *flagBuf,uint_16 flag);
uint_8 flagGet(uint_8 *flagBuf,uint_16 flag);
uint_8 ueupdate_update();
//======================================================================

//======================================================================
//函数名称：ueupdate_init
//函数参数：startSector：用户程序起始扇区号；endSector：用户程序结束扇区号+1；
//       sectSize：芯片扇区大小
//函数返回：无
//功能概要：实现终端程序更新功能初始化，并设置用户程序起始和结束扇区号
//       flash模块的初始化和帧标志初始化
//======================================================================
void ueupdate_init(uint_8 startSector,uint_8 endSector,uint_16 sectSize)
{
	//（1）变量声明
	uint_8 i;

	//（2）初始化文件级全局变量
	uStartNo = startSector;  //设置用户程序起始扇区
	uEndNo = endSector;      //设置用户程序结束扇区
	uSectSize = sectSize;    //设置芯片扇区大小
	uFrameNum = 0;           //初始化总帧数为0
	uCurFrame = 0;           //初始化当前接收帧号为0
	for(i = 0;i < sizeof(uCheck);i++)
		uCheck[i] = 0;       //接收帧标志初始化为0
	uCheckFlag = 0;          //初始化更新检查标志为0

	//（3）初始化外设模块
	flash_init();
}

//======================================================================
//函数名称：ueupdate_reinit
//函数参数：buf:接收到的更新数据;len:接收到的更新数据长度
//函数返回：
//       1：开始整体替换更新；
//       4：丢帧；
//功能概要：根据开始更新数据帧，重新初始化Ueupdate构件。该函数仅用于整体替换更新情况，因为从User程序
//       跳回BIOS程序，ueupdate构件的初始状态未能保留，需要重新初始化更新状态变量。
//======================================================================
uint_8 ueupdate_reinit(uint_8 *buf,uint_16 len)
{
	//（1）变量声明
	uint_8 i;
	uint_8 rv;
	uint_8 flag;
	uint_32 codeSize;

	rv = 0;
	//（2）解析更新数据
	//（2.1）接收到更新开始帧数据
	if(buf[0] == 0)
	{
		if(len == sizeof(struct startData))  //数据长度满足更新开始帧
		{
			//重新初始化接收帧标志为0
			for(i = 0;i < sizeof(uCheck);i++)
				uCheck[i] = 0;
			//获取更新开始帧数据
			uStyle = ((struct startData *)buf)->style;
			uFrameNum = ((struct startData *)buf)->frameNum;
			uCurFrame = ((struct startData *)buf)->curFrame;
			codeSize = ((struct startData *)buf)->codeSize;
			//计算更新代码所占的扇区数
			if(codeSize%uSectSize == 0)
				uSectNo = codeSize/uSectSize;
			else
				uSectNo = codeSize/uSectSize+1;
			//根据更新方式的不同进行不同操作
			if(uStyle == 0)
			{
				rv = 1;  //开始整体替换更新
			}
			//修改当前帧接收状态
			flagSet(uCheck,uCurFrame);
		}
	}
	else
	{
		rv = 4;  //反馈帧数据丢失状态
	}
	uUpdateFlag = rv;  //用于提示更新返回
	return rv;
}

//======================================================================
//函数名称：ueupdate_recv
//函数参数：buf:接收到的更新数据;len:接收到的更新数据长度
//函数返回：0：接收并执行更新操作成功；
//       1：开始整体替换更新；
//       2：开始保留更新（保留整体更新、保留增量更新）；
//       3：更新中断，通知上位机重新开始；
//       4：丢帧；
//       5：接收数据帧标识错误；
//       6：替换更新操作成功；
//       7：保留更新操作成功；
//功能概要：接收并解析更新数据，并进行相应的操作，包括更新开始、更新复制、更新插入、更新检查、更新命令
//======================================================================
uint_8 ueupdate_recv(uint_8 *buf,uint_16 len)
{
	//（1）变量声明
	uint_8 i;
	uint_8 rv;
	uint_8 flag;
	uint_32 codeSize;

	rv = 0;
	//（2）解析更新数据
	//（2.1）接收到更新开始帧数据
	if(buf[0] == 0)
	{
		if(len == sizeof(struct startData))  //数据长度满足更新开始帧
		{
			//重新初始化接收帧标志为0
			for(i = 0;i < sizeof(uCheck);i++)
				uCheck[i] = 0;
			//获取更新开始帧数据
			uStyle = ((struct startData *)buf)->style;
			uFrameNum = ((struct startData *)buf)->frameNum;
			uCurFrame = ((struct startData *)buf)->curFrame;
			codeSize = ((struct startData *)buf)->codeSize;
			//计算更新代码所占的扇区数
			if(codeSize%uSectSize == 0)
				uSectNo = codeSize/uSectSize;
			else
				uSectNo = codeSize/uSectSize+1;
			//根据更新方式的不同进行不同操作
			if(uStyle == 0)
			{
				//整体替换更新，直接将User程序擦除后写入
				for(i = uStartNo;i < (uStartNo+uSectNo);i++)
					flash_erase(i);
				rv = 1;  //开始整体替换更新
			}
			else
			{
				//保留更新，擦除User程序之后的扇区，更新成功后整体覆盖
				for(i = uEndNo+1;i < (uEndNo+uSectNo+1);i++)
					flash_erase(i);
				rv = 2;  //开始保留更新（保留整体更新、保留增量更新）
			}
			//修改当前帧接收状态
			flagSet(uCheck,uCurFrame);
		}
	}
	//（2.2）接收到其他更新数据（更新复制帧、更新插入帧 、更新检查帧、更新命令帧）
	else
	{
		//根据更新方式的不同进行不同操作
		if(uStyle == 0)  //整体替换更新
		{
			flag = ueupdate_replaceRecv(buf,len);
			//构造返回值，供应用层判断
			switch(flag)
			{
			case 0: rv = 0;break;  //当前更新操作成功
			case 1: rv = 3;break;  //更新中断，需通知上位机重新开始
			case 2: rv = 4;break;  //丢帧
			case 3: rv = 6;break;  //替换更新操作成功
			case 4: rv = 5;break;  //接收数据帧标识错误
			}
		}
		else  //保留更新
		{
			flag = ueupdate_reserveRecv(buf,len);
			//构造返回值，供应用层判断
			switch(flag)
			{
			case 0: rv = 0;break;  //当前更新操作成功
			case 1: rv = 3;break;  //更新中断，需通知上位机重新开始
			case 2: rv = 4;break;  //丢帧
			case 3: rv = 7;break;  //保留更新操作成功
			case 4: rv = 5;break;  //接收数据帧标识错误
			}
		}
	}

	uUpdateFlag = rv;  //用于提示更新返回
	return rv;
}

//======================================================================
//函数名称：ueupdate_replaceRecv
//函数参数：buf:接收到的更新数据;len:接收到的更新数据长度
//函数返回：0：接收并执行替换更新操作成功；
//       1：更新中断，需通知上位机重新开始；
//       2：丢帧；
//       3：代码替换更新完毕；
//       4：帧标识错误；
//功能概要：接收更新数据并进行整体替换更新操作，包括更新插入、更新检查、更新命令
//======================================================================
uint_8 ueupdate_replaceRecv(uint_8 *buf,uint_16 len)
{
	//（1）变量声明
	uint_8 i;
	uint_8 rv;
	uint_8 segNum;
	uint_32 insertTo;
	uint_16 insertLen;
	uint_16 insertCurLen;
	uint_8 *iData;

	rv = 0;
	//（2）根据帧标识来进行更新操作
	switch(buf[0])
	{
	case 0:  //更新开始帧
		//本函数无需进行更新开始帧操作
		break;
	case 1:  //更新复制帧
		//替换更新无更新复制帧
		break;
	case 2:  //更新插入帧
		if(len == sizeof(struct insertData))  //数据长度满足更新插入帧
		{
			//获取更新插入帧数据
			uCurFrame = ((struct insertData *)buf)->curFrame;
			segNum = ((struct insertData *)buf)->segNum;
			//更新中断，通知上位机重新开始
			if(uFrameNum == 0 || uCurFrame >= uFrameNum)
			{
				rv = 1;
				goto ueupdate_replaceRecv_EXIT;
			}
			//进行代码插入操作
			insertCurLen = 0;
			for(i = 0;i < segNum;i++)
			{
				insertTo = ((struct insertData *)buf)->addInfo[i];  //目标地址
				insertLen = ((struct insertData *)buf)->lenInfo[i];   //复制数据长度
				iData = ((struct insertData *)buf)->data + insertCurLen;        //插入数据
				//插入数据
				flash_write_physical(insertTo,insertLen,iData);
				insertCurLen += insertLen;
			}
			//修改当前帧接收状态
			flagSet(uCheck,uCurFrame);
		}
		break;
	case 3:  //更新检查帧
		if(len == sizeof(struct checkData))  //数据长度满足更新检查帧
		{
			//获取更新检查帧数据
			uCurFrame = ((struct checkData *)buf)->curFrame;
			//更新中断，通知上位机重新开始
			if(uFrameNum == 0 || uCurFrame >= uFrameNum)
			{
				rv = 1;
				goto ueupdate_replaceRecv_EXIT;
			}
			//修改当前帧接收状态
			flagSet(uCheck,uCurFrame);
			//检查是否丢帧
			for(i = 0;i < uFrameNum-1;i++)
			{
				if(flagGet(uCheck,i) == 0)  //出现丢帧状况
				{
					rv = 2;
					goto ueupdate_replaceRecv_EXIT;
				}
			}
			//检查过后设置更新检查标志
			uCheckFlag = 1;
		}
		break;
	case 4:  //更新命令帧
		if(len == sizeof(struct updateData))  //数据长度满足更新命令帧
		{
			if(uCheckFlag == 1)  //检查过，可以更新
			{
				rv = 3;
				goto ueupdate_replaceRecv_EXIT;
			}
		}
		break;
	default:  //其他错误帧标识
		rv = 4;
		goto ueupdate_replaceRecv_EXIT;
	}

	ueupdate_replaceRecv_EXIT:
	return rv ;
}

//======================================================================
//函数名称：ueupdate_reserveRecv
//函数参数：buf:接收到的更新数据;len:接收到的更新数据长度
//函数返回：0：接收并执行保留更新操作成功；
//       1：更新中断，需通知上位机重新开始；
//       2：丢帧；
//       3：代码保留更新完毕；
//       4：帧标识错误；
//功能概要：接收更新数据并进行保留更新操作，包括更新复制、更新插入、更新检查、更新命令
//======================================================================
uint_8 ueupdate_reserveRecv(uint_8 *buf,uint_16 len)
{
	//（1）变量声明
	uint_8 i;
	uint_8 rv;
	uint_8 segNum;
	uint_32 copyFrom;
	uint_32 copyTo;
	uint_16 copyLen;
	uint_8 cData[512];
	uint_32 insertTo;
	uint_16 insertLen;
	uint_16 insertCurLen;
	uint_8 *iData;

	rv = 0;
	//（2）根据帧标识来进行更新操作
	switch(buf[0])
	{
	case 0:  //更新开始帧
		//本函数无需进行更新开始帧操作
		break;
	case 1:  //更新复制帧
		if(len == sizeof(struct copyData))  //数据长度满足更新复制帧
		{
			//获取更新复制帧数据
			uCurFrame = ((struct copyData *)buf)->curFrame;
			segNum = ((struct copyData *)buf)->segNum;
			//更新中断，通知上位机重新开始
			if(uFrameNum == 0 || uCurFrame >= uFrameNum)
			{
				rv = 1;
				goto ueupdate_reserveRecv_EXIT;
			}

			//进行代码复制操作
			for(i = 0;i < segNum;i++)
			{
				copyFrom = ((struct copyData *)buf)->addInfo[i*2];  //源地址
				copyTo = ((struct copyData *)buf)->addInfo[i*2+1];  //目标地址
				copyLen = ((struct copyData *)buf)->lenInfo[i];     //复制数据长度
				//保留更新，目标地址需进行一定的地址偏移
				copyTo += (uEndNo-uStartNo+1)*uSectSize;
				//分块复制数据，每块最多512字节
				while(copyLen)
				{
					if(copyLen > 512)  //当前复制长度大于512，仅复制512字节
					{
						flash_read_physical(cData,copyFrom,512);
						flash_write_physical(copyTo,512,cData);
						copyFrom += 512;
						copyTo += 512;
						copyLen -= 512;
					}
					else  //当前复制长度小于512，全部复制
					{
						flash_read_physical(cData,copyFrom,copyLen);
						flash_write_physical(copyTo,copyLen,cData);
						copyLen = 0;
					}
				}
			}
			//修改当前帧接收状态
			flagSet(uCheck,uCurFrame);
		}
		break;
	case 2:  //更新插入帧
		if(len == sizeof(struct insertData))  //数据长度满足更新插入帧
		{
			//获取更新插入帧数据
			uCurFrame = ((struct insertData *)buf)->curFrame;
			segNum = ((struct insertData *)buf)->segNum;
			//更新中断，通知上位机重新开始
			if(uFrameNum == 0 || uCurFrame >= uFrameNum)
			{
				rv = 1;
				goto ueupdate_reserveRecv_EXIT;
			}
			//进行代码插入操作
			insertCurLen = 0;
			for(i = 0;i < segNum;i++)
			{
				insertTo = ((struct insertData *)buf)->addInfo[i];  //目标地址
				insertLen = ((struct insertData *)buf)->lenInfo[i];   //复制数据长度
				iData = ((struct insertData *)buf)->data + insertCurLen;        //插入数据
				//保留更新，目标地址需进行一定的地址偏移
				insertTo += (uEndNo-uStartNo+1)*uSectSize;
				//插入数据
				flash_write_physical(insertTo,insertLen,iData);
				insertCurLen += insertLen;
			}
			//修改当前帧接收状态
			flagSet(uCheck,uCurFrame);
		}
		break;
	case 3:  //更新检查帧
		if(len == sizeof(struct checkData))  //数据长度满足更新检查帧
		{
			//获取更新检查帧数据
			uCurFrame = ((struct checkData *)buf)->curFrame;
			//更新中断，通知上位机重新开始
			if(uFrameNum == 0 || uCurFrame >= uFrameNum)
			{
				rv = 1;
				goto ueupdate_reserveRecv_EXIT;
			}
			//修改当前帧接收状态
			flagSet(uCheck,uCurFrame);
			//检查是否丢帧
			for(i = 0;i < uFrameNum-1;i++)
			{
				if(flagGet(uCheck,i) == 0)  //出现丢帧状况
				{
					rv = 2;
					goto ueupdate_reserveRecv_EXIT;
				}
			}
			//检查过后设置更新检查标志
			uCheckFlag = 1;
		}
		break;
	case 4:  //更新命令帧
		if(len == sizeof(struct updateData))  //数据长度满足更新命令帧
		{
			if(uCheckFlag == 1)  //检查过，可以更新
			{
				rv = 3;
				ueupdate_update();
				goto ueupdate_reserveRecv_EXIT;
			}
		}
		break;
	default:  //其他错误帧标识
		rv = 4;
		goto ueupdate_reserveRecv_EXIT;
	}

	ueupdate_reserveRecv_EXIT:
	return rv;
}

//======================================================================
//函数名称：ueupdate_recv
//函数参数：buf:接收到的更新数据;len:接收到的更新数据长度
//函数返回：0：接收并执行更新操作（部分）成功；1：代码更新完毕
//       2：帧标识错误；3：丢帧；4：更新中断，需重新更新
//功能概要：接收并解析更新数据，并进行相应的操作，包括更新开始、更新复制、更新插入、更新检查、更新命令
//======================================================================
//uint_8 ueupdate_recv(uint_8 *buf,uint_16 len)
//{
//	//（1）变量声明
//	uint_8 i;
//	uint_8 rv;
//	uint_32 codeSize;
//	uint_8 segNum;
//	uint_32 copyFrom;
//	uint_32 copyTo;
//	uint_16 copyLen;
//	uint_8 cData[512];
//	uint_32 insertTo;
//	uint_16 insertLen;
//	uint_16 insertCurLen;
//	uint_8 *iData;
//
//	rv = 0;
//	//（2）根据帧标识来进行更新操作
//	switch(buf[0])
//	{
//	case 0:  //更新开始帧
//		if(len == sizeof(struct startData))  //数据长度满足更新开始帧
//		{
//			//重新初始化接收帧标志为0
//			for(i = 0;i < sizeof(uCheck);i++)
//				uCheck[i] = 0;
//			//获取更新开始帧数据
//			uFrameNum = ((struct startData *)buf)->frameNum;
//			uCurFrame = ((struct startData *)buf)->curFrame;
//			codeSize = ((struct startData *)buf)->codeSize;
//			//计算更新代码所占的扇区数
//			if(codeSize%uSectSize == 0)
//				uSectNo = codeSize/uSectSize;
//			else
//				uSectNo = codeSize/uSectSize+1;
//			//擦除flash指定区域用于存放更新代码
//			for(i = uEndNo+1;i < (uEndNo+uSectNo+1);i++)
//				flash_erase(i);
//			//修改当前帧接收状态
//			flagSet(uCheck,uCurFrame);
//		}
//		break;
//	case 1:  //更新复制帧
//		if(len == sizeof(struct copyData))  //数据长度满足更新复制帧
//		{
//			//获取更新复制帧数据
//			uCurFrame = ((struct copyData *)buf)->curFrame;
//			segNum = ((struct copyData *)buf)->segNum;
//			//更新中断，通知上位机重新开始
//			if(uFrameNum == 0 || uCurFrame >= uFrameNum)
//			{
//				rv = 4;
//				goto ueupdate_recv_EXIT;
//			}
//
//			//进行代码复制操作
//			for(i = 0;i < segNum;i++)
//			{
//				copyFrom = ((struct copyData *)buf)->addInfo[i*2];  //源地址
//				copyTo = ((struct copyData *)buf)->addInfo[i*2+1];  //目标地址
//				copyLen = ((struct copyData *)buf)->lenInfo[i];     //复制数据长度
//				//目标地址需进行一定的地址偏移
//				copyTo += (uEndNo-uStartNo+1)*uSectSize;
//				//分块复制数据，每块最多512字节
//				while(copyLen)
//				{
//					if(copyLen > 512)  //当前复制长度大于512，仅复制512字节
//					{
//						flash_read_physical(cData,copyFrom,512);
//						flash_write_physical(copyTo,512,cData);
//						copyFrom += 512;
//						copyTo += 512;
//						copyLen -= 512;
//					}
//					else  //当前复制长度小于512，全部复制
//					{
//						flash_read_physical(cData,copyFrom,copyLen);
//						flash_write_physical(copyTo,copyLen,cData);
//						copyLen = 0;
//					}
//				}
//			}
//			//修改当前帧接收状态
//			flagSet(uCheck,uCurFrame);
//		}
//		break;
//	case 2:  //更新插入帧
//		if(len == sizeof(struct insertData))  //数据长度满足更新插入帧
//		{
//			//获取更新插入帧数据
//			uCurFrame = ((struct insertData *)buf)->curFrame;
//			segNum = ((struct insertData *)buf)->segNum;
//			//更新中断，通知上位机重新开始
//			if(uFrameNum == 0 || uCurFrame >= uFrameNum)
//			{
//				rv = 4;
//				goto ueupdate_recv_EXIT;
//			}
//			//进行代码插入操作
//			insertCurLen = 0;
//			for(i = 0;i < segNum;i++)
//			{
//				insertTo = ((struct insertData *)buf)->addInfo[i];  //目标地址
//				insertLen = ((struct insertData *)buf)->lenInfo[i];   //复制数据长度
//				iData = ((struct insertData *)buf)->data + insertCurLen;        //插入数据
//				//目标地址需进行一定的地址偏移
//				insertTo += (uEndNo-uStartNo+1)*uSectSize;
//				//插入数据
//				flash_write_physical(insertTo,insertLen,iData);
//				insertCurLen += insertLen;
//			}
//			//修改当前帧接收状态
//			flagSet(uCheck,uCurFrame);
//		}
//		break;
//	case 3:  //更新检查帧
//		if(len == sizeof(struct checkData))  //数据长度满足更新检查帧
//		{
//			//获取更新检查帧数据
//			uCurFrame = ((struct checkData *)buf)->curFrame;
//			//更新中断，通知上位机重新开始
//			if(uFrameNum == 0 || uCurFrame >= uFrameNum)
//			{
//				rv = 4;
//				goto ueupdate_recv_EXIT;
//			}
//			//修改当前帧接收状态
//			flagSet(uCheck,uCurFrame);
//			//检查是否丢帧
//			for(i = 0;i < uFrameNum-1;i++)
//			{
//				if(flagGet(uCheck,i) == 0)  //出现丢帧状况
//				{
//					rv = 3;
//					goto ueupdate_recv_EXIT;
//				}
//			}
//			//检查过后设置更新检查标志
//			uCheckFlag = 1;
//		}
//		break;
//	case 4:  //更新命令帧
//		if(len == sizeof(struct updateData))  //数据长度满足更新命令帧
//		{
//			if(uCheckFlag == 1)  //检查过，可以更新
//			{
//				rv = 1;
//				ueupdate_update();
//				goto ueupdate_recv_EXIT;
//			}
//		}
//		break;
//	default:  //其他错误帧标识
//		rv = 2;
//		goto ueupdate_recv_EXIT;
//	}
//
//	ueupdate_recv_EXIT:
//	uUpdateFlag = rv;  //用于提示更新返回
//	return rv;
//}

//======================================================================
//函数名称：ueupdate_backGet
//函数参数：buf:更新返回数据，len:更新返回数据长度
//函数返回：
//功能概要：解析接收到的数据，对其进行回应，提示上位机更新操作执行状态
//======================================================================
uint_8 ueupdate_backGet(uint_8 *buf,uint_16 *len)
{
	//（1）变量声明
	uint_8 rv;
	struct backData bdata;

	rv = 0;
	//（2）更新返回帧赋值
	bdata.type = 5;
	bdata.curFrame = uCurFrame;
	bdata.flag = uUpdateFlag;

	//（3）返回数据
	*len = sizeof(struct backData);
	memcpy(buf,(uint_8 *)&bdata,*len);

	return rv;
}

//======================================================================
//函数名称：ueupdate_checkGet
//函数参数：buf:更新检查数据，len:更新检查数据长度
//函数返回：
//功能概要：返回更新检查帧数据，提示上位机更新过程中的丢帧状态
//======================================================================
uint_8 ueupdate_checkGet(uint_8 *buf,uint_16 *len)
{
	//（1）变量声明
	uint_8 i;
	uint_8 rv;
	uint_8 loseNum;
	struct checkData cdata;

	rv = 0;
	loseNum = 0;
	//（2）更新检查帧赋值
	cdata.type = 3;
	cdata.curFrame = uCurFrame;
	//遍历帧接收状态数组，查找丢帧数据
	for(i = 0;i < uFrameNum-1;i++)
	{
		if(flagGet(uCheck,i) == 0)  //出现丢帧状况
		{
			cdata.loseFrame[loseNum++] = i;
		}
	}
	cdata.loseNum = loseNum;

	//（3）返回数据
	*len = sizeof(struct checkData);
	memcpy(buf,(uint_8 *)&cdata,*len);

	return rv;
}

//======================================================================
//函数名称：ueupdate_dataJudge
//函数参数：data:接收到的上位机数据，len:待检查的数据长度
//函数返回：0：数据满足更新帧结构；其他：数据不满足更新帧结构
//功能概要：检查传入数据是否满足更新上位机传输过来的数据
//======================================================================
uint_8 ueupdate_dataJudge(uint_8 *data,uint_16 len)
{
	//（1）变量声明
	uint_8 rv;

	rv = 0;  // 默认成功
	//（2）判断数据是否满足更新开始帧
	if(len == sizeof(struct startData) && data[0] == 0)  //是更新开始帧
		goto ueupdate_dataJudge_EXIT;
	//（3）判断数据是否满足更新复制帧
	else if(len == sizeof(struct copyData) && data[0] == 1)  //是更新复制帧
		goto ueupdate_dataJudge_EXIT;
	//（4）判断数据是否满足更新插入帧
	else if(len == sizeof(struct insertData) && data[0] == 2)  //是更新插入帧
		goto ueupdate_dataJudge_EXIT;
	//（5）判断数据是否满足更新检查帧
	else if(len == sizeof(struct checkData) && data[0] == 3)  //是更新检查帧
		goto ueupdate_dataJudge_EXIT;
	//（6）判断数据是否满足更新命令帧
	else if(len == sizeof(struct updateData) && data[0] == 4)  //是更新命令帧
		goto ueupdate_dataJudge_EXIT;
	else
		rv= 1;  //其他情况皆为不满足更新帧数据

ueupdate_dataJudge_EXIT:
	return rv;
}


//内部函数

//======================================================================
//函数名称：ueupdate_update
//函数参数：无
//函数返回：无
//功能概要：将更新代码复制到User程序指定位置，待系统复位
//======================================================================
uint_8 ueupdate_update()
{
	//（1）变量声明
	uint_8 i;
	uint_32 j;
	uint_32 userAddress,updateAddress;
	uint_8 data[512];

	//（2）获取User程序和更新程序首地址
	userAddress = uStartNo*uSectSize;
	updateAddress = (uEndNo+1)*uSectSize;

	//（3）删除User程序
	for(i = uStartNo;i <= uEndNo;i++)
		flash_erase(i);

	//（4）复制flash数据
	for(j = 0;j < uSectNo*(uSectSize/512);j++)  //分块复制，每块512字节
	{
		flash_read_physical(data,updateAddress+j*512,512);
		flash_write_physical(userAddress+j*512,512,data);
	}

//	//（5）系统复位
//	NVIC_SystemReset();

	return 0;
}

//======================================================================
//函数名称：flagSet
//函数参数：flagBuf:标志数据;flag:标志位数
//函数返回：无
//功能概要：按照位的方式设置标志，如flagBuf[0]中的8位分别代表0~7的状态，
//       flagBuf[1]中的8位分别代表8~15的状态，...
//======================================================================
void flagSet(uint_8 *flagBuf,uint_16 flag)
{
	uint_16 i;
	uint_8 j;

	i = flag/8;  //标志所处字节数
	j = flag%8;  //字节内位置

	flagBuf[i] |= (1 << j);  //设置标志位
}

//======================================================================
//函数名称：flagGet
//函数参数：flagBuf:标志数据;flag:标志位数
//函数返回：第flag位的标志状态
//功能概要：获取flagBuf地址开始的第flag位状态
//======================================================================
uint_8 flagGet(uint_8 *flagBuf,uint_16 flag)
{
	uint_16 i;
	uint_8 j;

	i = flag/8;  //标志所处字节数
	j = flag%8;  //字节内位置

	return flagBuf[i] & (1 << j);
}
