从日志信息可以看出,出现了“BT OSI: config save: NVS not initialized. Call nvs flash init before initializing bluetooth.” 以及 “err code: 0x2” 的错误,这通常表示在初始化蓝牙功能之前,未正确初始化 NVS(Non-Volatile Storage)。在 ESP32 上使用蓝牙(BT/BLE)功能时,需要先完成对 NVS 的初始化,否则就会导致上述错误。
以下是可能的原因及对应的解决思路:
-
在初始化蓝牙之前未调用 nvs_flash_init()
- 在调用任何和蓝牙相关的函数(例如
esp_bt_controller_init()
、esp_bluedroid_init()
)之前,需要先调用nvs_flash_init()
。如果不调用,会导致 NVS 未被初始化而无法正常保存/读取蓝牙配置,从而出现日志中所示错误。 - 典型的初始化流程(简化)通常是:
esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); ESP_ERROR_CHECK(esp_bluedroid_init()); ESP_ERROR_CHECK(esp_bluedroid_enable()); // 后续 BLE/GATT 配置和使用
- 因此,首先要确保
nvs_flash_init()
调用顺利完成且没有报错,然后再初始化 BT 控制器和协议栈。
- 在调用任何和蓝牙相关的函数(例如
-
NVS 分区异常或没有正确分区表
- 如果在
nvs_flash_init()
时持续报错,可能是因为分区表没有正确配置 NVS 分区,或者 NVS 分区与固件中的配置不一致。 - 请确认
partition_table.csv
或partitions.csv
中包含了名为nvs
的分区,并且大小足够(官方示例通常是 0x6000 或更多)。 - 如果在开发过程中频繁修改分区表,也可能导致 NVS 存储数据不兼容,需要先调用
nvs_flash_erase()
再重新初始化。
- 如果在
-
代码中的调用顺序不正确
- 如果确认已正确调用
nvs_flash_init()
,也要检查一下调用顺序是否存在以下问题:- 在
nvs_flash_init()
还没完成时就调用了和蓝牙相关的 API; - 或者重复调用了 BT 初始化函数,而中间没有正确释放或清理资源。
- 在
- 建议在应用启动时尽早完成 NVS 初始化,然后再进行蓝牙初始化的相关步骤。
- 如果确认已正确调用
-
错误码 0x2 的含义
- ESP-IDF 中很多错误码以
ESP_ERR_
开头,0x2 可能对应ESP_ERR_NVS_NOT_FOUND
或者其他与 NVS 读取/写入失败相关的错误。 - 确认下
esp_err_t
返回的具体定义,可以通过idf.py monitor
或使用esp_err_to_name()
函数进行查看。 - 如果是 “not found”,说明尝试读取某个 NVS key 时该 key 并不存在,需要先确保在写入前进行相应的 create/写入操作,或者先擦除后重新写入。
- ESP-IDF 中很多错误码以
总的建议:
- 先确保在 app_main() 中最早的阶段就正确调用
nvs_flash_init()
并检查返回值是否成功。 - 如果报错或 NVS 存储混乱,可以先调用
nvs_flash_erase()
再调用nvs_flash_init()
。 - 在完成 NVS 初始化后,再进行 Bluetooth Controller 与 Bluedroid 的初始化。
- 检查分区表配置,确保有合适大小的
nvs
分区并且没有冲突。
只要保证上述步骤正确且调用顺序没问题,日志中的 BT OSI: config save: NVS not initialized
错误就会消失,蓝牙功能才能正常工作。