找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3414|回复: 11
打印 上一主题 下一主题
收起左侧

关于STC8A8K64S单片机远程升级讨论

  [复制链接]
跳转到指定楼层
楼主
ID:301968 发表于 2022-1-17 09:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这个话题,相信很多朋友都有讨论和使用。今天我就说说我自已成功使用的方法。首先单片机需要有这个IAP功能。STC单片机在选型时要注意,不是哪一款都可以,要有IAP功能才行。单片机通过串口或其它通讯方式,接收升级BIN文件,写入到内部FLASH中,校验通过,执行自动升级过程。我的升级思想及过程如下。
1:出厂程序:(含有IAP功能)程序起址地址为单片机内存的后半部份,例如0X8000,KEIL中需要设置一下

2:为什么要设置成后半部份,这是因为我把前半部份的空间留给后续需要升级时的程序。
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(); //读出端口时间数据 云端已实现
  16.           RestTimes=0;
  17.                 LEDs_up_ten_flag=1;//流水灯禁止
  18.                 while(1)
  19.                         {                 
  20.                                         LED_show();
  21.                                         Uart1_drive();                           //串口功能函数,主循环中调用        
  22.                                         Uart2_drive();                           //串口功能函数,主循环中调用                                  HeartbeatServer();
  23.                                         WDT_CONTR |= 0x10;    //清看门狗,否则系统复位
  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功能 并保护数据
  53. {
  54.         IAP_CONTR = 0;          // 关闭 IAP 功能
  55.         IAP_CMD = 0;                         // 清除命令寄存器
  56.         IAP_TRIG = 0;                 // 清除触发寄存器
  57.         IAP_ADDRH = 0x80; // 将地址设置到非 IAP 区域
  58.         IAP_ADDRL = 0;
  59. }

  60. u8 IapRead(u16 addr)                                // 读数据的操作
  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;                                                         // 写触发命令 (0x5a)
  68.         IAP_TRIG = 0xa5;                                                         // 写触发命令 (0xa5)
  69.         _nop_();
  70.         dat = IAP_DATA;                                                         // 读 IAP 数据
  71.         IapIdle();                                                                          // 关闭 IAP 功能
  72.         return dat;
  73. }

  74. void IapProgram(u16 addr, u8 dat)                 //写数据操作。
  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 数据
  81.         IAP_TRIG = 0x5a;                                                         // 写触发命令 (0x5a)
  82.         IAP_TRIG = 0xa5;                                                         // 写触发命令 (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;                                 // 写触发命令 (0x5a)
  93.         IAP_TRIG = 0xa5;                                 // 写触发命令 (0xa5)
  94.         _nop_();                                                                                          //
  95.         IapIdle();                                                                          // 关闭 IAP 功能
  96. }


  97. void Iap_Isp()
  98. {

  99.         ///系统切换,当读到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);     //保存在专用区,IAP返回ISP时使用。备用  ISPadd=0xF400
  106.         }
  107.         IapBootCode=IapRead(IAPadd);                                                  //读出升级文件IAP保存区起始跳转数据,如果有,表示有升级程序,需要写入起始区,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的中断向量区写入起始位置
  115.                 }        
  116.                 IapErase(IAPadd);                                        //擦除IAP中断向量文件块,防止死循环。
  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=='\"')                      //判断“号的数量,
  138.                                         m++;
  139.                                 if(m==19&&temchar!='\"')   //提取数据包数据,存入EEPARM中
  140.                                 {
  141.                                         if(Saveflag==0)
  142.                                         {
  143.                                                 if(temchar>='0'&&temchar<='9') //如果接收到的是数字, 转化16进制高位
  144.                                                         { Hchar=temchar-0x30;}      
  145.                                                 else
  146.                                                         { Hchar=temchar-87;}          //如果接收到的是字母, 转化16进制高位
  147.                                                 Saveflag=!Saveflag;                         //数据保存标志取反                                                                                       
  148.                                         }
  149.                                         else
  150.                                         {
  151.                                                 if(temchar>='0'&&temchar<='9') //如果接收到的是数字, 转化16进制高位
  152.                                                         { Lchar=temchar-0x30;}      
  153.                                                 else
  154.                                                         { Lchar=temchar-87;}                          //如果接收到的是字母, 转化16进制高位
  155.                                                         
  156.                                                         Saveflag=!Saveflag;                                         //数据保存标志取反                                                                        
  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);     //写入实际数据内存地址        
  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);                                                                                                                                                                                                                                                                 //保存相关数据再重启                                                        
  184.                                                                  //   Save_PortTimes(); //保存端口时间数据                                                                                                                                                        
  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.         }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏12 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:99525 发表于 2022-6-15 20:56 | 只看该作者
这个话题值得探讨!现在物联网时代了,没有远程升级功能的产品就低人一等了!
回复

使用道具 举报

板凳
ID:25310 发表于 2022-6-17 08:38 | 只看该作者
这个话题好,楼主帖子不错,观摩一下。
回复

使用道具 举报

地板
ID:290796 发表于 2022-7-1 09:38 | 只看该作者
这个办法好。已经实现了吗?
回复

使用道具 举报

5#
ID:485350 发表于 2023-4-4 16:59 | 只看该作者
不需要什么IAP功能一样可以实现,任意FLASH芯片都可以
回复

使用道具 举报

6#
ID:954815 发表于 2023-7-7 14:25 | 只看该作者
18680365301 发表于 2023-4-4 16:59
不需要什么IAP功能一样可以实现,任意FLASH芯片都可以

大佬有参考案例吗,尝试了好久,升级程序也写到eeprom里面了,自己写isp程序就是无法跳转到用户区程序
回复

使用道具 举报

7#
ID:514317 发表于 2023-7-10 14:13 | 只看该作者
wangjunhuisky 发表于 2023-7-7 14:25
大佬有参考案例吗,尝试了好久,升级程序也写到eeprom里面了,自己写isp程序就是无法跳转到用户区程序

去看下STC的官网上面有介绍   可以使用官方示例进入ISP引导程序    使用2种方式    1种是P3.2低电位进入ISP   一种是内存最后特定区域写特殊字符串进入ISP    程序升级完后跳转到用户代码区域
回复

使用道具 举报

8#
ID:301968 发表于 2024-4-24 15:53 | 只看该作者
wangjunhuisky 发表于 2023-7-7 14:25
大佬有参考案例吗,尝试了好久,升级程序也写到eeprom里面了,自己写isp程序就是无法跳转到用户区程序

我的升级方法和STC官方不一样
首先最开始本地烧进去的程序是全功能的,当需要升级时,会制行串口接收BIN文件,写入FLASH中,校验通过后,直接改写0X200前面那段程序。
我用这个方法做了好多个案例,都是成功可行的,没有问题 。
回复

使用道具 举报

9#
ID:344848 发表于 2024-4-26 09:49 | 只看该作者
邓文雄ABC 发表于 2024-4-24 15:53
我的升级方法和STC官方不一样
首先最开始本地烧进去的程序是全功能的,当需要升级时,会制行串口接收BIN ...

不具备普性,这对于程序较小比较实用,程序大了就不能用了。网络如此发达,这种方法是否考虑被攻击的情况。
回复

使用道具 举报

10#
ID:961114 发表于 2024-4-26 09:55 | 只看该作者
人工智能时代:
控制下载数量,利用ID号控制下载的芯片,如何自动获得ID号
===最好的办法是,远程升级 = 【程序加密后传输 + 发布项目程序】
5.18.5  如何简单的控制下载次数,
             通过ID号必须对,来限制实际可以下载的MCU,控制数量
             ———【下载日志 + 发布项目程序】 高级应用      


如果你的客人,说他自己提前买了芯片,让你给他程序自己下载,
你要控制下载的芯片数量,你就先发布个只有部分功能的程序给他,
然后对方说程序好像不完整,你就请他将下载日志发你分析:
这样你就获得了他实际买了多少MCU和对应MCU的ID号

你再根据获得的芯片ID号文件,发布项目程序给他远程现场升级,
但ID号不对则不升级,达到了控制升级次数的目的
回复

使用道具 举报

11#
ID:433219 发表于 2024-4-26 17:10 | 只看该作者
是小容量,局部升级吧??   stc官方的是全擦除全部升级
回复

使用道具 举报

12#
ID:514317 发表于 2024-4-26 17:42 | 只看该作者
MCU升级还是有很多问题的    小程序还好   大程序超过内存一半的时候怎么处理??   还要中断向量偏移等   如果内置了升级功能还好   没有升级功能编写难度大点
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表