3 Commits

Author SHA1 Message Date
2b4cf82f0c fix(ble): 释放 27 KB DRAM 给 BT controller, 修复手机搜不到 BLE 信号
============ 问题现象 ============

  烧录 f5a2777 (A+B+C 三件套 + BT_ALLOCATION_FROM_SPIRAM_FIRST) 后:
     BOOT 按键可正常进入配网模式 (不再 future_new abort)
     手机搜不到 Kapi 蓝牙信号
    日志:
      E (2240) BLE_INIT: Malloc failed
      E (2240) BT_HCI: CC evt: op=0x2008, status=0x7 (HCI_BLE_WRITE_ADV_DATA)
      代码层 "广播启动成功" 但 ADV_DATA 实际为空, 手机不可见

============ 根因 ============

  CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST 只影响 Bluedroid host 层动态分配,
  不影响 BT controller. 上一次提交修了 host (future_new 不再 NULL),
  但 controller 自己分配 advertising buffer 仍然失败 → ADV_DATA op=0x2008
  malloc fail → 广播空数据.

  size 对比 (Kapi vs Baji 已修好版本):
    Kapi DIRAM .bss = 51152 字节 (54.25%, 剩余 156 KB)
    Baji DIRAM .bss = 23536 字节 (50.58%, 剩余 169 KB)

  差异定位 (per-archive .bss):
    libbt.a       : Kapi 12450 / Baji 0  (Baji 已挪 PSRAM)
    libnet80211.a : Kapi  7570 / Baji 0  (Baji 已挪 PSRAM)
    liblwip.a     : Kapi  4691 / Baji 0  (Baji 已挪 PSRAM)
    libwpa.a      : Kapi  1326 / Baji 0  (Baji 已挪 PSRAM)
    libpp.a       : Kapi  1177 / Baji 0  (Baji 已挪 PSRAM)
    合计 27214 字节 (~27 KB) 都在 Kapi 内部 SRAM, 不在 Baji.

============ 修复 ============

  sdkconfig + sdkconfig.defaults.esp32s3:
    +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
    +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y

  作用: 允许 ESP-IDF linker 把 BT/WiFi/LWIP 等核心库的 .bss 段整体
  搬到 PSRAM, 释放等量内部 SRAM 给 BT controller 启动时分配
  ADV_DATA / SCAN_RSP_DATA / connection state buffer.

============ 验证 (用户实测 2026-05-21) ============

   BOOT 按键进入配网模式, 蓝牙配网音效正常播放
   手机扫描可见 Kapi 蓝牙信号
   蓝牙连接 + WiFi 配置 + 设备重启后自动连 WiFi 成功

  size 实测 (修复后):
    DIRAM .bss: 51152 → 23816 (-27336 字节, -27 KB)
    DIRAM 总占: 185410 → 158114 (54.25% → 46.26%)
    剩余 DIRAM: 156350 → 183646 (+27 KB)
  Flash Data 多出 27 KB .bss (实际放 PSRAM).

============ 移植说明 ============

  本修复需与上次 commit f5a2777 (A+B+C 三件套 + BT_ALLOCATION_FROM_SPIRAM_FIRST)
  搭配使用, 缺一不可:
    - f5a2777 修 host: future_new 不 abort, 可进入配网模式
    - 本次   修 controller: ADV_DATA buffer 可分配, 手机搜得到
    - 加 A方案 LWIP_MAX_SOCKETS=20: 修 RTC 偶发连接失败
    - 加 B方案 ForceRebuildEngine: 兜底 SDK 状态污染
    - 加 C方案 DIAG_RTC_BIND_ENABLE: 一键诊断埋点

  关联文档:
    全局 CLAUDE.md "BLE 配网 DRAM 紧张完整排查流程"
    项目记忆 project_ble_provisioning_issues.md
    Baji commit bffd316 (相同思路在 Baji 验证有效)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 16:03:32 +08:00
f5a2777abf feat(rtc+ble): A+B+C 三件套 RTC 偶发连接失败修复 + BLE 配网 reboot 修复 (移植自 Baji)
============ 问题与修复 ============

### 问题 1: 配网模式按 BOOT 进入配网 → 设备 reboot
  日志:
    E BT_OSI: future_new unable to allocate memory for the semaphore.
    assert failed: future_ready future.c:64 (future != NULL)

  根因:
    BLE Bluedroid 协议栈初始化时, future_new 分配 semaphore 失败 → 后续 future_ready
    拿到 NULL → assert. 跟 Baji 的 vQueueDelete(NULL) 同性质 — DRAM 不足.
    Kapi 用 LVGL (~50-80 KB DRAM) + RTC SDK 静态 .bss (~30-50 KB),
    BLE Bluedroid stack 抢不到所需内存.

  修复 (sdkconfig):
    CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y
    让 BLE Bluedroid 全局变量动态分配优先走 PSRAM, 释放 ~30 KB DRAM
    给 controller / GATT / WiFi 使用. 修复后 BLE 配网正常.

### A+B+C 三件套 (移植自 Baji commit 70f0cdd, 解决 RTC 偶发连接失败)

  [A] sdkconfig: CONFIG_LWIP_MAX_SOCKETS=10 → 20
    根治火山 RTC SDK 启动时 lwIP socket fd 不足触发 SocketConnection-Lite.c:191
    bind local ip failed → ICE 协商失败 → wait connect bits=0x0 超时.

  [B] application.h/cc + volc_rtc_protocol.h/cc: 失败 3 次后销毁 + 重建 engine
    新增 VolcRtcProtocol::ForceRebuildEngine() public 方法.
    application.cc 加 audio_channel_retry_count_ 重试计数,
    OpenAudioChannel 连续失败 3 次时调用 ForceRebuildEngine 清理 SDK 状态.
    应对 A 修复后仍可能出现的 SDK 内部状态污染 (ICE Agent 异常等).

  [C] volc_rtc_protocol.cc: DIAG_RTC_BIND_ENABLE 一键开关诊断埋点
    在 join_room 前/后 + ForceRebuildEngine 前/后打印 lwIP socket fd / heap /
    psram / WiFi rssi / errno, 偶发失败时直接定位根因.
    验证完成后改 0 关闭, 编译器消除 #if 块, 零运行时开销.

============ 文件改动 ============

  sdkconfig:
    +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y    (BLE 配网修复)
    +CONFIG_LWIP_MAX_SOCKETS=10 → 20             (方案 A)

  main/application.h:
    +int audio_channel_retry_count_ = 0;         (RTC 重试计数)

  main/application.cc:
    OpenAudioChannel 失败处加重试计数 + 连续失败 3 次调 ForceRebuildEngine,
    static_cast<VolcRtcProtocol*>(protocol_.get()) (ESP-IDF 默认 -fno-rtti).

  main/protocols/volc_rtc_protocol.h:
    +void ForceRebuildEngine() 声明.

  main/protocols/volc_rtc_protocol.cc:
    +DIAG_RTC_BIND_ENABLE 开关 + diag_count_used_sockets() 工具函数,
    +OpenAudioChannel Pre-Join / Post-Fail DIAG 埋点,
    +ForceRebuildEngine() 实现 (volc_rtc_stop + volc_rtc_destroy + 等 2 秒 + 触发重建).

============ 关联资源 ============
  Baji commit 70f0cdd: feat(rtc): 偶发连接失败完整修复 (A+B+C 三件套)
  Baji commit bffd316: feat(provisioning): BLE 配网完整修复
  全局 CLAUDE.md "BLE 配网 DRAM 紧张完整排查流程" 章节
  项目记忆 project_ble_provisioning_issues.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 15:15:34 +08:00
f3cc5b4f5a chore: 跟踪 sdkconfig 保证多电脑 clone 后可直接编译
.gitignore 移除 sdkconfig 那行 (sdkconfig.old 仍忽略),
首次提交当前 sdkconfig (kapi 软件 AEC + 火山 RTC 已验证配置).

Why: 后续在其他电脑拉取代码时无需 idf.py reconfigure,
     避免 menuconfig 默认值与已验证配置不一致导致项目跑不起来.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:23:40 +08:00