標題: 關于STC8A8K64S單片機遠程升級討論 [打印本頁]

作者: 鄧文雄ABC    時間: 2022-1-17 09:36
標題: 關于STC8A8K64S單片機遠程升級討論
這個話題,相信很多朋友都有討論和使用。今天我就說說我自已成功使用的方法。首先單片機需要有這個IAP功能。STC單片機在選型時要注意,不是哪一款都可以,要有IAP功能才行。單片機通過串口或其它通訊方式,接收升級BIN文件,寫入到內部FLASH中,校驗通過,執(zhí)行自動升級過程。我的升級思想及過程如下。
1:出廠程序:(含有IAP功能)程序起址地址為單片機內存的后半部份,例如0X8000,KEIL中需要設置一下

2:為什么要設置成后半部份,這是因為我把前半部份的空間留給后續(xù)需要升級時的程序。
3:因為中斷向量部份在最前面的內存空間,無法改變,因此我的升級方法比較簡單暴力。當接收完校驗通過后,直接改變中斷向量部份空間。
4:貼出代碼:
  1. int main()
  2. {                 
  3.         LEDs_up_ten_flag=0; //流水燈開始
  4.         GPIOInit();          //GPIO+時鐘初始化
  5.         Iap_Isp();          //升級包檢測
  6.         Uart1_Init();                //115200bps@24MHz
  7.         Uart2_Init();                //9600bps@24MHz
  8.         Timer0Init();       //1毫秒@24.000MHz   
  9.         printf("\r\n青橙新能源4G控制充電板V00啟動成功!\r\n");
  10.          LETCAT1_Init(); //模組初始化及登陸服務器
  11.        LB0910_Init(); //0910初始化
  12.          BUZZFlag=1;
  13.         WDT_CONTR = 0x27;//使能看門狗,溢出時間約為5s        
  14.         BeatTimescnt=BeatTimesSet-10;  //快速上線心跳
  15. //          Read_PortTimes(); //讀出端口時間數(shù)據(jù) 云端已實現(xiàn)
  16.           RestTimes=0;
  17.                 LEDs_up_ten_flag=1;//流水燈禁止
  18.                 while(1)
  19.                         {                 
  20.                                         LED_show();
  21.                                         Uart1_drive();                           //串口功能函數(shù),主循環(huán)中調用        
  22.                                         Uart2_drive();                           //串口功能函數(shù),主循環(huán)中調用                                  HeartbeatServer();
  23.                                         WDT_CONTR |= 0x10;    //清看門狗,否則系統(tǒng)復位
  24.                                   if(RestTimes>=120)
  25.                                         {
  26.                                                 RestTimes=0;
  27.                                                 IAP_CONTR |= 0x60;
  28.                                         }
  29.                         }                                
  30. }        


  31. #include "EEPROM.H"

  32. u16 code IAP_Code1[60]={                                                                                                                                                                                       
  33.                                                                                                                 0x0200,0x0400,0x0600,0x0800,0x0A00,0x0C00,0x0E00,  //升級版地址30K
  34.                                                                                                          0x1000,0x1200,0x1400,0x1600,0x1800,0x1A00,0x1C00,0x1E00,
  35.                                                                                                          0x2000,0x2200,0x2400,0x2600,0x2800,0x2A00,0x2C00,0x2E00,
  36.                                                                                                          0x3000,0x3200,0x3400,0x3600,0x3800,0x3A00,0x3C00,0x3E00,
  37.                                                                                                          0x4000,0x4200,0x4400,0x4600,0x4800,0x4A00,0x4C00,0x4E00,
  38.                                                                                                          0x5000,0x5200,0x5400,0x5600,0x5800,0x5A00,0x5C00,0x5E00,
  39.                                                                                                          0x6000,0x6200,0x6400,0x6600,0x6800,0x6A00,0x6C00,0x6E00,
  40.                                                                                                          0x7000,0x7200,0x7400,0x7600,0x7800                                                                                                                                                                                       
  41.                                                                                                 };
  42.          
  43. /*u16 code IAP_Code2[50]={ 0x8000,0x8200,0x8400,0x8600,0x8800,0x8A00,0x8C00,0x8E00,
  44.                                                                                                                 0x9000,0x9200,0x9400,0x9600,0x9800,0x9A00,0x9C00,0x9E00,            //基礎版軟件放置地址        25K                                                                                                                                                                        
  45.                                                                                                                 0xA000,0xA200,0xA400,0xA600,0xA800,0xAA00,0xAC00,0xAE00,
  46.                                                                                                                 0xB000,0xB200,0xB400,0xB600,0xB800,0xBA00,0xBC00,0xBE00,
  47.                                                                                                                 0xC000,0xC200,0xC400,0xC600,0xC800,0xCA00,0xCC00,0xCE00,
  48.                                                                                                                 0xD000,0xD200,0xD400,0xD600,0xD800,0xDA00,0xDC00,0xDE00,
  49.                                                                                                                 0xE000,0xE200,                                                                                         
  50.                                                                                                 };
  51.                                                                                                 */


  52. void IapIdle()                   //關閉 IAP功能 并保護數(shù)據(jù)
  53. {
  54.         IAP_CONTR = 0;          // 關閉 IAP 功能
  55.         IAP_CMD = 0;                         // 清除命令寄存器
  56.         IAP_TRIG = 0;                 // 清除觸發(fā)寄存器
  57.         IAP_ADDRH = 0x80; // 將地址設置到非 IAP 區(qū)域
  58.         IAP_ADDRL = 0;
  59. }

  60. u8 IapRead(u16 addr)                                // 讀數(shù)據(jù)的操作
  61. {
  62.         char dat;
  63.         IAP_CONTR = WT_24M;                                                 // 使能 IAP
  64.         IAP_CMD = 1;                                                                         // 設置 IAP 讀命令
  65.         IAP_ADDRL = addr;                                                 // 設置 IAP 低地址
  66.         IAP_ADDRH = addr >> 8;                                 // 設置 IAP 高地址
  67.         IAP_TRIG = 0x5a;                                                         // 寫觸發(fā)命令 (0x5a)
  68.         IAP_TRIG = 0xa5;                                                         // 寫觸發(fā)命令 (0xa5)
  69.         _nop_();
  70.         dat = IAP_DATA;                                                         // 讀 IAP 數(shù)據(jù)
  71.         IapIdle();                                                                          // 關閉 IAP 功能
  72.         return dat;
  73. }

  74. void IapProgram(u16 addr, u8 dat)                 //寫數(shù)據(jù)操作。
  75. {
  76.         IAP_CONTR = WT_24M;                                   // 使能 IAP
  77.         IAP_CMD = 2;                                                                   // 設置 IAP 寫命令
  78.         IAP_ADDRL = addr;                                          // 設置 IAP 低地址
  79.         IAP_ADDRH = addr >> 8;                         // 設置 IAP 高地址
  80.         IAP_DATA = dat;                                                         // 寫 IAP 數(shù)據(jù)
  81.         IAP_TRIG = 0x5a;                                                         // 寫觸發(fā)命令 (0x5a)
  82.         IAP_TRIG = 0xa5;                                                         // 寫觸發(fā)命令 (0xa5)
  83.         _nop_();
  84.         IapIdle();                                                                          // 關閉 IAP 功能
  85. }

  86. void IapErase(u16 addr)
  87. {
  88.         IAP_CONTR =WT_24M;                  // 使能 IAP
  89.         IAP_CMD = 3;                                                 // 設置 IAP 擦除命令
  90.         IAP_ADDRL = addr;                         // 設置 IAP 低地址
  91.         IAP_ADDRH = addr >> 8;         // 設置 IAP 高地址
  92.         IAP_TRIG = 0x5a;                                 // 寫觸發(fā)命令 (0x5a)
  93.         IAP_TRIG = 0xa5;                                 // 寫觸發(fā)命令 (0xa5)
  94.         _nop_();                                                                                          //
  95.         IapIdle();                                                                          // 關閉 IAP 功能
  96. }


  97. void Iap_Isp()
  98. {

  99.         ///系統(tǒng)切換,當讀到IAPADD地址存有IAP程序中斷向量文件時,寫到0X0000地址中,并重啟到新的
  100.         u8 IapBootCode=0;
  101.         u16 i;

  102.         for(i=0;i<0x0200;i++)
  103.         {         
  104.                 IapBootCode=IapRead[i];                //讀出ISP中斷向量文件塊
  105.                 IapProgram(ISPadd+i, IapBootCode);     //保存在專用區(qū),IAP返回ISP時使用。備用  ISPadd=0xF400
  106.         }
  107.         IapBootCode=IapRead(IAPadd);                                                  //讀出升級文件IAP保存區(qū)起始跳轉數(shù)據(jù),如果有,表示有升級程序,需要寫入起始區(qū),0x0000;寫入后就可以使用升級程序了
  108.         if(IapBootCode==0x02)               
  109.         {                                
  110.                 IapErase(0x0000);                                                          //擦除中斷向量文件塊,準備寫入新的IAP中斷向量
  111.                 for(i=0;i<0x0200;i++)
  112.                 {
  113.                         IapBootCode=IapRead(IAPadd+i);             //讀出IAP中斷向量文件塊,
  114.                         IapProgram(i, IapBootCode);                      //將IAP的中斷向量區(qū)寫入起始位置
  115.                 }        
  116.                 IapErase(IAPadd);                                        //擦除IAP中斷向量文件塊,防止死循環(huán)。
  117.                 IAP_CONTR=0x60;                                          //重啟,將進入IAP程序
  118.         }
  119.         
  120. }


  121.    if(CmpMemory(pbuf,&cmd7[0], sizeof(cmd7)-1))      //升級程序包接收轉存功能程序
  122.          {
  123.                 u16 m=0,n=0,temchar=0;
  124.                   static xdata Buftem[0x0200]={0};  //IAP臨時保存
  125.                  static u8 Hchar=0;    static u8 Lchar=0;          //臨時字高位 //臨時字低位
  126.                 static bit Saveflag=0;                                        // 存儲標志
  127.                   ET0=0;
  128.                   BeatTimescnt=0;                                                          //收到指令,將心跳時間復位        
  129.                         RestTimes=0;                        
  130.                         StorageArray(&IAP_num[0],&Uart1_Rxd_buff[0],15);   //轉化提取升級包序號
  131.                         IAPnum=(u8)atoi(IAP_num);
  132.                          pbuf=&Uart1_Rxd_buff[0];                          //接收指令轉賦值        
  133.                         
  134.                         for(n=0;n<Uart1_bufcnt;n++)
  135.                         {
  136.                                  temchar=*(pbuf+n);
  137.                                 if(temchar=='\"')                      //判斷“號的數(shù)量,
  138.                                         m++;
  139.                                 if(m==19&&temchar!='\"')   //提取數(shù)據(jù)包數(shù)據(jù),存入EEPARM中
  140.                                 {
  141.                                         if(Saveflag==0)
  142.                                         {
  143.                                                 if(temchar>='0'&&temchar<='9') //如果接收到的是數(shù)字, 轉化16進制高位
  144.                                                         { Hchar=temchar-0x30;}      
  145.                                                 else
  146.                                                         { Hchar=temchar-87;}          //如果接收到的是字母, 轉化16進制高位
  147.                                                 Saveflag=!Saveflag;                         //數(shù)據(jù)保存標志取反                                                                                       
  148.                                         }
  149.                                         else
  150.                                         {
  151.                                                 if(temchar>='0'&&temchar<='9') //如果接收到的是數(shù)字, 轉化16進制高位
  152.                                                         { Lchar=temchar-0x30;}      
  153.                                                 else
  154.                                                         { Lchar=temchar-87;}                          //如果接收到的是字母, 轉化16進制高位
  155.                                                         
  156.                                                         Saveflag=!Saveflag;                                         //數(shù)據(jù)保存標志取反                                                                        
  157.                                                         temchar=(Hchar<<4|Lchar);                //高低四位合并                                                        
  158.                                                         if(IAP_cnt<0x0200)
  159.                                                                 {
  160.                                                                         Buftem[IAP_cnt]=temchar;//中斷向量表臨時保存        
  161.                                                                         //SBUF=Buftem[IAP_cnt];Delay1ms();                                                                                
  162.                                                                 }
  163.                                                         else
  164.                                                                 {
  165.                                                                         IapProgram(IAP_Code1[0]+IAP_cnt-0x0200, temchar);     //寫入實際數(shù)據(jù)內存地址        
  166.                                                                         //SBUF=IapRead(IAP_Code1[0]+IAP_cnt-0x0200);Delay1ms();        //讀出        驗證                                                                                       
  167.                                                                 }        
  168.                                                                 IAP_cnt++;
  169.                                                                 IAP_ChecksumAcc+=(u32)temchar;
  170.                                                         
  171.                                                                 if(IAP_cnt==IAPLen&&IAP_ChecksumAcc==IAPChecksum)  //寫入長度和校驗和都相同
  172.                                                                 {        
  173.                                                                
  174.                                                                                 for(m=0;m<0x0200;m++)
  175.                                                                                 {
  176.                                                                                         IapProgram(IAPadd+m, Buftem[m]);     //最后寫入中斷向量文件,防止斷電時無法回到基礎版        
  177.                                                                                         //SBUF=IapRead(IAPadd+m);        //讀出        驗證               
  178.                                                                                         Delay1ms();                                                                                       
  179.                                                                                 }        
  180.                                                                                 // Delay1ms_cont(5000);//
  181.                                                                                 printf("\r\n_num_%bd_len=%u--",IAPnum,IAP_cnt);         Delay1ms_cont(10);
  182.                                                                                 printf("\r\n_num_%bd_ChecksumAcc=%lu--",IAPnum,IAP_ChecksumAcc);         Delay1ms_cont(10);        
  183.                                                                                 printf("\r\n***********The driver upgrade is successful!*************\r\n");        Delay1ms_cont(10);                                                                                                                                                                                                                                                                 //保存相關數(shù)據(jù)再重啟                                                        
  184.                                                                  //   Save_PortTimes(); //保存端口時間數(shù)據(jù)                                                                                                                                                        
  185.                                                                                 IAP_CONTR |= 0x60;                                       
  186.                                                                 }
  187.                                         }                                       
  188.                                 }                        
  189.                         }
  190.                         ET0=1;        
  191.                                 printf("\r\n_num_%bd_len=%u--\r\n",IAPnum,IAP_cnt);         Delay1ms_cont(10);
  192.                           printf("_num_%bd_ChecksumAcc=%lu--\r\n",IAPnum,IAP_ChecksumAcc);         Delay1ms_cont(10);
  193.                           Delay1ms_cont(1500);               
  194.         printf("{\"pc\":\"update\",\"mid\":\"%s\",\"res\":\"1\",\"softid\":\"%s\",\"num\":\"%bd\"}",AT_SIMID,&IAP_softid[0],IAPnum+1);                                                                                                                           
  195.                                 return;        
  196.         }
復制代碼



作者: 雪玉寐影    時間: 2022-6-15 20:56
這個話題值得探討!現(xiàn)在物聯(lián)網(wǎng)時代了,沒有遠程升級功能的產(chǎn)品就低人一等了!
作者: pcbboy    時間: 2022-6-17 08:38
這個話題好,樓主帖子不錯,觀摩一下。
作者: zjczm    時間: 2022-7-1 09:38
這個辦法好。已經(jīng)實現(xiàn)了嗎?
作者: 18680365301    時間: 2023-4-4 16:59
不需要什么IAP功能一樣可以實現(xiàn),任意FLASH芯片都可以
作者: wangjunhuisky    時間: 2023-7-7 14:25
18680365301 發(fā)表于 2023-4-4 16:59
不需要什么IAP功能一樣可以實現(xiàn),任意FLASH芯片都可以

大佬有參考案例嗎,嘗試了好久,升級程序也寫到eeprom里面了,自己寫isp程序就是無法跳轉到用戶區(qū)程序
作者: lzzasd    時間: 2023-7-10 14:13
wangjunhuisky 發(fā)表于 2023-7-7 14:25
大佬有參考案例嗎,嘗試了好久,升級程序也寫到eeprom里面了,自己寫isp程序就是無法跳轉到用戶區(qū)程序

去看下STC的官網(wǎng)上面有介紹   可以使用官方示例進入ISP引導程序    使用2種方式    1種是P3.2低電位進入ISP   一種是內存最后特定區(qū)域寫特殊字符串進入ISP    程序升級完后跳轉到用戶代碼區(qū)域
作者: 鄧文雄ABC    時間: 2024-4-24 15:53
wangjunhuisky 發(fā)表于 2023-7-7 14:25
大佬有參考案例嗎,嘗試了好久,升級程序也寫到eeprom里面了,自己寫isp程序就是無法跳轉到用戶區(qū)程序

我的升級方法和STC官方不一樣
首先最開始本地燒進去的程序是全功能的,當需要升級時,會制行串口接收BIN文件,寫入FLASH中,校驗通過后,直接改寫0X200前面那段程序。
我用這個方法做了好多個案例,都是成功可行的,沒有問題 。

作者: donglw    時間: 2024-4-26 09:49
鄧文雄ABC 發(fā)表于 2024-4-24 15:53
我的升級方法和STC官方不一樣
首先最開始本地燒進去的程序是全功能的,當需要升級時,會制行串口接收BIN ...

不具備普性,這對于程序較小比較實用,程序大了就不能用了。網(wǎng)絡如此發(fā)達,這種方法是否考慮被攻擊的情況。
作者: STC莊偉    時間: 2024-4-26 09:55
人工智能時代:
控制下載數(shù)量,利用ID號控制下載的芯片,如何自動獲得ID號
===最好的辦法是,遠程升級 = 【程序加密后傳輸 + 發(fā)布項目程序】
5.18.5  如何簡單的控制下載次數(shù),
             通過ID號必須對,來限制實際可以下載的MCU,控制數(shù)量
             ———【下載日志 + 發(fā)布項目程序】 高級應用      


如果你的客人,說他自己提前買了芯片,讓你給他程序自己下載,
你要控制下載的芯片數(shù)量,你就先發(fā)布個只有部分功能的程序給他,
然后對方說程序好像不完整,你就請他將下載日志發(fā)你分析:
這樣你就獲得了他實際買了多少MCU和對應MCU的ID號

你再根據(jù)獲得的芯片ID號文件,發(fā)布項目程序給他遠程現(xiàn)場升級,
但ID號不對則不升級,達到了控制升級次數(shù)的目的
作者: wkman    時間: 2024-4-26 17:10
是小容量,局部升級吧??   stc官方的是全擦除全部升級
作者: lzzasd    時間: 2024-4-26 17:42
MCU升級還是有很多問題的    小程序還好   大程序超過內存一半的時候怎么處理??   還要中斷向量偏移等   如果內置了升級功能還好   沒有升級功能編寫難度大點




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1