找回密码
 立即注册
查看: 297|回复: 1

ISP/OTA升级介绍,A/B分区升级,不同版本芯片不同处理方法

[复制链接]
  • 打卡等级:以坛为家III
  • 打卡总天数:687
  • 最近打卡:2026-03-05 13:33:59
已绑定手机
已实名认证

129

主题

3375

回帖

8784

积分

版主

积分
8784
发表于 2026-1-22 14:43:57 | 显示全部楼层 |阅读模式
STC, ISP/OTA升级介绍,A/B分区升级,不同版本芯片不同处理方法, 开源参考程序

ISP
(In-System Programming)
即“在系统编程”,这是 STC 主导的技术

这是一种对芯片(如单片机、FPGA、存储器)进行程序烧录的技术。这里的“在系统”是指:芯片已经被焊接在电路板(PCB)上之后,不再需要将芯片取下来,而是直接通过预留的接口线(如 JTAG、SWD、UART、SPI 等)对芯片内部的程序进行写入或擦除。

OTA (Over-the-Air) 是一种通过无线通信网络(如 Wi-Fi、蓝牙、4G/5G、LoRa 等)接收数据包,对设备进行远程固件或软件更新的技术,但现在 大量的实际是有线升级的ISP也故意叫OTA。
通常来讲,OTA也会被用在系统升级的一种泛用定义上,因为蓝牙/WIFI等方式,最终还是通过接口线对单片机进行程序的重新烧写,所以在更新单片机程序这件事上来讲,ISP/OTA其实是差不多的定义


那么通常的更新程序手段有哪些呢?
一种是通过官方的下载程序升级的,使用USB转串口,或者USB直接下载,使用官方的ISP软件,走的是官方下载协议,内部程序中,是系统固化的BootLoader来处理,无需用户程序介入
还有一种就是通过蓝牙串口转发,配置好校验位和波特率后,也可以通过官方的ISP软件下载,这种其实也算OTA的一种定义场景


还有就是用户使用自己编写的BootLoader进行程序的更新,这个时候因为是完全由用户控制,所以自由度就比较大了,常见的数据接收手段都能用来更新程序。
例如Wifi/蓝牙/4G/红外线/SPI/IIC/CAN/LIN等众多方式,只要能完成数据通讯就可以进行程序的更新。


而A/B 分区(也称为 Dual-Bank 或双分区机制)是 OTA 升级中一种为了保证安全性和体验而采用的存储架构设计。
  • 核心原理将设备的存储空间(Flash)划分为两个独立的区域,通常称为 A 区(主分区)和 B 区(备份分区)。这两个区域大小相同,都可以存放完整的系统固件。

  • 状态一:设备当前正在运行 A 区的旧系统。
  • 状态二:B 区处于闲置状态。

  • 升级流程(1) 沉默下载:当 OTA 升级开始时,设备继续运行 A 区的系统,用户正常使用不受影响。同时,设备在后台悄悄将下载的新固件写入闲置的 B 区。(2) 校验与激活:写入完成后,系统会校验 B 区数据的完整性。校验通过后,系统修改启动标志位,告诉引导程序(Bootloader)下次从 B 区启动。(3) 重启切换:设备重启。引导程序读取标志位,直接加载 B 区的新系统。此时,原来的 A 区变成了闲置的备份分区,等待下一次升级使用


在普通单片机上的实现差异:由于很多单片机在写入 Flash 时无法同时读取指令(即无法运行程序),所以在单片机上实现 A/B 升级时,通常流程是:先将数据下载到缓存或外部存储,需要写入 Flash 时,程序统一跳转到用户编写的 Bootloader 中(此时 A/B 区都不运行),由 Bootloader 将新固件写入目标分区。如果更新中途出现断电或数据传输失败,Bootloader 会在下次启动时检测,自动跳转到未损坏的那个分区(如保留的 A 区),从而保证设备不“变砖”。



当然由于A/B分区所需空间是双倍大小,而程序有时候会不够用,所以还有一种更新方式是,只保留一个用户BootLoader和程序区。但是更新程序时,如果出现中断或者数据断开,则下次上电或者恢复后,程序仍然保留在BootLoader运行。保证程序区如果不完整则不会跳转过去执行,防止程序死机。
这种方式还可以搭配一个看门狗,发现程序死机的时候,可以通过看门狗纠正回到程序开始,然后进入BootLoader等待重新刷写(异常问题回到等待下载状态,不会继续卡死)




STC单片机如果想要实现普通的ISP/OTA更新,目前已经有了不少参考案例:
深圳国芯人工智能有限公司-在线升级
手机也能对AI8051U, ISP/OTA升级用户程序了,使用用户系统区实现 - ISP下载/做自己的ISP 国芯人工智能技术交流网站 - AI32位8051交流社区

但是如果想要实现A/B分区更新,目前需要分成两种单片机不同的处理方法
支持用户系统区的单片机:AI8051U,STC32G144K246及其后续支持划分用户系统区的单片机
不支持用户系统区的单片机:AI8/AI32系列,STC32G12K128及其不支持划分用户系统区,但是支持全部FLASH可划分为EEPROM操作的单片机

这里主要一个区别是,中断跳转不同和地址映射不同
在支持用户系统区的单片机中,由硬件处理中断跳转地址和程序地址偏移,直接将原有程序下载进去即可,无需更改工程设置,可以完全当成不改动程序,且可以用来切换两套程序的单片机
如果不支持这个特性,那么就需要手动设置BOOT和APP程序不同的程序,要手动处理中断跳转问题(因为中断跳转只能是固定地址,需要使用额外方法来判断究竟是谁要用),要设置中断地址偏移和程序地址偏移,相对来讲稍微麻烦一点


1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:687
  • 最近打卡:2026-03-05 13:33:59
已绑定手机
已实名认证

129

主题

3375

回帖

8784

积分

版主

积分
8784
发表于 2026-1-24 18:00:33 | 显示全部楼层
这里针对传统 STC32 / STC8 系列,无用户系统区的单片机(但是可以操作全部FLASH空间)

提供一种BOOT和APP之间共享中断的方案,无需重定向中断向量表
且支持多个APP同时使用中断
ota程序升级.zip (101.24 KB, 下载次数: 8)


BOOT程序:
  1. #include <AI8H.H>
  2. int cnt = 0;
  3. int ota_cnt = 0;
  4. void Timer0_Init(void);
  5. unsigned int xdata ISR_Offset _at_ 0x400;         //偏移地址,定义在1k的xdata处
  6. #define LDR_SIZE 0x1800
  7. void All_Isr(void)
  8. {
  9.         cnt++;
  10. }
  11. void Timer0_Isr(void) interrupt 1
  12. {
  13.         ((void (code *)())(ISR_Offset))();
  14. }
  15. void main(void)
  16. {
  17.         P_SW2 |= 0x80;
  18.         ISR_Offset = (unsigned int)All_Isr;//给定中断地址
  19.         P4M0 = 0x00; P4M1 = 0x00;
  20.   P6M0 = 0x00; P6M1 = 0x00;
  21.         Timer0_Init();
  22.         EA = 1;
  23.         while(1)
  24.         {
  25.                 if(cnt>=200)
  26.                 {
  27.                         cnt = 0;
  28.                         P40 = ~P40;
  29.                         P60 = ~P60;
  30.                         ota_cnt++;
  31.                         if(ota_cnt>10)
  32.                         {
  33.                                 ota_cnt = 0;
  34.                                 EA = 0;//跳转之前记得给中断关了,不然乱蹦跶
  35.                                 ((void (code *)())(LDR_SIZE))();
  36.                         }
  37.                 }
  38.         }
  39. }
  40. void Timer0_Init(void)                //1毫秒@24.000MHz
  41. {
  42.         AUXR |= 0x80;                        //定时器时钟1T模式
  43.         TMOD &= 0xF0;                        //设置定时器模式
  44.         TL0 = 0x40;                                //设置定时初始值
  45.         TH0 = 0xA2;                                //设置定时初始值
  46.         TF0 = 0;                                //清除TF0标志
  47.         TR0 = 1;                                //定时器0开始计时
  48.         ET0 = 1;                                //使能定时器0中断
  49. }
复制代码
app程序:
  1. #include <AI8H.H>
  2. int cnt = 0;
  3. void Timer0_Init(void);
  4. unsigned int xdata ISR_Offset _at_ 0x400;         //偏移地址,定义在1k的xdata处
  5. void All_Isr(void)
  6. {
  7.         cnt++;
  8. }
  9. void main(void)
  10. {
  11.         P_SW2 |= 0x80;
  12.         ISR_Offset = (unsigned int)All_Isr;//给定中断地址
  13.         P4M0 = 0x00; P4M1 = 0x00;
  14.   P6M0 = 0x00; P6M1 = 0x00;
  15.         Timer0_Init();
  16.         EA = 1;
  17.         while(1)
  18.         {
  19.                 if(cnt>=50)
  20.                 {
  21.                         cnt = 0;
  22.                         P40 = ~P40;
  23.                         P60 = ~P60;
  24.                 }
  25.         }
  26. }
  27. void Timer0_Init(void)                //1毫秒@24.000MHz
  28. {
  29.         AUXR |= 0x80;                        //定时器时钟1T模式
  30.         TMOD &= 0xF0;                        //设置定时器模式
  31.         TL0 = 0x40;                                //设置定时初始值
  32.         TH0 = 0xA2;                                //设置定时初始值
  33.         TF0 = 0;                                //清除TF0标志
  34.         TR0 = 1;                                //定时器0开始计时
  35.         ET0 = 1;                                //使能定时器0中断
  36. }
复制代码
程序主要使用xdata不断电情况下不变的特性,通过一个变量来存储不同的中断函数地址
然后在app内,不使用interrupt定义,而是使用普通函数写完成中断程序后,将此函数的地址赋值给这个共同约定好的变量,使其可以在BOOT的中断函数中被调用一次,以此达到可以不用重定向中断向量,多个APP可用中断函数的作用
APP程序的HEX文件处理方法可以参考:如何把自己的用户区ISP固件和自己的用户区AP固件进行合并供工厂量产使用 - ISP下载/做自己的ISP 国芯人工智能技术交流网站 - AI32位8051交流社区
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-6 05:11 , Processed in 0.104260 second(s), 47 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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