V1.5: 回退W25Q64结构改动(现场无法刷BL);OTA任务id改存APP私有EEPROM(175),确认时可靠连接补发result.post
This commit is contained in:
parent
e9eed60b00
commit
2facb017bf
|
|
@ -750,7 +750,7 @@ static void air780e_trigger_ota_body(const char *host, int port, const char *pat
|
||||||
air780e_mqtt_result_nowait("iot.ota.result.post", ota_id, 1);
|
air780e_mqtt_result_nowait("iot.ota.result.post", ota_id, 1);
|
||||||
bg_delay(1000); /* 给模组一点发送时间即复位(权威通知由重启后的 confirm.post 承担) */
|
bg_delay(1000); /* 给模组一点发送时间即复位(权威通知由重启后的 confirm.post 承担) */
|
||||||
/* 只把固件信息写入 W25Q64,版本号在 APP 确认成功后再写入 EEPROM */
|
/* 只把固件信息写入 W25Q64,版本号在 APP 确认成功后再写入 EEPROM */
|
||||||
W25Q64_OTA_SetNewInfo(new_ver, file_size, crc16, ota_id);
|
W25Q64_OTA_SetNewInfo(new_ver, file_size, crc16);
|
||||||
reset_log_mark(RSN_OTA_UPDATE);
|
reset_log_mark(RSN_OTA_UPDATE);
|
||||||
bg_delay(100); NVIC_SystemReset();
|
bg_delay(100); NVIC_SystemReset();
|
||||||
}
|
}
|
||||||
|
|
@ -777,11 +777,20 @@ int air780e_ota_confirm(void)
|
||||||
else log_error("> OTA 确认写入失败(已重试 3 次)");
|
else log_error("> OTA 确认写入失败(已重试 3 次)");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 重启后的新鲜可靠连接上,先补发 result.post(带平台任务 id,驱动"完成"标志),
|
/* 重启后的新鲜可靠连接上,先补发 result.post(带平台任务 id,驱动"完成"标志)。
|
||||||
* 再发 confirm.post(防回滚确认)。下载完成时发的那条 result 在 OTA 会话上不可靠 */
|
* 任务 id 存在 EEPROM(175~194)(下载开始时由网络层写入),发送成功后清回 0xFF */
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
if (info.ota_id[0]) {
|
{
|
||||||
rc |= NET_mqtt_report("iot.ota.result.post", info.ota_id, 1);
|
char oid[20];
|
||||||
|
eepromReadData(175, oid, sizeof(oid));
|
||||||
|
if ((uint8_t)oid[0] != 0xFF && oid[0] != 0) {
|
||||||
|
oid[19] = 0;
|
||||||
|
rc |= NET_mqtt_report("iot.ota.result.post", oid, 1);
|
||||||
|
if (rc == 0) {
|
||||||
|
memset(oid, 0xFF, sizeof(oid));
|
||||||
|
eepromWriteData(175, oid, sizeof(oid)); /* 已送达,清除防止重复 */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* 再向服务器上报"确认成功"(走网络层路由,4G/WiFi 通道均可) */
|
/* 再向服务器上报"确认成功"(走网络层路由,4G/WiFi 通道均可) */
|
||||||
char id_buf[24] = {0};
|
char id_buf[24] = {0};
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ void net_wifi_ota(const char *host, int port, const char *path,
|
||||||
log_info("* 正在重启进入 BootLoader... *");
|
log_info("* 正在重启进入 BootLoader... *");
|
||||||
log_info("**************************************");
|
log_info("**************************************");
|
||||||
/* 只把固件信息写入 W25Q64,版本号在 APP 确认成功后再写入 EEPROM */
|
/* 只把固件信息写入 W25Q64,版本号在 APP 确认成功后再写入 EEPROM */
|
||||||
W25Q64_OTA_SetNewInfo(new_ver, file_size, crc16, ota_id);
|
W25Q64_OTA_SetNewInfo(new_ver, file_size, crc16);
|
||||||
reset_log_mark(RSN_OTA_UPDATE);
|
reset_log_mark(RSN_OTA_UPDATE);
|
||||||
bg_delay(100);
|
bg_delay(100);
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ static void esp_power(uint8_t on)
|
||||||
volatile net_ui_phase_t g_net_ui_phase = NET_UI_NONE;
|
volatile net_ui_phase_t g_net_ui_phase = NET_UI_NONE;
|
||||||
volatile int g_net_ui_countdown = 0;
|
volatile int g_net_ui_countdown = 0;
|
||||||
|
|
||||||
|
#define OTA_ID_EEP_ADDR 175 /* EEPROM 175~194:OTA 平台任务 id(确认后清 0xFF) */
|
||||||
|
|
||||||
static net_backend_t s_backend = NET_BACKEND_4G;
|
static net_backend_t s_backend = NET_BACKEND_4G;
|
||||||
|
|
||||||
/* 上次成功联网方式(EEPROM 偏移 130,秤参数占用到 126,避开) */
|
/* 上次成功联网方式(EEPROM 偏移 130,秤参数占用到 126,避开) */
|
||||||
|
|
@ -451,6 +453,14 @@ void net_dispatch_message(const char *msg)
|
||||||
else strncpy(host,p,sizeof(host)-1);
|
else strncpy(host,p,sizeof(host)-1);
|
||||||
}}
|
}}
|
||||||
log_info("> OTA: %s:%d%s", host, port, path);
|
log_info("> OTA: %s:%d%s", host, port, path);
|
||||||
|
/* 平台任务 id 存 EEPROM(偏移 175):重启确认时补发 result.post 用。
|
||||||
|
* 注意:故意不用 W25Q64 OTA 信息结构(它 BL/APP 共享,改结构要重刷 BL,
|
||||||
|
* 现场设备无法远程刷 BL),EEPROM 是 APP 私有的 */
|
||||||
|
if (ota_id[0]) {
|
||||||
|
char id20[20] = {0};
|
||||||
|
strncpy(id20, ota_id, sizeof(id20) - 1);
|
||||||
|
eepromWriteData(OTA_ID_EEP_ADDR, id20, sizeof(id20));
|
||||||
|
}
|
||||||
/* 两条通道共用 W25Q64 双槽 + CRC + BootLoader 回退体系,仅下载传输不同 */
|
/* 两条通道共用 W25Q64 双槽 + CRC + BootLoader 回退体系,仅下载传输不同 */
|
||||||
if (s_backend == NET_BACKEND_WIFI) {
|
if (s_backend == NET_BACKEND_WIFI) {
|
||||||
net_wifi_ota(host, port, path, ota_id, new_ver, crc16);
|
net_wifi_ota(host, port, path, ota_id, new_ver, crc16);
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ int W25Q64_OTA_WriteInfo(const W25Q64_OtaInfo *info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int W25Q64_OTA_SetNewInfo(uint16_t version, uint32_t size, uint16_t crc16, const char *ota_id)
|
int W25Q64_OTA_SetNewInfo(uint16_t version, uint32_t size, uint16_t crc16)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
storage_lock();
|
storage_lock();
|
||||||
|
|
@ -330,8 +330,6 @@ int W25Q64_OTA_SetNewInfo(uint16_t version, uint32_t size, uint16_t crc16, const
|
||||||
info.boot_trial_count = 0;
|
info.boot_trial_count = 0;
|
||||||
info.app_confirmed = 0;
|
info.app_confirmed = 0;
|
||||||
info.backup_valid = 0; /* 新下载后,下一次更新需要重新备份当前 APP */
|
info.backup_valid = 0; /* 新下载后,下一次更新需要重新备份当前 APP */
|
||||||
memset(info.ota_id, 0, sizeof(info.ota_id));
|
|
||||||
if (ota_id) strncpy(info.ota_id, ota_id, sizeof(info.ota_id) - 1); /* 平台任务 id,重启后补发结果用 */
|
|
||||||
ret = W25Q64_OTA_WriteInfo(&info);
|
ret = W25Q64_OTA_WriteInfo(&info);
|
||||||
storage_unlock();
|
storage_unlock();
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,6 @@ typedef struct {
|
||||||
uint16_t backup_crc16; /* 备份固件 CRC16 */
|
uint16_t backup_crc16; /* 备份固件 CRC16 */
|
||||||
uint8_t backup_valid; /* 槽 A 备份是否有效 */
|
uint8_t backup_valid; /* 槽 A 备份是否有效 */
|
||||||
uint8_t reserved2;
|
uint8_t reserved2;
|
||||||
char ota_id[20]; /* 平台 OTA 任务 id(重启后补发 result.post 用) */
|
|
||||||
uint16_t checksum; /* 前面所有字节累加和 */
|
uint16_t checksum; /* 前面所有字节累加和 */
|
||||||
} W25Q64_OtaInfo;
|
} W25Q64_OtaInfo;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
@ -95,7 +94,7 @@ int W25Q64_Verify(uint32_t addr, const uint8_t *data, uint32_t len);
|
||||||
/* OTA 专用信息区操作 */
|
/* OTA 专用信息区操作 */
|
||||||
int W25Q64_OTA_ReadInfo(W25Q64_OtaInfo *info);
|
int W25Q64_OTA_ReadInfo(W25Q64_OtaInfo *info);
|
||||||
int W25Q64_OTA_WriteInfo(const W25Q64_OtaInfo *info);
|
int W25Q64_OTA_WriteInfo(const W25Q64_OtaInfo *info);
|
||||||
int W25Q64_OTA_SetNewInfo(uint16_t version, uint32_t size, uint16_t crc16, const char *ota_id);
|
int W25Q64_OTA_SetNewInfo(uint16_t version, uint32_t size, uint16_t crc16);
|
||||||
int W25Q64_OTA_SetBackupInfo(uint32_t size, uint16_t crc16);
|
int W25Q64_OTA_SetBackupInfo(uint32_t size, uint16_t crc16);
|
||||||
int W25Q64_OTA_ClearNew(void);
|
int W25Q64_OTA_ClearNew(void);
|
||||||
int W25Q64_OTA_SetState(uint8_t state);
|
int W25Q64_OTA_SetState(uint8_t state);
|
||||||
|
|
|
||||||
|
|
@ -328,6 +328,7 @@ W25Q64 外部 Flash(8MB):
|
||||||
| 164~171 | 8B | HLW8032 累计脉冲数(uint64,每攒 0.1kWh + 断电前写入) |
|
| 164~171 | 8B | HLW8032 累计脉冲数(uint64,每攒 0.1kWh + 断电前写入) |
|
||||||
| 172 | 1B | 产品模式:0=四路继电器(无秤),1=称重投料(带秤),空白时用 main.h 宏默认值(蓝牙 SCALE0/SCALE1 切换) |
|
| 172 | 1B | 产品模式:0=四路继电器(无秤),1=称重投料(带秤),空白时用 main.h 宏默认值(蓝牙 SCALE0/SCALE1 切换) |
|
||||||
| 173 | 1B | GPS 定位开关:0=关,1=开,空白时用 main.h 宏默认值(蓝牙 GPS0/GPS1 切换,重启生效) |
|
| 173 | 1B | GPS 定位开关:0=关,1=开,空白时用 main.h 宏默认值(蓝牙 GPS0/GPS1 切换,重启生效) |
|
||||||
|
| 175~194 | 20B | OTA 平台任务 id(下载开始时写入,重启确认补发 result.post 成功后清 0xFF) |
|
||||||
| 250 | 1B | 探测字节(上电写 0xA5 回读,验证 I2C 通信) |
|
| 250 | 1B | 探测字节(上电写 0xA5 回读,验证 I2C 通信) |
|
||||||
|
|
||||||
> 注意:改 `MqttInfo_Str` 结构体会改变上述偏移,秤参数(120+)和联网方式(130)在
|
> 注意:改 `MqttInfo_Str` 结构体会改变上述偏移,秤参数(120+)和联网方式(130)在
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,6 @@ typedef struct {
|
||||||
uint16_t backup_crc16; /* 备份固件 CRC16 */
|
uint16_t backup_crc16; /* 备份固件 CRC16 */
|
||||||
uint8_t backup_valid; /* 槽 A 备份是否有效 */
|
uint8_t backup_valid; /* 槽 A 备份是否有效 */
|
||||||
uint8_t reserved2;
|
uint8_t reserved2;
|
||||||
char ota_id[20]; /* 平台 OTA 任务 id(重启后补发 result.post 用) */
|
|
||||||
uint16_t checksum; /* 前面所有字节累加和 */
|
uint16_t checksum; /* 前面所有字节累加和 */
|
||||||
} W25Q64_OtaInfo;
|
} W25Q64_OtaInfo;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
|
||||||
|
|
@ -159,3 +159,6 @@
|
||||||
在可靠连接上补发 result.post(success=1, 任务id) + confirm.post——平台"完成"标志可正常闭环
|
在可靠连接上补发 result.post(success=1, 任务id) + confirm.post——平台"完成"标志可正常闭环
|
||||||
- 注意:OTA 信息结构变化,BootLoader 的 w25q64.h 已同步,**需 J-Link 刷一次新 BL**
|
- 注意:OTA 信息结构变化,BootLoader 的 w25q64.h 已同步,**需 J-Link 刷一次新 BL**
|
||||||
(旧 BL 读不了新格式,会认不出待安装固件)
|
(旧 BL 读不了新格式,会认不出待安装固件)
|
||||||
|
- OTA 闭环(兼容版):回退 W25Q64 结构改动(BL/APP 共享结构不能动,现场无法刷 BL),
|
||||||
|
平台任务 id 改存 APP 私有 EEPROM(175~194),新固件首启确认时在可靠连接上补发
|
||||||
|
result.post(success=1, 任务id) + confirm.post,送达后清回 0xFF
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue