Files
STM8_Mesh_Control/docs/OTA_STORAGE_AND_PROTOCOL.md

9.9 KiB
Raw Permalink Blame History

STM8 Mesh 继电器 OTA、Flash 分区与业务协议设计

本文档记录当前已经确认的外部 W25Q80BV存储规划、Bootloader启动策略、主程序OTA职责以及业务命令规则。

1. 硬件资源与程序分区

1.1 STM8S003F3P6TR 内部 Flash

STM8S003F3P6TR 内部程序 Flash 总容量为 8KiB,地址范围为 0x8000~0x9FFF。

当前 Bootloader 规划如下:

地址范围 容量 用途
0x8000~0x84FF 1.25KiB Bootloader
0x8500~0x9FFF 6.75KiB Application 主程序

应用程序必须按照 0x8500 重新链接,不能使用默认的 0x8000 起始地址。

1.2 W25Q80BV 外部 Flash

W25Q80BV总容量为128KiB。当前固定分区如下:

地址范围 容量 用途
0x000000~0x001FFF 8KiB 出厂固件镜像
0x002000~0x002FFF 4KiB 出厂固件元数据
0x003000~0x004FFF 8KiB OTA升级固件镜像
0x005000~0x005FFF 4KiB OTA升级元数据
0x006000~0x01FFFF 104KiB 后续日志、运行记录、故障记录等

元数据区域均独占一个4KiB扇区,避免擦除元数据时影响固件镜像。

1.3 SPI连接

STM8引脚 W25Q80BV信号
PC5 SCK
PC6 MOSI/DI
PC7 MISO/DO
PD4 CS#
3.3V VCC
GND GND

恢复/继电器按键连接到 PA3,按键另一端接地,使用内部上拉:

PA3 = 1:按键释放
PA3 = 0:按键按下

JDY-28M 控制脚当前分配为:PA2=PWRC、PD2=RESET。PA2 不再作为Flash片选。

蓝牙状态/故障指示灯连接到 PB4,低电平点亮;继电器状态指示灯连接到 PD3,高电平点亮。

程序运行/OTA状态灯连接到 PB5,低电平点亮:正常运行时按500ms节奏闪烁,OTA接收或校验时按约100ms节奏快速闪烁。

2. 元数据格式

出厂元数据和OTA元数据使用相同字段布局,只是存储区域不同。

2.1 元数据字段

相对于元数据区域起始地址的固定偏移如下:

偏移 字段 长度 说明
0x00 魔数 4字节 识别元数据类型
0x04 固件长度 4字节 实际固件字节数
0x08 固件版本 2字节 版本号,高低字节规则由打包工具固定
0x0A CRC16 2字节 完整固件镜像CRC-16/MODBUS
0x0E 镜像有效标志 1字节 0xA5表示有效
0x0F 升级请求 1字节 非0表示请求Bootloader处理
0x10 升级结果 1字节 Bootloader执行结果
0x11 保留 1字节 后续扩展

2.2 元数据绝对地址

OTA元数据区域起始地址为 0x005000,因此:

魔数:        0x005000~0x005003
固件长度:    0x005004~0x005007
固件版本:    0x005008~0x005009
CRC16:       0x00500A~0x00500B
有效标志:    0x00500E
升级请求:    0x00500F
升级结果:    0x005010

出厂元数据区域起始地址为 0x002000,字段偏移相同,因此出厂镜像升级结果地址为 0x002010。

2.3 魔数

魔数是固定识别值,不是密码。当前约定:

FACTORY_METADATA_MAGIC = 0x46414331   /* FAC1,出厂镜像 */
OTA_METADATA_MAGIC     = 0x4F544131   /* OTA1,升级镜像 */

Bootloader只有在魔数正确、有效标志正确、升级请求有效、固件长度合法且CRC16正确时,才允许使用镜像。

2.4 元数据写入规则

下载过程中不能提前写入有效标志。正确顺序为:

1. 擦除OTA固件区域;
2. 接收并写入固件分包;
3. 计算完整固件CRC16/MODBUS;
4. 写入魔数、长度、版本和CRC16;
5. 校验元数据;
6. 最后写入image_valid = 0xA5;
7. 设置upgrade_request;
8. 软件复位进入Bootloader。

这样可以避免断电时把不完整固件误判为有效镜像。

3. Bootloader职责

Bootloader不处理JDY-28M Mesh通信,也不接收OTA分包。

Bootloader负责:

  • 上电检测PA3上电恢复按键;
  • 读取OTA元数据;
  • 校验OTA固件CRC16/MODBUS;
  • 擦除STM8内部应用区;
  • 从W25Q80BV搬运固件到内部Flash;
  • 回读校验内部Flash;
  • 写入升级结果;
  • 清除升级请求;
  • 检查内部应用程序是否有效;
  • 应用损坏时恢复出厂固件;
  • 跳转到 0x8500 启动主程序。

升级安全顺序必须是:

先完整校验W25Q80BV固件
        ↓
CRC正确
        ↓
擦除内部应用区
        ↓
写入应用程序
        ↓
回读校验
        ↓
记录升级成功
        ↓
清除升级请求

3.1 出厂固件恢复

以下任一情况出现时,Bootloader使用 0x000000 开始的出厂镜像:

  • 内部应用程序为空;
  • 内部应用程序入口无效;
  • OTA固件CRC16错误;
  • 内部Flash写入失败;
  • 内部Flash写入后校验失败;
  • 应用程序损坏导致无法正常启动。

出厂镜像必须预先写入W25Q80BV,并且出厂元数据中的镜像有效标志和CRC16必须正确。

4. PA3上电恢复按键

4.1 Bootloader阶段

上电后首先运行Bootloader:

检测PA3
├── 未按下:执行正常Bootloader流程
└── 已按下:开始计时,此期间不跳转主程序
    ├── 5秒内释放:继续正常Bootloader流程
    └── 持续按住超过5秒:恢复出厂固件

主程序不会参与本次上电按键判断,因此不存在Bootloader长按和主程序恢复参数重复触发的问题。

4.2 主程序阶段

主程序只处理正常运行期间的新按键:

短按:按下时间小于5秒,控制继电器
长按:按下时间大于5秒,恢复主程序参数

5. 主程序OTA职责

主程序负责:

  • 通过JDY-28M接收OTA业务帧;
  • 校验业务帧CRC16/MODBUS;
  • 擦除OTA固件区域;
  • 将固件分包写入 0x003000;
  • 计算完整固件CRC16/MODBUS;
  • 写入OTA元数据;
  • 设置有效标志和升级请求;
  • 软件复位进入Bootloader;
  • 启动后读取Bootloader升级结果;
  • 通过Mesh主动上报升级结果;
  • 收到主机确认后清除升级结果。

6. 主程序业务帧格式

业务数据帧格式:

CMD | LEN | DATA | CRC16_H | CRC16_L

说明:

  • JDY-28M 外层地址:发送方和接收方 Mesh 短地址均由外层提供,高字节在前; 设备应答时将外层发送方地址作为目标地址;
  • CMD:命令;
  • LEN:DATA长度;
  • DATA:命令数据;
  • CRC16:CRC-16/MODBUS,计算范围为 CMD、LEN、DATA,高字节在前;
  • 发送方和接收方 Mesh 短地址由 JDY-28M 外层帧携带,业务帧不重复添加地址;
  • CRC错误时静默丢弃,不执行继电器动作,不返回错误帧。

JDY-28M的Mesh外层帧负责目标地址、源地址、Mesh头和帧尾,业务帧本身不重复添加地址。

7. 已确定的业务命令

CMD 名称 方向 DATA说明
0x01 继电器控制 主机→设备 0x00断开,0x01吸合
0x02 查询继电器状态 主机→设备 返回0x00断开或0x01吸合
0x03 查询实际电流 主机→设备 返回无符号mA,高字节在前
0x04 故障/恢复上报 设备→主机 DATA为故障码或恢复码
0x05 查询设备短地址 主机→设备 返回2字节短地址
0x06 配置电流阈值 主机→设备 2字节,单位mA,低字节在前,保存到EEPROM

当前汇编主程序已经完成并通过实物验证的命令为:0x01、0x02和0x05。 0x03、0x04、0x06、0x07以及0x08~0x0E属于已确定的协议设计, 在当前汇编主程序中尚未全部完成或尚未完成实物验证,上位机不应据此判断当前 固件已经支持这些命令。 | 0x0E | 查询当前固件版本 | 主机→设备 | 无DATA | | 0x0D | OTA升级结果上报 | 设备→主机 | DATA为升级结果码 |

应答命令使用请求命令加 0x80:

0x81:继电器控制应答
0x82:继电器状态应答
0x83:电流查询应答
0x85:短地址查询应答
0x86:阈值配置应答

OTA内部控制命令建议保留:

0x08:进入OTA模式
0x09:固件数据分包
0x0A:固件发送完成并校验
0x0B:查询OTA状态
0x0C:取消OTA
0x0E:查询当前固件版本

8. 故障码和升级结果码

8.1 故障码

0x02:ACS712采样异常
0x03:蓝牙初始化异常
0x04:电流故障恢复
0x05:蓝牙故障恢复
0x06:采样异常恢复
0x07:继电器控制失败预留码

电流故障需要持续至少10秒确认,恢复也需要持续至少10秒确认。默认电流阈值为100mA,支持动态配置并保存到EEPROM。

故障恢复上报需要等待主机确认;未收到确认时每10秒重复上报,直到收到确认。

8.2 OTA升级结果码

0x00:无结果
0x01:升级成功
0x02:固件CRC错误
0x03:内部Flash写入失败
0x04:写入后校验失败
0x05:固件长度非法
0x06:W25Q80BV读取失败

主程序启动后读取升级结果,并使用:

CMD = 0x0D
LEN = 0x01
DATA = 升级结果码

发送给主机。主机确认后,主程序清除结果字段。

8.3 主机侧最终确认流程

CMD=0x8B仅表示应用程序已经完成外部Flash固件的整包CRC16校验,并且 已经成功写入OTA元数据。校验成功后,设备先发送0x8B=00,再主动触发 MCU复位;Bootloader随后负责把OTA镜像搬运到内部Flash。

主机不能在收到0x8B=00后立即认为升级完成,而应继续等待设备重新启动并 主动上报:

CMD = 0x0D
LEN = 0x01
DATA[0] = 0x01:Bootloader搬运并校验成功

主机默认等待20秒。超时未收到0x0D,或者收到的结果码不是0x01,均应 判定本次升级失败。收到结果后,主机向上报帧的设备短地址发送:

CMD = 0x8D
LEN = 0x01
DATA[0] = 原样返回设备上报的升级结果码

设备收到0x8D后清除待上报结果记录。