📄 upgrade.cpp
字号:
// Upgrade.cpp: implementation of the CUpgradeFile class.
//
//////////////////////////////////////////////////////////////////////
#include "public.h"
#include "Upgrade.h"
#include "DataPort.h"
extern CDataPort gDataPort;
#include "CrcCode.h"
extern CCrcCode gCrcCode;
unsigned char mBuffer[10240];
extern unsigned short int gSecondTimeout;
extern const unsigned short int gUSecond;
extern void Teststack();
extern unsigned char gArriveAnswerTime;
CUpgradeFile::CUpgradeFile()
{
}
CUpgradeFile::~CUpgradeFile()
{
DELETE(m_ptrSuccPackMark);
}
/////////////////////////////////////////////////////////////
void CUpgradeFile::SendErrorMessagePackage(unsigned char ErrorCode)
{
extern unsigned short int gIntervalTimeout;
unsigned char SendBuffer[12]={0x0,0x07,0x01,0xB9,ErrorCode};
cprintf("\r\n\tSend Error Code %02X ",ErrorCode);
RuningOK();
gDataPort.SendDataPackage(SendBuffer);
gIntervalTimeout=18;while(gIntervalTimeout) ;
gDataPort.SendDataPackage(SendBuffer);
gIntervalTimeout=9;while(gIntervalTimeout) ;
}
//从数据包获得升级数据参数0=OK 1=ERROR
short CUpgradeFile::ReadUpgradeParameter(const unsigned char *ptrData)
{
m_UnSuccFileCount=*(ptrData+0);//最后文件(标识)
m_UprModel=*(ptrData+1);//升级模式 1=单工 2=其他
m_lFileLen=ftonl(ptrData+2);//升级文件长度
m_uPackageSize=ftons(ptrData+6);//升级文件每包大小
m_uPackageCount=ftons(ptrData+8);;//升级包数。
m_lFileCrcCode1=ftonl(ptrData+10);//升级文件最终校验码
m_lFileCrcCode2=ftonl(ptrData+14);//升级文件最终校验码
memcpy(m_strFileName,ptrData+18,64);//升级文件名
m_strFileName[64]=0;
if(m_lFileCrcCode1!=m_lFileCrcCode2
|| m_uPackageSize==0
|| m_uPackageSize%512!=0
|| (m_lFileLen+m_uPackageSize-1)/m_uPackageSize!=m_uPackageCount
|| strlen(m_strFileName)==0)
{
m_lFileLen=m_uPackageSize=m_uPackageCount=0;
m_strFileName[0]=0;
return 1;
}
return 0;
}
short CUpgradeFile::CheckDiskFreeSpace(unsigned long newFileLen)//0=OK 1=不足
{
struct dfree free;
getdfree(getdisk()+1, &free);//获得当前磁盘的基本信息。
//每族字节数.每一文件按簇分配,不足一簇使用一簇
unsigned short BytesPerCluster=free.df_bsec*free.df_sclus;
newFileLen=(newFileLen+BytesPerCluster-1)/BytesPerCluster;//升级文件占有簇数
if(free.df_avail<newFileLen) return 1;
return 0;
}
/////////////////////////////////////////////////////////////
void CUpgradeFile::CreateSuccMarkFile()
{
FILE *fp;
cprintf("\r\n ----Create Succ Mark File \\\\uprade!!.OK----");
fp=fopen(constUpgradeOKFileName,"w");
fprintf(fp,"OK");
fclose(fp);
}
//主动发送连接信息(计算机编号)和上位通信协商,每550毫秒发送一次,等待0xB1协议或等待50秒。
short CUpgradeFile::Operate_SendB0_WaitB1()//发送B0等待连接协商
{
extern unsigned long GetCurComputerNo();
static unsigned long ComputerNo=GetCurComputerNo();
unsigned char SendBuffer[16]={0x0,0x0A,0x01,0xB0};
*(unsigned long*)(SendBuffer+4)=ftonl(ComputerNo);
cprintf("\r\nWait Connect.");
int k=12;
unsigned char ReturnCode;
while(k)
{
RuningOK();
gDataPort.SendDataPackage(SendBuffer);
ReturnCode=gDataPort.ReceiveDataPackage(mBuffer);
if(ReturnCode==0xB1)
{
cprintf("..OK. ");
return 0;
}
else if(ReturnCode==0xB9)
{
cprintf("\r\n...Fail(Recv Stop Command).");
return 1;
}
k--;
cprintf("%u ",k);
}
cprintf("..Fail(Over Time). ");
return 1;
}
//收到B1协商数据,建立文件等等。直到收到B2数据包为止。
short CUpgradeFile::Operate_SendB1_WaitB2()//发送B1等待传输数据
{
unsigned char SendBuffer[12]={0x0,0x07,0x01,0xB1,0xF0};
unsigned char ReturnCode;
if(mBuffer[3]!=0xB1) return 1;
//准备建立升级文件
ReturnCode=Handle_0xB1();
if(ReturnCode) {SendErrorMessagePackage(ReturnCode);return 1;}
DELETE(m_ptrSuccPackMark);
m_ptrSuccPackMark=new char[m_uPackageCount];
if(m_ptrSuccPackMark==NULL){SendErrorMessagePackage(0xF1);return 1;}
memset(m_ptrSuccPackMark,0,m_uPackageCount);
m_SuccPackCount=0;
m_CurRecvFileIndex=0;
//产生wenjianOK,等待发送数据
gDataPort.SendDataPackage(SendBuffer);//发送
gSecondTimeout=60;
while(gSecondTimeout)
{
RuningOK();
ReturnCode=gDataPort.ReceiveDataPackage(mBuffer);
if(ReturnCode==0xB2) return 0;
else if(ReturnCode==0xB9)
{
cprintf("\r\n...Fail(Recv Stop Command).");
return 1;
}
else if(ReturnCode) gDataPort.SendDataPackage(SendBuffer);//发送
else cprintf("+");
}
cprintf("..Fail(Over Time). ");
SendErrorMessagePackage(0xF1);
return 1;
}
//收到数据包回答是否学要需要数据,直到所有数据全部收到。只能接受B2或B9。
short CUpgradeFile::Operate_SendB2_WaitTransDataEND()//发送B2等待传输数据或新协商
{
unsigned char ReturnCode;
HAVE_NEW_DATA:
if(mBuffer[3]==0xB2)//肯定是数据包B2协议。本来是多余,为了防止程序有错
{
Handle_0xB2();
if(m_SuccPackCount==m_uPackageCount) return 0;//升级数据接受完成,等待校验。
Handle_Answer_0xB2();
}
//等待新数据
gSecondTimeout=60;
for(;;)
{
RuningOK();
if(gSecondTimeout==0)
{
cprintf("...Over Time.");
SendErrorMessagePackage(0xF1);
break;
}
ReturnCode=gDataPort.ReceiveDataPackage(mBuffer);
if(ReturnCode==0xB2) goto HAVE_NEW_DATA;
else if(ReturnCode==0xB9)
{
cprintf("\r\n...Fail(Recv Stop Command).");
break;
}
else if(ReturnCode)
{
SendErrorMessagePackage(0xF2);
break;
}
else cprintf("+");
}
return 1;
}
//数据已经接受完成,等待检验文件CRC码,等待新的协商
short CUpgradeFile::Operate_SendTransDataEND_WaitB1()//发送传输数据结束等待新文件协商
{
unsigned char ReturnCode;
//回答数据包
unsigned char SendBuffer[12]={0x0,0x0A,0x01,0xB2};
*(unsigned short *)(SendBuffer+4)=ftons(m_SuccPackCount);//正确包数
*(unsigned short *)(SendBuffer+6)=0L;//需重发包数
//校验文件CRC码。
FCLOSE(ptrFile);
if(CheckFileCrcCode()) //文件校验码错
{
cprintf("\r\nFile CRC Error");
SendErrorMessagePackage(0xF7);
return 1;
}
cprintf("\r\nFile %s Uprgade OK!!!",m_strFileName);
DELETE(m_ptrSuccPackMark);
gDataPort.SendDataPackage(SendBuffer);
cprintf("%4c",'O');
//如果是最后一个文件。
if(m_UnSuccFileCount==0)//最后一文件。
{
CreateSuccMarkFile();
gSecondTimeout=20;
while(gSecondTimeout)
{
ReturnCode=gDataPort.ReceiveDataPackage(mBuffer);
if(ReturnCode==0xB9) break;
else if(ReturnCode)
{
gDataPort.SendDataPackage(SendBuffer);
cprintf("%4c",'O');
}
else cprintf("+");
}
cprintf("\r\nUprgade Succeed!!!");
return 1;
}
gSecondTimeout=60;
for(;;)
{
if(gSecondTimeout==0)
{
cprintf("..Fail(Over Time). ");
SendErrorMessagePackage(0xF1);
break;
}
ReturnCode=gDataPort.ReceiveDataPackage(mBuffer);
if(ReturnCode==0xB1) return 0;
else if(ReturnCode==0xB9)
{
cprintf("\r\n...Fail(Recv Stop Command).");
break;
}
else if(ReturnCode)
{
gDataPort.SendDataPackage(SendBuffer);
cprintf("%4c",'A');
}
else cprintf("+");
}
return 1;
}
void CUpgradeFile::Start()
{
Teststack();
//删除文件 \\uprade!!.OK
unlink(constUpgradeOKFileName); //删除文件uprade!!.OK
m_ptrSuccPackMark=NULL;
m_SuccPackCount=0;
if(Operate_SendB0_WaitB1()) return ;
RuningOK();
for(;;)
{
RuningOK();
if(Operate_SendB1_WaitB2()) return ;//返回数据B2协议,发送B1等待传输数据
if(Operate_SendB2_WaitTransDataEND()) return ;//发送B2等待传输数据结束,
if(Operate_SendTransDataEND_WaitB1()) return;//校验文件CRC,发送传输数据结束等待新文件协商
}
DELETE(m_ptrSuccPackMark);
FCLOSE(ptrFile);
cprintf("\r\n");
}
////////////////////////////////////////////////////////////////////
//F1=错误或人为停止升级、F2=协议(未知)错误
//F3=产生文件错误、F4=升级磁盘空间不够、F5=磁盘读写错误、
unsigned char CUpgradeFile::Handle_0xB1()//返回0=OK,其它=错误码
{
//从0xB1协议数据mBuffer中获得升级参数。
if(ReadUpgradeParameter(mBuffer+4)) return 0xF2;//F2=协议(未知)错误
//产生一个升级空文件
cprintf("\r\n Create Upgrade File %s..",m_strFileName);
cprintf("\r\n(%u)Len %lu,PackageSize %u ,PackCount %u,Name:%s",m_UnSuccFileCount,m_lFileLen, m_uPackageSize,m_uPackageCount,m_strFileName);
if(m_lFileLen==0 ||m_uPackageCount==0)
{
cprintf("\r\n\t!!!FileLen=0,Upgrade Fail!!! ");
return 0xF8;//升级文件,包数不能为0
}
ptrFile=fopen(m_strFileName,"wb");
if(!ptrFile)
{
cprintf("..Error(File Name Error).");
return 0xF3;//F3=产生文件错误
}
RuningOK();
//检查磁盘空间是否够。
if(CheckDiskFreeSpace(m_lFileLen))
{
FCLOSE(ptrFile);
unlink(m_strFileName);
cprintf("..Error(disk Free Space too small).");
return 0xF4;//F4=升级磁盘空间不够
}
cprintf("..OK");
//产生给定大小的磁盘文件
unsigned long k=m_lFileLen;
memset(mBuffer,0,2048);
while(k>=2048)
{
RuningOK();
if(fwrite(mBuffer,2048,1,ptrFile)!=1) goto CREATE_ERROR_END;
k-=2048;
}
if(k) if(fwrite(mBuffer,(unsigned short)k,1,ptrFile)!=1) goto CREATE_ERROR_END;
FCLOSE(ptrFile);
//检验产生文件大小是否成功,并打开读写。
ptrFile=fopen(m_strFileName,"rb+");
if(ptrFile)
{
fseek(ptrFile,0,SEEK_END);
if(ftell(ptrFile)!=(long)m_lFileLen) goto CREATE_ERROR_END;
}
cprintf("\r\n Waiting Transmit File Data(Succ Count): \r\n");
return 0;
CREATE_ERROR_END:
FCLOSE(ptrFile);
unlink(m_strFileName);
cprintf("\r\n...Disk have Error!!!!");
return 0xF5;//F5=磁盘读写错误
}
short CUpgradeFile::Handle_Check_0xB1()//返回0=和上次协商一致,1=不一致
{
const unsigned char *ptrData=mBuffer+4;
if(m_UnSuccFileCount==*(ptrData+0)
&&m_UprModel==*(ptrData+1)
&&m_lFileLen==ftonl(ptrData+2)
&&m_uPackageSize==ftons(ptrData+6)
&&m_uPackageCount==ftons(ptrData+8)
&&m_lFileCrcCode1==ftonl(ptrData+10)
&&m_lFileCrcCode2==ftonl(ptrData+14)
&& stricmp(m_strFileName,(char*)(ptrData+18))==0
) return 0;
return 1;
}
short CUpgradeFile::Handle_0xB2()//0=数据OK 其它=错误。
{
unsigned short int FileDataLen=((mBuffer[0]<<8)|mBuffer[1])-6-2;
unsigned short int FileIndex=((mBuffer[4]<<8)|mBuffer[5]);
unsigned char *ptrFileData=(mBuffer+6);
if(FileIndex>=m_uPackageCount)
{
return 1;
}
else if(FileIndex==m_uPackageCount-1) //最后一包
{
if(m_lFileLen!=(m_uPackageCount-1)*(unsigned long)m_uPackageSize+FileDataLen) return 1;
gArriveAnswerTime=0;
}
else//其他包
{
if(FileDataLen!=m_uPackageSize ) return 1;
}
if(m_ptrSuccPackMark[FileIndex]==0)
{
m_SuccPackCount++;
m_ptrSuccPackMark[FileIndex]=1;
fseek(ptrFile,(long)FileIndex*m_uPackageSize,SEEK_SET);
fwrite(ptrFileData,FileDataLen,1,ptrFile);
cprintf("%4u",m_SuccPackCount);
}
m_CurRecvFileIndex=FileIndex;
return 0;
}
short CUpgradeFile::Handle_Answer_0xB2()//每5秒会一包数据包。单工没收到一包就就回一包
{
short ReSendCount=0;
if(m_SuccPackCount<(m_CurRecvFileIndex+1))//需重发包数
{
unsigned short *ptrReSendIndex=(unsigned short *)(mBuffer+8);
unsigned short int i;
for(i=0;i<=m_CurRecvFileIndex && ReSendCount<16;i++)
{
if(m_ptrSuccPackMark[i]==0)
{
*ptrReSendIndex=ftons(i);
ptrReSendIndex++;
ReSendCount++;
}
}
}
*(unsigned short *)mBuffer=ftons(6+4+ReSendCount*2);//长度
mBuffer[2]=0x01;
mBuffer[3]=0xB2;
*(unsigned short *)(mBuffer+4)=ftons(m_SuccPackCount);//正确包数
*(unsigned short *)(mBuffer+6)=ftons(ReSendCount);//需重发包数
gDataPort.SendDataPackage(mBuffer);
cprintf("%4c",'A');
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////
short CUpgradeFile::CheckFileCrcCode()//0=OK 1=错误
{
unsigned long CrcCode=0;
long k=0;
FILE *fp;
fp=fopen(m_strFileName,"rb");
if(!fp) return 1;
fseek(fp,0,SEEK_END);
if(ftell(fp)!=(long)m_lFileLen) {FCLOSE(fp);return 1;}
fseek(fp,0,SEEK_SET);
for(k=m_lFileLen;k>=2048;k-=2048)
{
RuningOK();
fread(mBuffer,2048,1,fp);
CrcCode=gCrcCode.Crc32Mtt(mBuffer,2048,CrcCode);
}
if(k) fread(mBuffer,(short)k,1,fp);
CrcCode=gCrcCode.Crc32Mtt(mBuffer,k,CrcCode);
FCLOSE(fp);
// cprintf("\r\nCRC=%lX CRc1=%lX CRC2=%lX",CrcCode,m_lFileCrcCode1,m_lFileCrcCode2);
if(CrcCode==m_lFileCrcCode1 && CrcCode==m_lFileCrcCode2) return 0;
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -