资源占用
资源占用与功能裁剪
本文用于决定"哪些功能要编进固件,哪些功能应关闭"。构建段落、环境列表和宏定义位置见 构建配置;本页只保留资源预算、裁剪策略和交付前检查清单,避免重复维护 platformio.ini 的完整说明。
ESP32 内存背景
| 资源 | ESP32 | ESP32-S3 | ESP32-C3 | ESP32-C6 |
|---|---|---|---|---|
| 内部 SRAM | ~320KB | ~512KB | ~400KB | ~512KB |
| 可用堆(启动后) | ~220KB | ~310KB | ~140KB | ~220KB |
| PSRAM | 4-8MB 可选 | 2-8MB 可选 | 无 | 无 |
| Flash | 4-16MB | 8-16MB | 4MB | 4MB |
关键约束:
- WiFi、lwIP、FreeRTOS、TLS 握手等仍需要内部 DRAM,不能完全依赖 PSRAM。
- PSRAM 适合 HTTP/JSON 缓冲区和较大临时对象,不适合实时性高或硬件要求内部 DRAM 的结构。
- ESP32-C3/C6 的 4MB 无 PSRAM 环境应优先使用 Lite,并关闭未接硬件的显示、网络和高级协议模块。
- 长期运行时最大连续堆比总空闲堆更重要;总空闲 35KB 但最大连续块只有 8KB 时,大对象仍可能分配失败。
内存优化策略
PSRAM 分配阈值
固件通过 heap_caps_malloc_extmem_enable(256) 设置 PSRAM 分配阈值:大于 256 字节的分配优先走 PSRAM(如果有),小于该阈值的分配保留在内部 DRAM。这确保 TLS 缓冲区、JSON 文档等大对象不挤占宝贵的内部堆。
集中管理在 include/core/MemoryBudget.h,关键常量:
| 常量 | 值 | 说明 |
|---|---|---|
PSRAM_ALLOC_THRESHOLD | 256 | PSRAM 分配最小阈值(字节) |
HEAP_WARN_THRESHOLD | 20000 | 堆空闲低于此值触发 WARN |
HEAP_SEVERE_THRESHOLD | 12000 | 堆空闲低于此值触发 SEVERE |
HEAP_CRITICAL_THRESHOLD | 8000 | 堆空闲低于此值触发 CRITICAL |
MQTT_CMD_QUEUE_MAX_BYTES | 4096 | MQTT 命令队列内存上限 |
HealthMonitor 四级保护
HealthMonitor 根据 DRAM 内部空闲量(排除 PSRAM)实施四级保护策略。WiFi、MQTT、TLS 握手等都不能使用 PSRAM,因此 DRAM 空闲才是评估系统稳定性的真实指标。
| 级别 | 条件 | 行为 |
|---|---|---|
| NORMAL | DRAM 空闲 > WARN 阈值 | 正常运行;恢复已停止的服务(MQTT 被禁用除外) |
| WARN | DRAM 空闲 < WARN 阈值 | 日志警告,尝试碎片紧凑化 |
| SEVERE | DRAM 空闲 < 16KB | MQTTS→MQTT 降级 + 停 Modbus + 暂停 PeriphExec |
| CRITICAL | DRAM 空闲 < 8KB | 30s 永久禁用 MQTT + 90s 安全重启(含 boot loop 保护) |
PSRAM 动态阈值
CRITICAL 阈值根据 PSRAM 容量自动调整:无 PSRAM 8KB、4MB PSRAM 10KB、8MB PSRAM 12KB。阈值在首次检测时计算一次,运行时不变。
内存自动恢复机制
当 DRAM 持续下降进入 SEVERE 或 CRITICAL 时,固件自动执行分级恢复,任何情况下 Web 服务保持可用,设备不会变砖。
分级恢复策略
| 触发时机 | 恢复动作 | 持久性 |
|---|---|---|
| SEVERE(DRAM < 16KB) | ① MQTTS→MQTT 降级(释放 ~35KB TLS DRAM) ② 停止 Modbus RTU ③ 暂停 PeriphExec 定时器 | 降级持久;Modbus/PeriphExec 恢复后自动恢复 |
| EMERGENCY(DRAM < 4KB) | 立即执行全部 SEVERE 恢复 + 永久禁用 MQTT,不等计时 | 持久 |
| CRITICAL 持续 30s | 写入 protocol.json 设置 mqtt.enabled=false + 停止 MQTT | 持久:重启后 MQTT 不连,用户手动在 Web 开启 |
| CRITICAL 持续 90s | 安全重启(MQTT 已禁用,重启后内存充裕) | 重启后系统恢复 |
| NORMAL 恢复(DRAM > 30KB) | 恢复 Modbus + PeriphExec;MQTT 被禁用时不自动恢复 | 用户手动开启 MQTT |
防砖保护
| 机制 | 说明 |
|---|---|
| Web 服务永不停止 | 所有降级级别中 Web 服务器始终保持运行;SSE 在 SEVERE 时关闭以节省内存,但 Web 核心保持响应 |
| 重启循环保护 | 启动 < 120s 内不执行 90s 重启,防止"启动→CRITICAL→重启"死循环 |
| 紧急释放兜底 | DRAM < 4KB 时不等 30s 计时,立即禁用 MQTT + 停止所有非 Web 服务 |
| MQTT 永久禁用 | CRITICAL 30s 写入 mqtt.enabled=false,重启后 MQTT 不连,用户需通过 Web 手动开启 |
| 配置写入失败安全退出 | protocol.json 写入失败时跳过降级操作,不标记已完成,避免状态不一致 |
串口日志格式
每个恢复动作输出 [MEMRECOVER] 前缀的结构化日志,便于串口排查:
[MEMRECOVER] === SEVERE recovery triggered === dram=15832 largest=4096 frag=74%
[MEMRECOVER] Step 1/3: MQTTS -> MQTT downgrade (releasing ~35KB TLS DRAM)
[MEMRECOVER] protocol.json updated: scheme=mqtt, port=1883
[MEMRECOVER] DRAM after downgrade: 48216 bytes
[MEMRECOVER] Step 2/3: Modbus stopped (was running)
[MEMRECOVER] Step 3/3: PeriphExec timers paused
[MEMRECOVER] === SEVERE recovery complete === dram=48216 (gained 32384 bytes)
[MEMRECOVER] === CRITICAL 30s: disabling MQTT permanently ===
[MEMRECOVER] protocol.json updated: mqtt.enabled=false
[MEMRECOVER] MQTT stopped (will NOT reconnect after reboot)
[MEMRECOVER] === Recovery summary before reboot ===
[MEMRECOVER] Uptime: 3600s, CRITICAL duration: 90s
[MEMRECOVER] Actions taken: MQTTS->MQTT(SEVERE) Modbus stopped PeriphExec paused MQTT disabled(30s)
[MEMRECOVER] DRAM: current=6144 largest=2048
[MEMRECOVER] Reboot reason: DRAM<8KB for 90s, all recovery exhausted恢复状态 API
/api/system/health 接口的 memguard 字段包含恢复状态标志:
{
"memguard": {
"level": 2,
"level_name": "SEVERE",
"mqtts_downgraded": true,
"mqtt_stopped": false,
"mqtt_disabled": false,
"modbus_stopped": true,
"periph_exec_paused": true,
"critical_duration_s": 0
}
}内存池管理
- StringBufferPool:模板缓冲池
StringBufferPool<BufSize, PoolCount>,用于 Modbus 等重复缓冲区场景,避免频繁 new/delete 导致碎片。 - Modbus 缓冲池:PSRAM 设备 8 个槽位,无 PSRAM 设备 4 个槽位,条件编译控制。
- MQTT 命令队列:总字节数跟踪
_cmdQueueTotalBytes,超过 4096 字节时丢弃新命令,防止队列无限增长。
PSRAM JSON 分配器
配置保存等大 JSON 操作使用 FastBee::makeJsonDocument(8192),在有 PSRAM 时自动分配到 PSRAM,避免内部堆峰值。
MQTTS(TLS) 内存影响
MQTTS 使用 WiFiClientSecure 进行 TLS 握手,单次连接需要 ~20-40KB 额外内存。内存优化措施:
- WiFiClientSecure 实例按需创建(
new),连接断开后立即释放(delete) - 无 PSRAM 设备 mqtts 连接失败后进入慢速退避,避免反复消耗
- TLS 传输层生命周期独立管理,
releaseTlsTransport()确保及时释放
功能开关方法
功能开关通过 platformio.ini 的 build_flags 设置:
build_flags =
-DFASTBEE_ENABLE_XXX=1 ; 启用
-DFASTBEE_ENABLE_XXX=0 ; 禁用默认值定义在 include/core/FeatureFlags.h,platformio.ini 中的值会覆盖默认值。通常先选择 lite_flags、standard_flags 或 full_flags,再在具体 [env:*] 中覆盖少量项目。
优先裁剪顺序
| 优先级 | 模块 | 建议 |
|---|---|---|
| 1 | BLE | Full 预设保留 FASTBEE_ENABLE_BLE=1,但当前没有完整 BLE 配网页面和处理链路;交付默认不要依赖 |
| 2 | 4G / 以太网 | 未接硬件就关闭;标准版默认关闭 4G 和以太网 |
| 3 | TCP / HTTP / CoAP | 仅 Full 或明确需要设备主动连接外部服务时启用 |
| 4 | OTA / 文件管理 / 文件日志 / 用户角色 | 交付版按维护需求开启,4MB 环境默认不启用 OTA |
| 5 | LCD/OLED、NeoPixel、LED 点阵、RFID、红外、I2C 高级传感器 | 未接模块就关闭;量产配置不要为预留硬件提前启用 |
| 6 | 规则脚本 / 命令脚本 | 需要现场自动化和脚本能力时开启;低内存环境优先用固定动作 |
模块资源预算
以下为估算值,用于选型和裁剪决策;实际占用以当前编译输出和运行时 /api/system/info 为准。
外设与显示
| 开关宏 | RAM | Flash | 预设 | 说明 |
|---|---|---|---|---|
FASTBEE_ENABLE_LCD | ~1.2KB | ~20KB | Lite/Standard/Full 默认启用 | OLED/LCD,依赖 U8g2 |
FASTBEE_ENABLE_NEOPIXEL | ~2KB + 3B/颗 | ~12KB | 默认启用 | WS2812 灯带;可用 FASTBEE_NEOPIXEL_MAX_LEDS 降低上限 |
FASTBEE_ENABLE_LED_SCREEN | 动态分配 | ~10KB | Standard/Full | WS2812B 点阵屏 |
FASTBEE_ENABLE_I2C_SENSORS | ~500B | ~15KB | Standard/Full | BMP280、MPU6050、SHT31、BH1750、AHT20 等 |
FASTBEE_ENABLE_RFID | ~200B | ~12KB | Standard/Full | MFRC522 |
FASTBEE_ENABLE_IR_REMOTE | ~300B | ~8KB | Standard,S3 禁用 | ESP32-S3 与 IRremoteESP8266 RMT 驱动冲突 |
FASTBEE_ENABLE_SENSOR_DRIVER | ~200B | ~8KB | 默认启用 | DHT、DS18B20 等基础传感器 |
FASTBEE_ENABLE_SEVEN_SEGMENT | ~32B/实例 | ~3KB | 默认启用 | TM1637 数码管 |
FASTBEE_ENABLE_DS1302 | ~100B | ~2KB | 默认关闭 | 有 NTP 时通常不必启用 |
FASTBEE_ENABLE_LCD1602 | ~100B | ~3KB | 默认关闭 | LCD1602/LCD2004 I2C 字符屏 |
网络与协议
| 开关宏 | RAM | Flash | 预设 | 说明 |
|---|---|---|---|---|
FASTBEE_ENABLE_MQTT | ~4-8KB | ~15KB | 默认启用 | 平台通信核心能力;mqtts 额外需 ~20-40KB(TLS) |
FASTBEE_ENABLE_MODBUS | ~3-5KB | ~20KB | Standard/Full | 工业现场常用 |
FASTBEE_MODBUS_SLAVE_ENABLE | ~440B | ~10KB | Full | 依赖 FASTBEE_ENABLE_MODBUS=1 |
FASTBEE_ENABLE_TCP | ~2-3KB | ~10KB | Full | 原生 TCP 服务 |
FASTBEE_ENABLE_HTTP | ~2KB | ~8KB | Full | HTTP 客户端 |
FASTBEE_ENABLE_COAP | ~1KB | ~12KB | Full | CoAP 协议 |
FASTBEE_ENABLE_ETHERNET | ~8KB | ~8KB | Full | W5500,以太网硬件未接时关闭 |
FASTBEE_ENABLE_CELLULAR | ~10-15KB | ~15KB | Full | EC801E 4G,RAM 占用高 |
FASTBEE_ENABLE_BLE | ~20-30KB | ~80KB | Full 预留 | 当前无完整 BLE 配网页面和处理链路;启用前需补齐依赖和验证 |
FASTBEE_ENABLE_MDNS | ~2KB | ~5KB | 默认启用 | 禁用后不能用 fastbee.local |
FASTBEE_ENABLE_DNS | ~1KB | ~3KB | 默认启用 | AP 配网页面常用 |
FASTBEE_ENABLE_AP_MODE | ~1-2KB | ~2KB | 默认启用 | 禁用后首次配网能力受影响 |
系统与 Web
| 开关宏 | RAM | Flash | 预设 | 说明 |
|---|---|---|---|---|
FASTBEE_ENABLE_WEB_SERVER | ~20-30KB | ~25KB | 默认启用 | Web 控制台和 REST API 核心 |
FASTBEE_ENABLE_PERIPH_EXEC | ~2-4KB | ~8KB | 默认启用 | 定时、事件、平台触发等自动化规则 |
FASTBEE_ENABLE_RULE_SCRIPT | ~4-8KB | ~8KB | Standard/Full | 规则脚本引擎 |
FASTBEE_ENABLE_COMMAND_SCRIPT | ~1-2KB | ~3KB | 继承规则脚本 | 命令脚本 |
FASTBEE_ENABLE_OTA / FASTBEE_ENABLE_OTA_FS | ~4-6KB | ~10KB | Full | Flash >= 8MB 才适合开启 |
FASTBEE_ENABLE_STORAGE_CACHE | ~2-4KB | ~1KB | 默认关闭 | 大配置文件会绕过缓存,避免峰值翻倍 |
FASTBEE_ENABLE_FILE_LOGGING | ~500B | ~3KB | Full | 持续写 Flash 会影响寿命 |
FASTBEE_ENABLE_USER_ADMIN | ~500B | ~5KB | Full | 多用户管理 |
FASTBEE_ENABLE_FILE_MANAGER | ~500B | ~3KB | Full | 文件管理器 |
FASTBEE_ENABLE_HEALTH_MONITOR | ~200B | ~4KB | 默认启用 | 不建议关闭;四级堆保护策略 |
FASTBEE_ENABLE_LOGGER | ~300B | ~6KB | 默认启用 | 可调小 FASTBEE_LOG_BUFFER_SIZE |
性能调优参数
| 参数 | 建议 | 说明 |
|---|---|---|
FASTBEE_USE_PSRAM / BOARD_HAS_PSRAM | 只在真实带 PSRAM 的环境开启 | 配合 heap_caps_malloc_extmem_enable(256) 将较大 HTTP/JSON 分配优先放到 PSRAM |
FASTBEE_JSON_DOC_SIZE | 低内存环境可从 4096/8192 下调 | 减少 JSON 文档峰值,但不能小到影响配置解析 |
CONFIG_ASYNC_TCP_MAX_CONNECTIONS | C3/C6 保守,S3+PSRAM 可提高 | 每个连接会消耗内部 DRAM 和 lwIP PCB |
ARDUINO_LOOP_STACK_SIZE | Modbus、配置保存、脚本路径需保持足够栈 | 栈溢出会表现为 Stack canary watchpoint triggered |
FASTBEE_STRIP_INFO_LOGS | 生产建议 1 | 编译期剥离 INFO 日志字符串,节省 Flash |
FASTBEE_DEBUG_LOG / CORE_DEBUG_LEVEL | 生产保持低级别 | 调试日志会增加 Flash 和运行时输出压力 |
典型配置方案
ESP32-C3/C6 4MB 精简版
目标是保留 MQTT、Web/API、基础 GPIO/传感器和 AP 配网,关闭 Modbus、OTA、脚本、4G/以太网、显示和高级外设。若不使用灯带,也关闭 NeoPixel:
-DFASTBEE_ENABLE_MODBUS=0
-DFASTBEE_ENABLE_OTA=0
-DFASTBEE_ENABLE_RULE_SCRIPT=0
-DFASTBEE_ENABLE_COMMAND_SCRIPT=0
-DFASTBEE_ENABLE_LCD=0
-DFASTBEE_ENABLE_NEOPIXEL=0
-DFASTBEE_ENABLE_I2C_SENSORS=0
-DFASTBEE_STRIP_INFO_LOGS=1
-DFASTBEE_LOG_BUFFER_SIZE=128注意:无 PSRAM 的 C3/C6 设备不建议使用 mqtts(TLS),请选择 mqtt 协议。
ESP32 4MB 标准版
目标是 WiFi + MQTT + Modbus + 基础外设。标准预设已关闭 4G、以太网、BLE、TCP/HTTP/CoAP 和 OTA;再按实际接线关闭显示、RFID、红外等未使用模块。
-DFASTBEE_ENABLE_OTA=0
-DFASTBEE_ENABLE_ETHERNET=0
-DFASTBEE_ENABLE_CELLULAR=0
-DFASTBEE_ENABLE_LCD=0
-DFASTBEE_ENABLE_RFID=0
-DFASTBEE_ENABLE_IR_REMOTE=0注意:标准 ESP32 无 PSRAM 时 mqtts 可能失败,建议使用 mqtt。
ESP32-S3/ESP32 带 PSRAM 全功能版
目标是完整联网能力、OTA、文件/日志和高级规则。Full 默认启用 4G、以太网,并保留 BLE 编译开关;未接 4G、以太网时应主动关闭对应宏,BLE 未补齐实现前也建议关闭。
-DFASTBEE_USE_PSRAM=1
-DBOARD_HAS_PSRAM
-DFASTBEE_ENABLE_BLE=0提示:带 PSRAM 的设备可正常使用 mqtts(TLS),TLS 缓冲区自动分配到 PSRAM。
资源上限参考
| 参数 | ESP32-C3 Lite | ESP32 Standard | ESP32-S3 Full |
|---|---|---|---|
| 最大外设数 | 16 | 24 | 32 |
| 推荐执行规则数 | 12 | 16 | 32 |
| 传感器缓存条目 | 16 | 24 | 32 |
| TCP 并发预算 | 4 | 6 | 8 |
| SSE 连接预算 | 1 | 1 | 2 |
| HTTP 连接预算 | 3 | 5 | 6 |
| TCP 耗尽阈值 | 10 | 12 | 14 |
| MQTT 命令队列上限 | 4096B | 4096B | 4096B |
| Modbus 缓冲池 | 4 槽 | 4 槽 | 8 槽(PSRAM) |
配置检查清单
- 确认硬件实际连接了哪些外设模块。
- 确认需要的联网方式:WiFi、以太网或 4G。
- 确认协议需求:MQTT 通常保留,Modbus/TCP/HTTP/CoAP 按需开启。
- Flash 小于 8MB 时不要启用 OTA。
- 有 PSRAM 的环境才启用
FASTBEE_USE_PSRAM=1和BOARD_HAS_PSRAM。 - 未连接的外设、网络模块和管理功能默认关闭。
- 需要 BLE 时同步确认依赖、源码入口、Web/API 能力、配网流程和资源验证;当前设备端默认使用 WiFi AP/Web 配网。
- 修改后执行
pio run -e <环境名>,并检查编译输出的 RAM/Flash 使用量。 - 烧录后通过仪表盘或
/api/system/info查看heapFree、heapMaxAlloc、PSRAM 和功能档位是否符合预期。 - 无 PSRAM 设备如需加密通信,评估是否改用外部 TLS 代理或 VPN,而非设备端 mqtts。
