From 0b51d84a9b6c6cead701f1fe52cac54c12e23669 Mon Sep 17 00:00:00 2001 From: wangfq Date: Thu, 20 Aug 2026 13:41:33 +0800 Subject: [PATCH] =?UTF-8?q?perf(vd960DBN):=20OTA=20RAM=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E2=80=94=20union=20=E5=A4=8D=E7=94=A8=E5=9D=97?= =?UTF-8?q?=E7=BC=93=E5=86=B2=20+=20=E5=91=BD=E4=BB=A4=E5=88=86=E6=94=AF?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E6=94=B9=20static?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MRS 编译 RAM 90.02% (44248/48KB) 逼近历史 .bss 挤栈红线, 减负: - ota_srv.c: _chunk_buf[256] + _fs_frame[254] 合并为 union (下载/校验与刷写帧 互斥复用, 省 ~260B static); ota_send_9f 组帧直接用 union 缓冲 (省 254B 栈) - iot_mqtt_srv.c: 6 个 ota_* 分支 resp[256~400] + ota_data hexbuf[513] 局部栈 数组改 static (栈峰值 → BSS, 防运行时栈溢出; RAM 总量不变但运行时安全) 验证: gcc 隔离单测 9/9 全过; 语法 0 新增错误 --- .../APP/iot_mqtt_srv.c | 14 +++---- .../OnlyUpdateApp_Peripheral/APP/ota_srv.c | 41 ++++++++++--------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c index 84b9d86..faf5ed4 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c @@ -710,7 +710,7 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_ } else if (strcmp(cmd_str, "ota_begin") == 0) { /* V1.08: 开启 OTA 会话 / 断点续传定位 (Loop MCU 远程 OTA, 先存后刷) */ - char resp[400]; + static char resp[400]; /* static: RAM 90% 下防栈峰值 (历史 .bss 挤栈事故) */ uint32_t size = 0, crc32 = 0; char version[16] = {0}; uint8_t force = 0; @@ -750,8 +750,8 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_ } else if (strcmp(cmd_str, "ota_data") == 0) { /* V1.08: 分片下发 (256B/片, 单片 CRC32; 重复片幂等, 乱序拒收指示续传) */ - char resp[400]; - char hexbuf[512 + 1]; + static char resp[400]; + static char hexbuf[512 + 1]; /* 512 hex 最大, static 防栈峰值 */ const char *hp; uint32_t offset = 0, crc32 = 0; int rc; @@ -793,7 +793,7 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_ } else if (strcmp(cmd_str, "ota_end") == 0) { /* V1.08: 结束下载, 全镜像 CRC32 复核 */ - char resp[300]; + static char resp[300]; uint32_t crc32 = 0; int rc; memset(tmp, 0, sizeof(tmp)); @@ -827,7 +827,7 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_ } else if (strcmp(cmd_str, "ota_abort") == 0) { /* V1.08: 中止会话, 释放暂存 */ - char resp[256]; + static char resp[256]; int rc = ota_cmd_abort(); snprintf(resp, sizeof(resp), "{\"msg_id\":%lu,\"cmd\":\"ota_abort\",\"ts\":%lu,\"code\":%d,\"msg\":\"%s\"}", @@ -837,7 +837,7 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_ } else if (strcmp(cmd_str, "ota_flash") == 0) { /* V1.08: 触发本地 ISP 刷写 (同步安全检查 → 异步执行) */ - char resp[300]; + static char resp[300]; char slot_buf[8] = {0}; uint8_t slot = 0, force = 0; int rc; @@ -868,7 +868,7 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_ } else if (strcmp(cmd_str, "ota_status") == 0) { /* V1.08: 查询 OTA 状态 (含刷写进度) */ - char resp[400]; + static char resp[400]; const OtaMeta *m = ota_meta(); snprintf(resp, sizeof(resp), "{\"msg_id\":%lu,\"cmd\":\"ota_status\",\"ts\":%lu,\"code\":0,\"msg\":\"success\"," diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/ota_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/ota_srv.c index e01bfed..ad1ff6b 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/ota_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/ota_srv.c @@ -46,9 +46,11 @@ static uint32_t _fs_block_crc; /* 当前块 CRC (调试/审计) */ uint8_t g_ota_flash_active = 0; /* 本地刷写进行中 → uart_srv 把 ACK 交给 ota_srv */ -/* 块缓冲 (static: 栈紧张教训) */ -static uint8_t _chunk_buf[OTA_CHUNK_SIZE]; /* 下载片缓冲 */ -static uint8_t _fs_frame[5 + OTA_FLASH_BLOCK + 1]; /* A7 帧: 9F+SubL+SubH+LEN+CMD+DATA+CHECK */ +/* 块缓冲 (static: 栈紧张教训; union: 下载片 256B 与 A7 帧 254B 互斥复用, 省 ~260B RAM) */ +static union { + uint8_t chunk[OTA_CHUNK_SIZE]; /* 下载片缓冲 / 校验读缓冲 */ + uint8_t frame[5 + OTA_FLASH_BLOCK + 1]; /* A7 帧: 9F+SubL+SubH+LEN+CMD+DATA+CHECK */ +} _ota_buf; /*=========================================================================== * CRC-32/ISO-HDLC (协议 §4.19.1; 逐位实现, 零查表 RAM) @@ -275,15 +277,15 @@ int ota_cmd_data(uint32_t offset, uint32_t crc32, const char *hex) clen = _meta.size - offset; if (clen > OTA_CHUNK_SIZE) clen = OTA_CHUNK_SIZE; - if (ota_hex_decode(hex, _chunk_buf, clen) != 0) { + if (ota_hex_decode(hex, _ota_buf.chunk, clen) != 0) { return 1; /* hex 格式错误 */ } - if (ota_crc32(_chunk_buf, clen) != crc32) { + if (ota_crc32(_ota_buf.chunk, clen) != crc32) { return 1; /* 单片 CRC 失败 */ } /* 落盘: SPI_Flash_Write 自带"目标区非 0xFF 则读-改-写擦扇区" (256B 页对齐) */ - SPI_Flash_Write(_chunk_buf, _slot_base + offset, (uint16_t)clen); + SPI_Flash_Write(_ota_buf.chunk, _slot_base + offset, (uint16_t)clen); _meta.received = offset + clen; ota_meta_flush(); PRINT("OTA: data@%lu crc_ok received=%lu\n", @@ -313,8 +315,8 @@ int ota_cmd_end(uint32_t crc32) while (i < _meta.size) { uint32_t n = _meta.size - i; if (n > OTA_CHUNK_SIZE) n = OTA_CHUNK_SIZE; - SPI_Flash_Read(_chunk_buf, _slot_base + i, (uint16_t)n); - total = ota_crc32_update(total, _chunk_buf, n); + SPI_Flash_Read(_ota_buf.chunk, _slot_base + i, (uint16_t)n); + total = ota_crc32_update(total, _ota_buf.chunk, n); i += n; } total ^= 0xFFFFFFFFu; @@ -407,18 +409,17 @@ int ota_cmd_flash(uint8_t slot, uint8_t force) static void ota_send_9f(uint8_t sub_l, uint8_t sub_h, uint8_t cmd, const uint8_t *data, uint16_t datalen) { - uint8_t frame[5 + OTA_FLASH_BLOCK + 1]; uint16_t i; uint8_t sum = 0; - frame[0] = 0x9F; - frame[1] = sub_l; - frame[2] = sub_h; - frame[3] = (uint8_t)(1 + datalen); /* LEN 含 CMD */ - frame[4] = cmd; - if (data && datalen) memcpy(&frame[5], data, datalen); - for (i = 1; i < 5 + datalen; i++) sum += frame[i]; /* SubL..DATA */ - frame[5 + datalen] = sum; - UART2_SendString(frame, (uint16_t)(5 + datalen + 1)); + _ota_buf.frame[0] = 0x9F; + _ota_buf.frame[1] = sub_l; + _ota_buf.frame[2] = sub_h; + _ota_buf.frame[3] = (uint8_t)(1 + datalen); /* LEN 含 CMD */ + _ota_buf.frame[4] = cmd; + if (data && datalen) memcpy(&_ota_buf.frame[5], data, datalen); + for (i = 1; i < 5 + datalen; i++) sum += _ota_buf.frame[i]; /* SubL..DATA */ + _ota_buf.frame[5 + datalen] = sum; + UART2_SendString(_ota_buf.frame, (uint16_t)(5 + datalen + 1)); } /* 刷写失败收尾: 状态落盘 + event_report 告警 + 恢复 0x7F 模式 */ @@ -566,9 +567,9 @@ void ota_poll(void) uint32_t read_off = _fs_sent; uint32_t remain = _meta.size - read_off; uint16_t datalen = (remain > OTA_FLASH_BLOCK) ? OTA_FLASH_BLOCK : (uint16_t)remain; - SPI_Flash_Read(_fs_frame + 5, _slot_base + read_off, datalen); + SPI_Flash_Read(_ota_buf.frame + 5, _slot_base + read_off, datalen); ota_send_9f((uint8_t)(_fs_sub & 0xFF), (uint8_t)(_fs_sub >> 8), 0xA7, - _fs_frame + 5, datalen); + _ota_buf.frame + 5, datalen); _fs = OTA_FLASH_WAIT_ACK; _fs_start_ms = now; PRINT("OTA: sent A7 sub=%u off=%lu datalen=%u\n",