blob: 6d04a83887ffa460707f24182054af25cbc51410 [file] [log] [blame]
#include "sp_msgpack.h"
#include "sp_flash.h"
#include "sp_util.h"
#include "sp_display.h"
#include "sp_communicate.h"
#include "sp_upgrade.h"
extern uint16 crc_table[];
#pragma pack(push)
#pragma pack(1)
typedef struct
{
uint32 file_size;
uint8 file_crc[2];
uint8 file_md5[16];
} sp_upgrade_info_t;
#pragma pack(pop)
/*
**************************************************************************************************************
* CRC У Ñé
* Ãè Êö: УÑéÒ»´®charÊý¾ÝµÄCRC
*
* Êä Èë: CPU_CHAR *str - ҪУÑéÊý¾ÝµÄÖ¸Õë
* CPU_INT16U size - ҪУÑéÊý¾ÝµÄ³¤¶È
* CPU_INT08U mode - УÑéµÄģʽ
* 1: Ϊ¸Ã´®Êý¾ÝÔö¼ÓCRCУÑé ͬʱ·µ»ØÐ£ÑéµÄCRCÖµ
* 0: ¸Ã´®Êý¾ÝÊÇ·ñͨ¹ýУÑé ·µ»ØÐ£ÑéµÄCRCÖµ
* ·µ »Ø:
*
* ×¢ Òâ:
*
**************************************************************************************************************
*/
//CRCʹÓÃ
typedef struct
{
uint8 L;
uint8 H;
} INT_08BIT_2;
typedef union
{
uint16 Int16Bit;
INT_08BIT_2 Int08Bit;
} INT_16BIT_08BIT;
uint16 AH_CRC_Verify(uint8 str[], uint16 size, uint8 mode)
{
uint32 i;
INT_16BIT_08BIT crc;
INT_16BIT_08BIT y;
crc.Int16Bit = 0;
for(i = 0 ; i < size ; i++)
{
y.Int16Bit = crc_table[ str[ i ] ^ crc.Int08Bit.H ];
y.Int08Bit.H ^= crc.Int08Bit.L;
crc.Int16Bit = y.Int16Bit;
}
if(mode == 1)
{
str[ i++ ] = y.Int08Bit.H ;
str[ i ] = y.Int08Bit.L ;
}
return(crc.Int16Bit);
}
static uint16 update_upgrade_mark(uint32 CheckSum, uint32 size)
{
uint16 ret,i;
uint8 buff[18] = { 0x5a,0x4b,0x3c,0x2d,0x1e,0x0f } ;
//дÉý¼¶Êý¾Ý³É¹¦Ð´ÈëFLASH±ê¼Ç, ºÍУÑéÂë, ÓÐЧ´úÂ볤¶ÈдÈëÊý¾ÝFLASH
memcpy(buff+6, (unsigned char*)&(CheckSum), 4) ; //УÑéºÍ
memcpy(buff+10,(unsigned char*)&(size) ,4) ; //Êý¾Ý³¤¶È
AH_CRC_Verify(buff, 14, 1);
for(i = 0; i<5; i++)
{
ret = sp_flash_erase(DEF_IapMarkAddr);
if(ret)
{
continue;
}
ret = sp_flash_write(DEF_IapMarkAddr, buff, 16);
if(!ret)
{
break;
}
}
if(i >= 5)
{
return 1;
}
return 0;
}
/**********************************************************************************************
º¯ÊýÃû³Æ: U32 APP_IapDataSumCheck( U32 staaddr, U32 len, U08 mode )
º¯Êý×÷ÓÃ: ¶Á³öFLASHÖеÄÊý¾Ý£¬²¢ÐγÉУÑé
º¯ÊýÊäÈë: staaddr - ¿ªÊ¼µØÖ·
len - Êý¾Ý³¤¶È
mode - УÑéģʽ 0 È¡·´ºÍУÑé 1 ÆÕͨºÍУÑé
º¯ÊýÊä³ö: ÎÞ
º¯Êý·µ»ØÖµ: 0 ³É¹¦ ÆäËûʧ°Ü
**********************************************************************************************/
uint32 do_APP_IapDataSumCheck(uint32 staaddr, uint32 len, uint8 mode)
{
uint32 Sum;
uint32 app_len, checksize, size;
uint16 rcode, i;
uint8 buffer[1024];//IAP_MAXLEN
app_len = len;
checksize = 0;
Sum = 0;
while(checksize < app_len)
{
if(len < 1024)
{
size = len;
}
else
{
size = 1024;
}
for(i=0; i<5; i++)
{
rcode = sp_flash_read((staaddr + checksize), buffer, size);
if(!rcode)
{
break;
}
}
if(mode == 0)
{
for(i = 0; i < size; i++)
{
Sum += ((~buffer[i]) & 0xFF); //еÄÊÇÈ¡·´ºÍ
}
}
else
{
for(i = 0; i < size; i++)
{
Sum += buffer[i]; //ÀϵÄÊÇÖ±½ÓºÍ
}
}
checksize += size;
len -= size;
}
return (Sum);
}
static uint8 get_file_info(sp_pos_t* pos, sp_upgrade_info_t* upgradeinfo)
{
uint8 ret;
uint8 size;
char temp[32];
sp_protocol_request_t req;
sp_protocol_response_t resp;
cw_pack_context pack;
cw_unpack_context unpack;
unpack_field_t field;
sp_flash_read(ADDR_UPGRADE_UPINFO,(uint8*)upgradeinfo,sizeof(sp_upgrade_info_t));
/*¶ÁÈ¡Îļþ³¤¶ÈºÍCRC*/
sp_protocol_req_init(&req,SP_CMD_UPGRADE);
sp_pack_init(&pack,req.data,sizeof(req.data));
cw_pack_map_size(&pack,5);
sp_pack_put_bin(&pack,PK_BIN_DEVPHYID, pos->devphyid, sizeof(pos->devphyid));
sp_pack_put_int(&pack,PK_INT_SEQNO ,0xFFFF);
sp_pack_put_str(&pack,PK_STR_DEVTYPE, DEV_TYPE);
sp_pack_put_str(&pack,PK_STR_VERSION, PRO_VERSION);
sp_pack_put_bin(&pack,PK_BIN_SOFT_MD5,upgradeinfo->file_md5,16);
req.datalen += sp_pack_length(&pack);
ret = sp_comm_call(pos, &req, &resp, COMM_WAIT_TIME);
if(!ret)
{
sp_unpack_init(&unpack,resp.data,resp.datalen);
//erase
sp_flash_erase(ADDR_UPGRADE_UPINFO);
size = sp_unpack_map_size(&unpack);
while(size-- > 0)
{
sp_unpack_value(&unpack,&field);
// 4 byte file_length,2 crc
if(IS_KEY(PK_INT_FILESIZE,field.key))
{
upgradeinfo->file_size = (uint32)field.val.intval;
}
else if(IS_KEY(PK_BIN_FILECRC,field.key))
{
if(field.strlen != 2)
{
sprintf(temp,"CRC³¤¶È=%d",field.strlen);
disp_hint_info_two(pos, "Éý¼¶Ê§°Ü",temp,DELAY_TIME3s);
return 1;
}
MEMCPY(upgradeinfo->file_crc,field.val.binval,field.strlen);
}
else if(IS_KEY(PK_BIN_SOFT_MD5,field.key))
{
MEMCPY(upgradeinfo->file_md5,field.val.binval,field.strlen);
}
}
}
else
{
disp_server_errmsg(pos, "Éý¼¶Ê§°Ü",resp.data,resp.datalen);
}
return ret;
}
static uint8 download_file(sp_pos_t* pos)
{
uint8 ret;
uint8 timeout_trycnt = 0;
uint8 sameseq_trycnt = 0;
uint8 data_len = 0;
uint16 seqno = 0;
uint16 resp_seqno = 0;
uint32 offset = 0;
uint8 endflag = 0;
uint8 size;
char temp[32];
uint8 buf[128];
sp_protocol_request_t req;
sp_protocol_response_t resp;
cw_pack_context pack;
cw_unpack_context unpack;
unpack_field_t field;
for(offset = ADDR_UPGRADE_BEGIN; offset < ADDR_UPGRADE_END; offset +=DEF_FLASH_PageSize)
{
sp_flash_erase(offset);
}
offset = 0;
while(1)
{
sp_feed_dog();
sp_protocol_req_init(&req,SP_CMD_UPGRADE);
sp_pack_init(&pack,req.data,sizeof(req.data));
cw_pack_map_size(&pack,2);
sp_pack_put_bin(&pack,PK_BIN_DEVPHYID, pos->devphyid, sizeof(pos->devphyid));
sp_pack_put_int(&pack,PK_INT_SEQNO,seqno);
req.datalen += sp_pack_length(&pack);
ret = sp_comm_call(pos, &req,&resp, COMM_WAIT_TIME);
if(!ret)
{
timeout_trycnt = 0;//success reset
sp_unpack_init(&unpack,resp.data,resp.datalen);
size = sp_unpack_map_size(&unpack);
while(size-- > 0)
{
sp_unpack_value(&unpack,&field);
if(IS_KEY(PK_INT_SEQNO,field.key))
{
resp_seqno = (uint32)field.val.intval;
}
else if(IS_KEY(PK_INT_FLAG,field.key))
{
if(0 == MEMCMP("end",field.val.strval,field.strlen))
{
// ÎļþÏÂÔØÍê³É
endflag = 1;
}
}
else if(IS_KEY(PK_BIN_FILEDATA,field.key))
{
data_len = field.strlen;
if(data_len > sizeof(buf))
{
sprintf(temp,"´íÎ󳤶È=%d",data_len);
disp_hint_info_two(pos, "Éý¼¶Ê§°Ü",temp,DELAY_TIME3s);
return 1;
}
MEMCLEAR(buf,sizeof buf);
MEMCPY(buf,field.val.binval,data_len);
}
}
if(resp_seqno != seqno +1)
{
if(10 < sameseq_trycnt)
{
return 1;
}
++sameseq_trycnt;
continue;
}
sameseq_trycnt = 0;
++seqno;
snprintf(temp,sizeof temp,"seqno = %04d",seqno);
disp_hint_info_two(pos, "ÕýÔÚÉý¼¶...",temp,0);
sp_flash_write(ADDR_UPGRADE_BEGIN+offset,buf,data_len);
if(endflag)
{
return 0;
}
offset += (uint32)data_len;
if(ADDR_UPGRADE_BEGIN + offset >= ADDR_UPGRADE_END)
{
disp_hint_info_two(pos,"Éý¼¶Ê§°Ü", "ÏÂÔØÎļþ¹ý´ó",DELAY_TIME3s);
return 1;
}
}
else
{
if(3 < timeout_trycnt)
{
disp_hint_info_two(pos,"Éý¼¶Ê§°Ü", "ÏÂÔØÎļþ³¬Ê±",DELAY_TIME3s);
return 1;
}
Delay_ms(DELAY_TIME1s);
++timeout_trycnt;
}
}
}
static uint8 check_file_and_upgrade(sp_pos_t* pos, sp_upgrade_info_t* upgradeinfo)
{
uint16 ret;
uint8 crc[2];
uint8 temp_crc[2];
uint8 buf[128];
uint32 sumcrc;
uint32 page_index = 0;
uint32 page_num = (upgradeinfo->file_size-1)/sizeof(buf) + 1;
while(1)
{
if(page_num == page_index +1)
{
sp_flash_read(ADDR_UPGRADE_BEGIN +page_index*sizeof(buf),buf,
sizeof buf);
memcpy(temp_crc,crc,2);
if(upgradeinfo->file_size%sizeof(buf) == 0)
{
sp_protocol_crc_init(buf,sizeof(buf),temp_crc,crc);
}
else
{
sp_protocol_crc_init(buf,upgradeinfo->file_size%sizeof(buf),temp_crc,crc);
}
if(0 == MEMCMP(upgradeinfo->file_crc,crc,2))
{
sp_flash_write(ADDR_UPGRADE_UPINFO,(uint8*)upgradeinfo,sizeof(sp_upgrade_info_t));
sumcrc = do_APP_IapDataSumCheck(ADDR_UPGRADE_BEGIN,upgradeinfo->file_size,0);
/*Éý¼¶ºó,boot »á²Á³ý¸ÃÒ³¼Ç¼ */
//¸üбê־λÖÃλ
ret = update_upgrade_mark(sumcrc,upgradeinfo->file_size);
if(ret)
{
disp_hint_info_two(pos, "Éý¼¶Ê§°Ü","¸üбê־ʧ°Ü",DELAY_TIME2s);
return 1;
}
else
{
disp_hint_info_two(pos, "ÕýÔÚÉý¼¶","ÇëÎð¶Ïµç",DELAY_TIME2s);
sp_reset();
return 0;
}
}
else
{
disp_hint_info_two(pos,"Éý¼¶Ê§°Ü", "ÎļþУÑé´íÎó",DELAY_TIME3s);
return 1;
}
}
else
{
sp_flash_read(ADDR_UPGRADE_BEGIN+page_index*sizeof(buf),buf,sizeof buf);
if(0 == page_index)
{
sp_protocol_crc(buf,sizeof buf,crc);
}
else
{
memcpy(temp_crc,crc,2);
sp_protocol_crc_init(buf,sizeof buf,temp_crc,crc);
}
++page_index;
}
}
}
void sp_manual_upgrade(sp_pos_t* pos)
{
uint8 ret;
sp_upgrade_info_t upgradeinfo;
disp_hint_info_two(pos, "ÕýÔÚÉý¼¶..","Îð¶Ïµç!!",0);
MEMCLEAR(&upgradeinfo,sizeof upgradeinfo);
ret = get_file_info(pos, &upgradeinfo);
if(ret)
{
return;
}
ret = download_file(pos);
if(ret)
{
return;
}
check_file_and_upgrade(pos, &upgradeinfo);
}