#ifndef __OTA_LOGIC_H__
#define __OTA_LOGIC_H__
#include "basic.h"
void OtaLogic_init(void);
//开始升级OTA
uint8_t OtaLogic_StartOTA(void);
//升级数据 处理
uint8_t OtaLogic_UPdate(char* data);
uint8_t OTALOGIC_UPDATE(int offset, int len, char* data);
/*OTA CRC校验*/
uint8_t OtaLogic_Check(void);
uint8_t OtaWriteReadOtaParamFlag(void);
#endif
/*OTA 数据初始化*/
void OtaLogic_init()
{
memset(&gOTALogic, 0, sizeof(gOTALogic));
gOTALogic.Status = OTA_INIT;
}
//开始升级OTA
uint8_t OtaLogic_StartOTA(void)
{
uint8_t ret = 0;
//u32 currentRunAPPAddr_para2 = 0;
//OTA开始升级
gOTALogic.Status = OTA_START;
gOTALogic.Current_WriteOfset = 0;
memset(gOTALogic.WritePageBuffer, 0 , sizeof(uint8_t) * OTA_WRITE_PAGE_SIZE);
gOTALogic.LastRemaidLen = 0;
memset(gOTALogic.LastRemaidBuffer, 0 , sizeof(uint8_t) * OTA_WRITE_PAGE_SIZE);
printf("开始升级....\r\n");
printf("0.当前是APP版本 程序将保存在 OTA_DOWN_ADDR\r\n");
gOTALogic.OTAPackSaveAddr = OTA_DOWN_ADDR;
printf("0.擦除 OTA保存区 ....\r\n");
STMFLASH_EraseSector(OTA_DOWN_SECRTOR, 1);
HAL_Delay(1000); //延迟500MS
printf("0.擦除成功\r\n");
printf("0.设置保存区 地址[%08x]\r\n", gOTALogic.OTAPackSaveAddr);
gOTALogic.WritePageIndex = 0;
gOTALogic.OtaTcpFlashReadCrc = 0;
gOTALogic.OtaTcpRecvCrc = 0;
ret = 1;
return ret;
}
//升级数据 处理
uint8_t OTALOGIC_UPDATE(int offset, int len, char* data)
{
/*base64 输出buffer大小和长度*/
char outtbuff[256] = {0};
int outlen = 0;
gOTALogic.Status = OTA_DOWLOAD;
int writeLen = 0; //当前写入区长度 下标
int thisTimeWriteLen = 0; //此次处理数据的 总长度
uint8_t ret = 0;
int i = 0;
int j = 0;
u32 writeBuf[128] = {0};
u32 t_wbuf = 0;
//如果下发长度地址 小于当前的已处理地址
if(offset + len <= gOTALogic.Current_WriteOfset)
{
printf("当前数据包已处理,不做处理\r\n");
return 0;
}
base64_decode(data, outtbuff, &outlen);
printf("1.ota decode Len: [%d]\r\n", outlen);
#if IS_DEBUG_OTA_UPDATE
for(i= 0; i<outlen ;i++)
{
printf("%02x ",outtbuff[i]);
if((i+1) %16 ==0 )
printf("\r\n");
}
printf("\r\n");
#endif
/*计算当前当前OTA包的CRC*/
for(i= 0; i < outlen ;i++)
{
//printf("%02x ",outtbuff[i]);
gOTALogic.OtaTcpRecvCrc += outtbuff[i];
// if((i+1) %16 ==0 )
// printf("\r\n");
}
/*拷贝上次剩余的缓存到写入区 */
if(gOTALogic.LastRemaidLen > 0)
{
for(i = 0; i < gOTALogic.LastRemaidLen; i++)
{
/*STEP 1*/
gOTALogic.WritePageBuffer[writeLen] = gOTALogic.LastRemaidBuffer[i];
writeLen ++;
}
//清除上次保存缓存区
gOTALogic.LastRemaidLen = 0;
memset(gOTALogic.LastRemaidBuffer, 0, OTA_WRITE_PAGE_SIZE);
}
/*当前缓存数据 >= 512 个字节长度数据*/
for(i = 0; i < outlen; i++)
{
if(writeLen == OTA_WRITE_PAGE_SIZE)
{
for(j = 0; j <128; j++)
{
t_wbuf = BUILD_UINT32(gOTALogic.WritePageBuffer[4*j], gOTALogic.WritePageBuffer[4*j +1], gOTALogic.WritePageBuffer[4*j +2], gOTALogic.WritePageBuffer[4*j +3]);
writeBuf[j] = t_wbuf;
}
#if IS_DEBUG_OTA_UPDATE
printf("t buf >>>>>\r\n");
for(j = 0; j <128; j++)
{
//t_wbuf = BUILD_UINT32(gOTALogic.WritePageBuffer[4*j], gOTALogic.WritePageBuffer[4*j +1], gOTALogic.WritePageBuffer[4*j +2], gOTALogic.WritePageBuffer[4*j +3]);
printf("[%2x]\r\n", writeBuf[j]);
if((j+1) %16 == 0)
printf("\r\n");
}
#endif
STMFLASH_WriteWord(gOTALogic.OTAPackSaveAddr + (512) *(gOTALogic.WritePageIndex), writeBuf, OTA_WRITE_PAGE_SIZE/4);
gOTALogic.WritePageIndex++;
printf("1.#Write[%d] Pack Data To flash!#\r\n", gOTALogic.WritePageIndex);
//如果写入,则清除写入区的缓存
writeLen = 0;
memset(gOTALogic.WritePageBuffer, 0, OTA_WRITE_PAGE_SIZE);
}
/*STEP 2*/
gOTALogic.WritePageBuffer[writeLen] = outtbuff[i]; //拷贝缓存区到 写入区
writeLen ++;
gOTALogic.Current_WriteOfset ++; //接收缓存数据总长度
thisTimeWriteLen ++;
}
//保存剩余未写入区域
gOTALogic.LastRemaidLen = writeLen; //记录此次的剩余的长度
memcpy(gOTALogic.LastRemaidBuffer, gOTALogic.WritePageBuffer, writeLen);
printf("1.Recv [%d] bytes. from clound. Write [%d]Page. size:[%d]bytes. Remind [%d] bytes not Write.", \
gOTALogic.Current_WriteOfset, gOTALogic.WritePageIndex, gOTALogic.WritePageIndex * 512, gOTALogic.LastRemaidLen);
ret = 1;
return ret;
}
/*升级包校验*/
uint8_t OtaLogic_Check(void)
{
uint8_t ret =0;
int writeLen = 0;
int i =0;
uint8_t ReadBuf [512] = {0};
int j = 0;
u32 writeBuf[128] = {0};
u32 t_wbuf = 0;
int readTimers = 0;
int readOffset = 0;
gOTALogic.Status = OTA_CHECK;
u32 isHaveOTApack_para1 = 0;
//u32 currentRunAPPAddr_para2 = 0;
u32 LastcurrentRunAPPAddr_para2 = 0;
u32 currentOtaPackAddr_para3 = 0;
//处理最后剩余的OTA数据长度
if(gOTALogic.LastRemaidLen > 0)
{
printf("1.Write Last Pack Len to Flash:[%d]\r\n", gOTALogic.LastRemaidLen);
for(i = 0; i < gOTALogic.LastRemaidLen; i++)
{
gOTALogic.WritePageBuffer[writeLen] = gOTALogic.LastRemaidBuffer[i];
//gOTALogic.Current_WriteOfset ++;
writeLen ++;
}
//清除上次保存缓存区
for(j = 0; j <128; j++)
{
t_wbuf = BUILD_UINT32(gOTALogic.WritePageBuffer[4*j], gOTALogic.WritePageBuffer[4*j +1], gOTALogic.WritePageBuffer[4*j +2], gOTALogic.WritePageBuffer[4*j +3]);
writeBuf[j] = t_wbuf;
}
#if IS_DEBUG_OTA_UPDATE
printf("write last >>>>>\r\n");
for(j = 0; j < 128; j++)
{
printf("%08x ", writeBuf[j] );
if((j+1) %16 == 0)
printf("\r\n");
}
#endif
STMFLASH_WriteWord(gOTALogic.OTAPackSaveAddr + (512) *(gOTALogic.WritePageIndex), writeBuf, gOTALogic.LastRemaidLen/4);
memset(gOTALogic.WritePageBuffer, 0, OTA_WRITE_PAGE_SIZE);
}
/*计算Flash CRC*/
readTimers = gDeviceInfo.LastCaculatOTAPack/512;
readOffset = gDeviceInfo.LastCaculatOTAPack % 512;
printf("2.CaCulate [%d] Pack Crc From Flash...\r\n", readTimers);
//读取并计算 写入数据 包的长度CRC
for(j = 0; j< readTimers; j++) {
FLASH_ReadByte(gOTALogic.OTAPackSaveAddr +j*512, ReadBuf, 512);
for(i = 0; i < 512; i++) {
gOTALogic.OtaTcpFlashReadCrc += ReadBuf[i];
}
}
#if IS_DEBUG_OTA_UPDATE
for(j = 0; j< readTimers; j++) {
//if(j<3)
printf("pack [%d] check\r\n", j);
FLASH_ReadByte(gOTALogic.OTAPackSaveAddr +j*512, ReadBuf, 512);
for(i = 0; i < 512; i++) {
//gOTALogic.OtaTcpFlashReadCrc += ReadBuf[i];
printf("%02x ", ReadBuf[i]);
if((i+1)%16 ==0)
printf("\r\n");
}
printf("\r\n");
}
#endif
printf("2.CaCulate [%d] Len Crc From Last Pack ...\r\n", readOffset);
//读取并计算 写入最后一包的长度CRC
FLASH_ReadByte(gOTALogic.OTAPackSaveAddr +j*512, ReadBuf, readOffset);
for(i = 0; i < readOffset; i++) {
gOTALogic.OtaTcpFlashReadCrc += ReadBuf[i];
}
#if IS_DEBUG_OTA_UPDATE
FLASH_ReadByte(gOTALogic.OTAPackSaveAddr +j*512, ReadBuf, readOffset);
for(i = 0; i < readOffset; i++) {
printf("%02x ", ReadBuf[i]);
if((i+1)%16 ==0)
printf("\r\n");
}
#endif
/*计算平台下发接收的crc和 读取保存之后的CRC数据*/
printf("2.Recv from Clound:[0x%x].\r\n", gOTALogic.OtaTcpRecvCrc);
printf("2.Flash Read Crc :[0x%x] VS ", gOTALogic.OtaTcpFlashReadCrc);
/*计算平台协议包里面的总长度*/
printf("2.Caculate Sum Len from Clound: [%d].\r\n", gDeviceInfo.LastCaculatOTAPack);
/*设备接收的数据总长度*/
printf("2.Sum Recv [%d] Len From Clound.\r\n", gOTALogic.Current_WriteOfset);
/*写入flash的数据总长度*/
printf("2.Have Write [%d] bytes To Flash...\r\n", gOTALogic.LastRemaidLen + gOTALogic.WritePageIndex*512);
gOTALogic.LastRemaidLen = 0;
memset(gOTALogic.LastRemaidBuffer, 0, OTA_WRITE_PAGE_SIZE);
gOTALogic.WritePageIndex = 0;
gOTALogic.Current_WriteOfset = 0;
gOTALogic.LastRemaidLen = 0;
//校验 CRC //和检验
if(gOTALogic.OtaTcpFlashReadCrc == gOTALogic.OtaTcpRecvCrc)
{
ret = 1;
gOTALogic.Status = OTA_SUCCESSED;
printf("3.恭喜你.软件升级成功!\r\n");
#if 1
printf("3.开始写入bootloader参数...\r\n");
//printf("------- ota param read-------------\r\n");
STMFLASH_ReadWord(OTA_PARM_1_ADDR, &isHaveOTApack_para1, 1);
//printf("读取是否有升级包标识 = [%08x]\r\n", isHaveOTApack_para1);
HAL_Delay(10);
STMFLASH_ReadWord(OTA_PARM_2_ADDR, &LastcurrentRunAPPAddr_para2, 1);
//printf("读取当前运行包地址 = [%08x]\r\n", LastcurrentRunAPPAddr_para2);
/*此处神秘代码.防止写不进去,多写几次--- 擦除OTA参数地址*/
OtaWriteReadOtaParamFlag(); /*读-擦-写*/
OtaWriteReadOtaParamFlag(); /*读-擦-写*/
OtaWriteReadOtaParamFlag(); /*读-擦-写*/
OtaWriteReadOtaParamFlag(); /*读-擦-写*/
if (OTA_PACK_USER_VERSION == 0){ //当前是APP版本 /*读-擦-写*/
printf("3.当前是APP版本\r\n");
isHaveOTApack_para1 = 0x01; //写入OTA升级包标识
STMFLASH_WriteWord(OTA_PARM_1_ADDR, &isHaveOTApack_para1, 1);
printf("3.写入OTA参数1 [%d]\r\n", isHaveOTApack_para1);
HAL_Delay(50);
printf("------- ota param write para3 -----------\r\n");
currentOtaPackAddr_para3 = OTA_DOWN_ADDR; //写入OTA升级地址
printf("3.写入OTA参数3 [0x%08x]\r\n", currentOtaPackAddr_para3);
STMFLASH_WriteWord(OTA_PARM_3_ADDR, ¤tOtaPackAddr_para3, 1);
HAL_Delay(50);
} else {
printf("3.当前是 OTA 版本\r\n");
isHaveOTApack_para1 = 0x02; //写入OTA升级包标识
STMFLASH_WriteWord(OTA_PARM_1_ADDR, &isHaveOTApack_para1, 1);
printf("3.写入OTA参数1 [%d]\r\n", isHaveOTApack_para1);
HAL_Delay(50);
printf("------- ota param write para3 -----------\r\n");
currentOtaPackAddr_para3 = APP1_RUN_ADDR;
printf("3.写入OTA参数3 [0x%08x]\r\n", currentOtaPackAddr_para3);
STMFLASH_WriteWord(OTA_PARM_3_ADDR, ¤tOtaPackAddr_para3, 1);
HAL_Delay(50);
}
printf("------- 3.参数检查读写 -------------\r\n");
STMFLASH_ReadWord(OTA_PARM_1_ADDR, &isHaveOTApack_para1, 1);
printf("3.读取是否有升级包 标识ota参数1 = [%08x]\r\n", isHaveOTApack_para1);
HAL_Delay(10);
STMFLASH_ReadWord(OTA_PARM_3_ADDR, ¤tOtaPackAddr_para3, 1);
printf("3.读取当前运行包地址 ota参数3 = [%08x]\r\n", currentOtaPackAddr_para3);
#endif
printf("3.写入成功...重启设备\r\n");
//软件重启
HAL_Delay(100);
__HAL_RCC_PWR_CLK_DISABLE();
HAL_RCC_DeInit();
__set_FAULTMASK(1); //关闭所有中断
__disable_irq();
NVIC_SystemReset(); //软件复位
} else {
ret = 0;
STMFLASH_EraseSector(OTA_PARM_SECRTOR, 1);
gOTALogic.Status = OTA_FAILED;
printf("CRC校验失败. 软件升级失败!\r\n");
}
gOTALogic.OtaTcpFlashReadCrc = 0;
gOTALogic.OtaTcpRecvCrc = 0;
return ret;
}