大理水控初始版本
diff --git a/supwisdom/sp_upgrade.c b/supwisdom/sp_upgrade.c
new file mode 100644
index 0000000..6f2fdb8
--- /dev/null
+++ b/supwisdom/sp_upgrade.c
@@ -0,0 +1,416 @@
+#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);
+}
+