使用ESP-IDF的HTTP OTA Demo测试,开启蓝牙功能后,HTTP下载速度就非常慢

这类现象在 ESP32/ESP32-S3 上很常见:只要固件里"启用过 BLE(NimBLE/Controller)",哪怕你在 OTA 前调用了 exit,HTTP OTA 仍可能明显变慢。通常是下面两类原因叠加造成的(你对比"直接注释蓝牙功能的固件"更快,这个对比非常关键)。


1)根因 A:BLE 让 Wi-Fi 走"共存"时隙,吞吐必然掉

Wi-Fi 和 BLE 共用同一个 2.4G 射频前端,打开 BLE 后会进入 RF coexist(时分复用)。

尤其当 BLE 在扫描/连接/较短 interval 广播时,会频繁抢占射频,Wi-Fi 可用 airtime 下降,HTTP 下载速度就会掉。

但你说"已经 exit 了还慢",这说明 不止是射频时隙,还有根因 B。


2)根因 B:即使 BLE "退出",Controller 预留内存/任务/共存状态没彻底释放

很多项目里 nimble_port_deinit() + esp_bt_controller_deinit() 之后,BT controller 的内存并不会自动回收到 heap ,而"未启用蓝牙的固件"天然没有这部分常驻占用,所以 OTA 的 lwIP / TCP / esp_http_client 可用的 内部内存更大、更连续,吞吐更高。

你截图里的 hal_eb_ble_exit() 里虽然做了 stop/deinit/controller_disable/deinit,但缺少最关键的一步:mem_release(以及某些 IDF 版本推荐的 controller deinit API)。


✅建议你按下面做(优先级从高到低)

✅1)在 OTA 前彻底关闭 BLE,并释放 BT Controller 内存(最关键)

把 exit 做成"完整关停 + 释放内存"的版本(注意顺序):

复制代码
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_log.h"

void hal_eb_ble_exit_for_ota(void)
{
    // 1) 先停止所有 BLE 行为(广告/扫描/连接)
    //    视你的代码情况调用:ble_gap_adv_stop(), ble_gap_disc_cancel(), 断开连接等

    // 2) 停 NimBLE host task
    nimble_port_stop();
    vTaskDelay(pdMS_TO_TICKS(200));
    nimble_port_deinit();

    // 3) 关 controller(不同 IDF 可能有更推荐的 API)
    esp_bt_controller_disable();
    esp_bt_controller_deinit();

    // 4) ★释放 controller 占用的内存给系统(没有这步,和"注释蓝牙"差距会很大)
    esp_err_t err = esp_bt_controller_mem_release(ESP_BT_MODE_BLE);
    ESP_LOGI("BLE", "mem_release BLE ret=%d", err);

    // 如果你工程里从来不用经典蓝牙,也可以在启动时就释放 CLASSIC 内存:
    // esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
}

你现在测到"编译时注释 BLE 更快",极大概率就是因为这一块 controller 常驻内存没回收,导致 OTA 期间 lwIP/TLS/HTTP 缓冲不足、碎片化更严重。

验证方法:在 OTA 开始前后打印内部 heap 和最大连续块:

复制代码
ESP_LOGI("MEM", "internal free=%u, largest=%u",
         heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
         heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL));

如果加了 mem_release() 后这两个数明显上涨,基本就坐实了。


✅2)如果 OTA 时仍需要 BLE 常开:降低 BLE 对 Wi-Fi 的"射频打扰"

如果你的业务要求 BLE 不能完全关(比如给小程序持续广播),那就只能"让 BLE 更温柔":

  • 停止扫描(scan 对 coexist 影响最大)

  • 广播间隔拉大(比如 100ms→500ms/1000ms)

  • 若连接态:conn interval 拉大(如 30ms→60~120ms),并减少 notify 频率

  • OTA 期间直接 暂停 notify/广播,OTA 完再恢复(最有效)


✅3)把 NimBLE host task 放到另外一个核/降低优先级(减少 CPU 抢占)

Wi-Fi/LwIP 在某些场景对 CPU 调度很敏感。nimble_port_freertos_init() 默认创建 host task,你可以:

  • 把 BLE host task pin 到 core1(Wi-Fi 通常在 core0 更重)

  • 降低 BLE host task priority(不要高过 tcpip、http、ota 相关任务)

(不同 IDF/NimBLE glue 方式不一样,你当前是 nimble_port_freertos_init(ble_host_task),如果你的 ble_host_task 是自己创建的任务,可在创建时 pin/priority。)


✅4)Wi-Fi 侧配置:关省电、提高吞吐稳定性

在 menuconfig 或运行时确保:

  • Wi-Fi power save 关闭(modem sleep 会让吞吐更抖)

    • esp_wifi_set_ps(WIFI_PS_NONE);
  • 信号弱时 BLE coexist 更明显:尽量在 OTA 时保证 RSSI 好一点(>-60dBm)


一句话结论

你现在"exit 了还慢",最像的是:蓝牙 controller 内存没有释放(mem_release 缺失) + coexist 机制/任务调度带来的残余影响

先把 esp_bt_controller_mem_release(ESP_BT_MODE_BLE) 加上再测,通常就能把"和注释蓝牙固件的差距"拉回去一大截。

如果你愿意,把你 OTA 开始前后打印的:

  • internal free / largest block

  • OTA 下载速度(KB/s)

  • 你 BLE 是否处于扫描/连接/仅广播(以及 interval)

相关推荐
鲨莎分不晴2 小时前
HTTP协议全解:从三次握手到HTTP/3的进化史
网络·网络协议·http
G_H_S_3_2 小时前
【网络运维】OpenStack 块存储与对象存储:Cinder 与 Swift 篇
linux·运维·网络·openstack
小鹿学程序3 小时前
IP地址消失
网络·网络协议·tcp/ip
报错小能手3 小时前
当键入网址后,到网页显示,其间发生了什么?
网络·计算机网络
G_H_S_3_3 小时前
【网络运维】Docker网络:基础与实战
linux·运维·网络·docker
Lisonseekpan3 小时前
RBAC 基于角色的访问控制模型详解与实践指南
java·服务器·网络·后端·spring·log4j
开发者导航3 小时前
【开发者导航】完全开源免费且可自托管的私有云盘
网络·开源
网安INF3 小时前
典型网络攻击分析:ARP欺骗与TCP劫持
网络·网络协议·tcp/ip·安全·网络安全
VekiSon3 小时前
Linux网络编程——网络数据封装与 HTTP 协议
网络·网络协议·http