| #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(pos, "ÏÂÔØÎļþ¹ý´ó",DELAY_TIME3s); |
| return 1; |
| } |
| } |
| else |
| { |
| if(3 < timeout_trycnt) |
| { |
| disp_hint_info(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(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); |
| } |
| |