feat: 完善Mesh继电器OTA升级闭环
This commit is contained in:
+99
-31
@@ -54,7 +54,7 @@ F1 DD 09 00 0A | SRC_H SRC_L | BUSINESS | 0D 0A
|
||||
JDY-28M完整Mesh帧最大20字节。当前业务帧最大DATA长度为4字节:
|
||||
|
||||
```text
|
||||
BUSINESS = SRC_H SRC_L CMD LEN DATA CRC16_L CRC16_H
|
||||
BUSINESS = SRC_H SRC_L CMD LEN DATA CRC16_H CRC16_L
|
||||
```
|
||||
|
||||
业务帧长度为`6 + LEN`,完整外层发送帧长度为`16 + LEN`,因此`LEN`最大为4。
|
||||
@@ -62,7 +62,7 @@ BUSINESS = SRC_H SRC_L CMD LEN DATA CRC16_L CRC16_H
|
||||
## 2. 业务帧格式
|
||||
|
||||
```text
|
||||
SRC_H SRC_L | CMD | LEN | DATA[0..LEN-1] | CRC16_L CRC16_H
|
||||
SRC_H SRC_L | CMD | LEN | DATA[0..LEN-1] | CRC16_H CRC16_L
|
||||
```
|
||||
|
||||
### 2.1 CRC16规则
|
||||
@@ -74,7 +74,7 @@ SRC_H SRC_L | CMD | LEN | DATA[0..LEN-1] | CRC16_L CRC16_H
|
||||
输入反射:是
|
||||
输出反射:是
|
||||
计算范围:SRC_H、SRC_L、CMD、LEN和DATA
|
||||
发送顺序:CRC低字节在前,高字节在后
|
||||
发送顺序:CRC高字节在前,低字节在后
|
||||
```
|
||||
|
||||
CRC错误时设备直接丢弃整帧,不执行命令,也不返回错误应答。
|
||||
@@ -87,6 +87,11 @@ CRC错误时设备直接丢弃整帧,不执行命令,也不返回错误应
|
||||
应答CMD = 请求CMD | 0x80
|
||||
```
|
||||
|
||||
当请求通过 Mesh 广播地址 `FFFF` 发送时,设备不会立即同时回复。设备会
|
||||
根据本机短地址和系统时间生成约20~170ms、按10ms分档的随机延时,然后向业务帧中的
|
||||
发送方 `SRC_H SRC_L` 单播回复,以降低多个设备同时应答造成的网络拥塞。
|
||||
单播请求仍然直接回复。
|
||||
|
||||
错误应答:
|
||||
|
||||
```text
|
||||
@@ -104,6 +109,54 @@ DATA[0] = 错误码
|
||||
0x06:未知命令
|
||||
```
|
||||
|
||||
## 3.1 `0x07` 设备上线广播
|
||||
|
||||
设备在本次上电完成基础初始化、蓝牙进入可通信状态后,向 Mesh 广播一次:
|
||||
|
||||
```text
|
||||
CMD = 07
|
||||
LEN = 00
|
||||
```
|
||||
|
||||
发送方短地址位于业务帧的 `SRC_H SRC_L` 字段中,因此该命令不需要 DATA,
|
||||
其他设备收到后不回复。主机或其他设备可据此更新在线状态;如果后续长期
|
||||
未收到该设备的上线或业务消息,可以结合应用层超时判断设备是否离线。
|
||||
|
||||
## 3.2 `0x10` 固件版本发现广播
|
||||
|
||||
主机发现服务器存在新固件后,向Mesh广播最新版本和固件长度。该命令只用于
|
||||
设备发现,不会直接启动OTA。
|
||||
|
||||
```text
|
||||
CMD = 10
|
||||
LEN = 04
|
||||
DATA[0] = 最新版本高字节
|
||||
DATA[1] = 最新版本低字节
|
||||
DATA[2] = 固件长度高字节
|
||||
DATA[3] = 固件长度低字节
|
||||
```
|
||||
|
||||
设备收到后比较:
|
||||
|
||||
```text
|
||||
最新版本 > 当前版本:随机延时后回复
|
||||
最新版本 <= 当前版本:静默丢弃,不回复
|
||||
```
|
||||
|
||||
需要升级的设备返回:
|
||||
|
||||
```text
|
||||
CMD = 90
|
||||
LEN = 04
|
||||
DATA[0] = 当前版本高字节
|
||||
DATA[1] = 当前版本低字节
|
||||
DATA[2] = 需要升级的版本高字节
|
||||
DATA[3] = 需要升级的版本低字节
|
||||
```
|
||||
|
||||
设备短地址位于响应业务帧的`SRC_H SRC_L`字段中。主机收到多个`0x90`后,
|
||||
生成待升级设备列表,由人工选择设备,再对选中的短地址执行后续OTA流程。
|
||||
|
||||
## 4. 主机下发的普通命令
|
||||
|
||||
### 4.1 `0x01` 继电器控制
|
||||
@@ -120,7 +173,7 @@ DATA[0] = 01:继电器吸合
|
||||
业务帧结构示例:
|
||||
|
||||
```text
|
||||
SRC_H SRC_L 01 01 01 CRC16_L CRC16_H
|
||||
SRC_H SRC_L 01 01 01 CRC16_H CRC16_L
|
||||
```
|
||||
|
||||
设备执行后返回:
|
||||
@@ -170,14 +223,14 @@ LEN = 00
|
||||
```text
|
||||
CMD = 83
|
||||
LEN = 02
|
||||
DATA[0] = 电流低字节
|
||||
DATA[1] = 电流高字节
|
||||
DATA[0] = 电流高字节
|
||||
DATA[1] = 电流低字节
|
||||
```
|
||||
|
||||
单位为mA,无符号整数,低字节在前。例如实际电流为`1000mA = 0x03E8`:
|
||||
单位为mA,无符号整数,高字节在前。例如实际电流为`1000mA = 0x03E8`:
|
||||
|
||||
```text
|
||||
DATA = E8 03
|
||||
DATA = 03 E8
|
||||
```
|
||||
|
||||
### 4.4 `0x05` 查询设备短地址
|
||||
@@ -211,14 +264,14 @@ DATA = 00 0C
|
||||
```text
|
||||
CMD = 06
|
||||
LEN = 02
|
||||
DATA[0] = 阈值低字节
|
||||
DATA[1] = 阈值高字节
|
||||
DATA[0] = 阈值高字节
|
||||
DATA[1] = 阈值低字节
|
||||
```
|
||||
|
||||
单位为mA,默认值为100mA,设备保存到内部EEPROM。例如设置100mA:
|
||||
|
||||
```text
|
||||
DATA = 64 00
|
||||
DATA = 00 64
|
||||
```
|
||||
|
||||
设备成功返回:
|
||||
@@ -245,8 +298,8 @@ LEN = 00
|
||||
```text
|
||||
CMD = 8E
|
||||
LEN = 02
|
||||
DATA[0] = 版本低字节
|
||||
DATA[1] = 版本高字节
|
||||
DATA[0] = 版本高字节
|
||||
DATA[1] = 版本低字节
|
||||
```
|
||||
|
||||
当前版本在主程序`include/app_config.h`中定义:
|
||||
@@ -303,17 +356,17 @@ DATA[0] = 被确认的故障码或恢复码
|
||||
```text
|
||||
CMD = 08
|
||||
LEN = 04
|
||||
DATA[0] = 固件长度低字节
|
||||
DATA[1] = 固件长度高字节
|
||||
DATA[2] = 版本号低字节
|
||||
DATA[3] = 版本号高字节
|
||||
DATA[0] = 固件长度高字节
|
||||
DATA[1] = 固件长度低字节
|
||||
DATA[2] = 版本号高字节
|
||||
DATA[3] = 版本号低字节
|
||||
```
|
||||
|
||||
设备收到后擦除:
|
||||
|
||||
```text
|
||||
OTA固件区:0x020000~0x02FFFF
|
||||
OTA元数据:0x030000~0x030FFF
|
||||
OTA固件区:0x003000~0x004FFF
|
||||
OTA元数据:0x005000~0x005FFF
|
||||
```
|
||||
|
||||
成功应答:
|
||||
@@ -364,8 +417,8 @@ DATA[2] = 下一期待偏移低字节
|
||||
```text
|
||||
CMD = 0A
|
||||
LEN = 02
|
||||
DATA[0] = 完整固件CRC16低字节
|
||||
DATA[1] = 完整固件CRC16高字节
|
||||
DATA[0] = 完整固件CRC16高字节
|
||||
DATA[1] = 完整固件CRC16低字节
|
||||
```
|
||||
|
||||
CRC16使用CRC-16/MODBUS,计算范围是整个裸二进制固件文件。
|
||||
@@ -390,12 +443,12 @@ LEN = 00
|
||||
设备从W25Q64重新读取完整固件并计算CRC16。校验成功后写入OTA元数据:
|
||||
|
||||
```text
|
||||
0x030000:魔数
|
||||
0x030004:固件长度
|
||||
0x030008:固件版本
|
||||
0x03000A:CRC16
|
||||
0x03000E:镜像有效标志0xA5
|
||||
0x03000F:升级请求0xA5
|
||||
0x005000:魔数
|
||||
0x005004:固件长度
|
||||
0x005008:固件版本
|
||||
0x00500A:CRC16
|
||||
0x00500E:镜像有效标志0xA5
|
||||
0x00500F:升级请求0xA5
|
||||
```
|
||||
|
||||
设备返回:
|
||||
@@ -407,7 +460,10 @@ DATA[0] = 00:校验成功,已提交升级
|
||||
DATA[0] = 01:校验失败
|
||||
```
|
||||
|
||||
之后设备复位,由Bootloader把OTA固件搬运到内部Flash的`0x8800`区域。
|
||||
当`DATA[0]=00`时,设备已经完成外部Flash固件校验并写入升级元数据。
|
||||
设备会先发送`0x8B`应答,随后自动触发MCU复位,由Bootloader把OTA固件
|
||||
搬运到内部Flash的`0x8800`区域。`0x8B`不代表Bootloader已经搬运完成,
|
||||
主机必须继续等待设备重新启动后主动上报的`0x0D`。
|
||||
|
||||
### 7.5 `0x0C` 取消OTA
|
||||
|
||||
@@ -437,14 +493,24 @@ DATA[0] = 00:取消成功
|
||||
发送完整CRC16:0A
|
||||
请求校验提交:0B
|
||||
等待校验结果:8B
|
||||
设备复位并升级
|
||||
设备发送8B后自动复位并升级
|
||||
主程序启动后主动上报升级结果:0D
|
||||
主机确认升级结果:8D
|
||||
```
|
||||
|
||||
主机等待最终升级结果的建议规则:
|
||||
|
||||
```text
|
||||
收到 0x8B=00 后,继续等待 0x0D,默认超时时间为20秒;
|
||||
收到 0x0D 且 DATA[0]=0x01:升级成功;
|
||||
收到 0x0D 且 DATA[0]不是0x01:升级失败;
|
||||
超过20秒没有收到0x0D:升级失败;
|
||||
收到升级结果后,主机向该设备短地址发送0x8D确认。
|
||||
```
|
||||
|
||||
## 8. OTA升级结果上报
|
||||
|
||||
设备启动后从`0x030010`读取升级结果,蓝牙初始化成功后主动广播:
|
||||
设备启动后从`0x005010`读取升级结果,蓝牙初始化成功后主动广播:
|
||||
|
||||
```text
|
||||
CMD = 0D
|
||||
@@ -472,4 +538,6 @@ LEN = 01
|
||||
DATA[0] = 对应的升级结果码
|
||||
```
|
||||
|
||||
设备收到确认后清除`0x030010`。
|
||||
设备收到确认后清除`0x005010`。
|
||||
如果主机没有发送`0x8D`,设备不会清除结果记录,后续启动时可能再次上报,
|
||||
便于主机发现升级结果确认丢失。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# STM8 Mesh 继电器 OTA、Flash 分区与业务协议设计
|
||||
|
||||
本文档记录当前已经确认的外部 W25Q64 存储规划、Bootloader 启动策略、主程序 OTA 职责以及业务命令规则。
|
||||
本文档记录当前已经确认的外部 W25Q80BV存储规划、Bootloader启动策略、主程序OTA职责以及业务命令规则。
|
||||
|
||||
## 1. 硬件资源与程序分区
|
||||
|
||||
@@ -17,23 +17,23 @@ STM8S003F3P6TR 内部程序 Flash 总容量为 8KiB,地址范围为 `0x8000~0x
|
||||
|
||||
应用程序必须按照 `0x8800` 重新链接,不能使用默认的 `0x8000` 起始地址。
|
||||
|
||||
### 1.2 W25Q64JVSIQ 外部 Flash
|
||||
### 1.2 W25Q80BV 外部 Flash
|
||||
|
||||
W25Q64 总容量为 8MiB。当前固定分区如下:
|
||||
W25Q80BV总容量为128KiB。当前固定分区如下:
|
||||
|
||||
| 地址范围 | 容量 | 用途 |
|
||||
|---|---:|---|
|
||||
| `0x000000~0x00FFFF` | 64KiB | 出厂固件镜像 |
|
||||
| `0x010000~0x010FFF` | 4KiB | 出厂固件元数据 |
|
||||
| `0x020000~0x02FFFF` | 64KiB | OTA升级固件镜像 |
|
||||
| `0x030000~0x030FFF` | 4KiB | OTA升级元数据 |
|
||||
| 其余空间 | 约8056KiB | 后续日志、运行记录、故障记录等 |
|
||||
| `0x000000~0x001FFF` | 8KiB | 出厂固件镜像 |
|
||||
| `0x002000~0x002FFF` | 4KiB | 出厂固件元数据 |
|
||||
| `0x003000~0x004FFF` | 8KiB | OTA升级固件镜像 |
|
||||
| `0x005000~0x005FFF` | 4KiB | OTA升级元数据 |
|
||||
| `0x006000~0x01FFFF` | 104KiB | 后续日志、运行记录、故障记录等 |
|
||||
|
||||
元数据区域均独占一个4KiB扇区,避免擦除元数据时影响固件镜像。
|
||||
|
||||
### 1.3 SPI连接
|
||||
|
||||
| STM8引脚 | W25Q64信号 |
|
||||
| STM8引脚 | W25Q80BV信号 |
|
||||
|---|---|
|
||||
| `PC5` | `SCK` |
|
||||
| `PC6` | `MOSI/DI` |
|
||||
@@ -76,19 +76,19 @@ JDY-28M 控制脚当前分配为:`PA2=PWRC`、`PD2=RESET`。`PA2` 不再作为
|
||||
|
||||
### 2.2 元数据绝对地址
|
||||
|
||||
OTA元数据区域起始地址为 `0x030000`,因此:
|
||||
OTA元数据区域起始地址为 `0x005000`,因此:
|
||||
|
||||
```text
|
||||
魔数: 0x030000~0x030003
|
||||
固件长度: 0x030004~0x030007
|
||||
固件版本: 0x030008~0x030009
|
||||
CRC16: 0x03000A~0x03000B
|
||||
有效标志: 0x03000E
|
||||
升级请求: 0x03000F
|
||||
升级结果: 0x030010
|
||||
魔数: 0x005000~0x005003
|
||||
固件长度: 0x005004~0x005007
|
||||
固件版本: 0x005008~0x005009
|
||||
CRC16: 0x00500A~0x00500B
|
||||
有效标志: 0x00500E
|
||||
升级请求: 0x00500F
|
||||
升级结果: 0x005010
|
||||
```
|
||||
|
||||
出厂元数据区域起始地址为 `0x010000`,字段偏移相同,因此出厂镜像升级结果地址为 `0x010010`。
|
||||
出厂元数据区域起始地址为 `0x002000`,字段偏移相同,因此出厂镜像升级结果地址为 `0x002010`。
|
||||
|
||||
### 2.3 魔数
|
||||
|
||||
@@ -128,7 +128,7 @@ Bootloader负责:
|
||||
- 读取OTA元数据;
|
||||
- 校验OTA固件CRC16/MODBUS;
|
||||
- 擦除STM8内部应用区;
|
||||
- 从W25Q64搬运固件到内部Flash;
|
||||
- 从W25Q80BV搬运固件到内部Flash;
|
||||
- 回读校验内部Flash;
|
||||
- 写入升级结果;
|
||||
- 清除升级请求;
|
||||
@@ -139,7 +139,7 @@ Bootloader负责:
|
||||
升级安全顺序必须是:
|
||||
|
||||
```text
|
||||
先完整校验W25Q64固件
|
||||
先完整校验W25Q80BV固件
|
||||
↓
|
||||
CRC正确
|
||||
↓
|
||||
@@ -165,7 +165,7 @@ CRC正确
|
||||
- 内部Flash写入后校验失败;
|
||||
- 应用程序损坏导致无法正常启动。
|
||||
|
||||
出厂镜像必须预先写入W25Q64,并且出厂元数据中的镜像有效标志和CRC16必须正确。
|
||||
出厂镜像必须预先写入W25Q80BV,并且出厂元数据中的镜像有效标志和CRC16必须正确。
|
||||
|
||||
## 4. PA3上电恢复按键
|
||||
|
||||
@@ -199,7 +199,7 @@ CRC正确
|
||||
- 通过JDY-28M接收OTA业务帧;
|
||||
- 校验业务帧CRC16/MODBUS;
|
||||
- 擦除OTA固件区域;
|
||||
- 将固件分包写入 `0x020000`;
|
||||
- 将固件分包写入 `0x003000`;
|
||||
- 计算完整固件CRC16/MODBUS;
|
||||
- 写入OTA元数据;
|
||||
- 设置有效标志和升级请求;
|
||||
@@ -288,7 +288,7 @@ OTA内部控制命令建议保留:
|
||||
0x03:内部Flash写入失败
|
||||
0x04:写入后校验失败
|
||||
0x05:固件长度非法
|
||||
0x06:W25Q64读取失败
|
||||
0x06:W25Q80BV读取失败
|
||||
```
|
||||
|
||||
主程序启动后读取升级结果,并使用:
|
||||
@@ -300,3 +300,29 @@ DATA = 升级结果码
|
||||
```
|
||||
|
||||
发送给主机。主机确认后,主程序清除结果字段。
|
||||
|
||||
### 8.3 主机侧最终确认流程
|
||||
|
||||
`CMD=0x8B`仅表示应用程序已经完成外部Flash固件的整包CRC16校验,并且
|
||||
已经成功写入OTA元数据。校验成功后,设备先发送`0x8B=00`,再主动触发
|
||||
MCU复位;Bootloader随后负责把OTA镜像搬运到内部Flash。
|
||||
|
||||
主机不能在收到`0x8B=00`后立即认为升级完成,而应继续等待设备重新启动并
|
||||
主动上报:
|
||||
|
||||
```text
|
||||
CMD = 0x0D
|
||||
LEN = 0x01
|
||||
DATA[0] = 0x01:Bootloader搬运并校验成功
|
||||
```
|
||||
|
||||
主机默认等待20秒。超时未收到`0x0D`,或者收到的结果码不是`0x01`,均应
|
||||
判定本次升级失败。收到结果后,主机向上报帧的设备短地址发送:
|
||||
|
||||
```text
|
||||
CMD = 0x8D
|
||||
LEN = 0x01
|
||||
DATA[0] = 原样返回设备上报的升级结果码
|
||||
```
|
||||
|
||||
设备收到`0x8D`后清除待上报结果记录。
|
||||
|
||||
Reference in New Issue
Block a user