ESP32程序入口文件解析

源代码阅读指南

一般来说,要阅读一个程序的源代码,我们需要找到程序的入口文件,这里是 main/main.cc。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <esp_log.h>
#include <esp_err.h>
#include <nvs.h>
#include <nvs_flash.h>
#include <driver/gpio.h>
#include <esp_event.h>

#include "application.h"
#include "system_info.h"

#define TAG "main"

//主程序入口函数

在这里,我们可以看到一些头文件的引入(include),以及一些宏定义(define)。

  • <esp_log.h>: 用于日志记录,帮助开发者输出调试信息。
  • <esp_err.h>: 提供错误处理机制,定义了各种错误码。
  • <nvs.h><nvs_flash.h>: 用于管理非易失性存储,常用于保存WiFi配置等信息。
  • <driver/gpio.h>: 提供GPIO的驱动支持,允许控制ESP32的输入输出引脚。
  • <esp_event.h>: 用于事件循环的创建和管理,支持异步事件处理。
  • "application.h": 通常用于定义应用程序的核心逻辑和启动流程。
  • "system_info.h": 可能用于获取系统相关的信息,如设备状态或配置。

主程序代码分析

接下来,我们来分析主程序的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extern "C" void app_main(void)
{
// Initialize the default event loop
ESP_ERROR_CHECK(esp_event_loop_create_default());

// Initialize NVS flash for WiFi configuration
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_LOGW(TAG, "Erasing NVS flash to fix corruption");
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);

// Launch the application
Application::GetInstance().Start();
}

我们先来看看app_main函数的定义。

  • extern "C"是C++的语法,用于告诉编译器这个函数是用C语言编写的。
  • void app_main(void)是主程序的入口函数,所有的程序都从这里开始执行。

进入到主程序的代码块中,我们可以看到以下几个步骤:

  1. 初始化默认的事件循环。
1
ESP_ERROR_CHECK(esp_event_loop_create_default());

这一行代码的具体作用是

  • 创建ESP-IDF框架的默认事件循环系统
  • 使用 ESP_ERROR_CHECK 宏确保初始化成功(如果失败会触发重启)
  • 为后续的事件处理(如WiFi事件、GPIO中断等)提供基础设施
    这是ESP32应用程序的标准初始化步骤之一,位于 app_main() 入口函数中,在NVS闪存初始化之前执行。
  1. 初始化NVS闪存。
1
esp_err_t ret = nvs_flash_init();

这行代码是NVS闪存初始化的关键操作。

  • 初始化ESP32的NVS(Non-Volatile Storage)闪存系统
  • 返回值 ret 用于检查初始化状态

后续代码会处理两种特殊情况:

  • ESP_ERR_NVS_NO_FREE_PAGES :闪存没有空闲页
  • ESP_ERR_NVS_NEW_VERSION_FOUND :发现新版本的NVS格式
  1. 处理NVS闪存初始化的错误恢复逻辑:
1
2
3
4
5
6
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_LOGW(TAG, "Erasing NVS flash to fix corruption");
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
ESP_ERROR_CHECK(ret);
}
  1. 错误检测 :检查NVS初始化返回的错误码是否为以下两种情况之一:
  • ESP_ERR_NVS_NO_FREE_PAGES :闪存没有空闲页
  • ESP_ERR_NVS_NEW_VERSION_FOUND :发现新版本的NVS格式
  1. 错误恢复 :如果检测到错误,执行以下操作:
  • 输出警告日志( ESP_LOGW )
  • 擦除整个NVS分区( nvs_flash_erase )
  • 重新尝试初始化( nvs_flash_init )
    这是ESP32开发中处理NVS闪存问题的标准恢复模式,确保在闪存损坏或格式不兼容时能自动修复。
  1. 启动应用程序:
1
Application::GetInstance().Start();

这行代码是启动应用程序的关键操作。

  • 调用 Application 类的静态方法 GetInstance() 获取应用程序的单例实例
  • 调用 Start() 方法启动应用程序
    这是ESP32应用程序的标准启动流程,位于 app_main() 入口函数的末尾。

NVS是什么?

NVS(Non-Volatile Storage)是ESP32中用于存储非易失性数据的系统。它允许在设备断电后仍然保留数据,通常用于存储配置参数、WiFi凭证等需要持久化的数据。
NVS的主要特点包括:

  1. 非易失性存储:NVS中的数据在断电后不会丢失,即使设备被重启。
  2. 分区支持:NVS可以划分为多个分区,每个分区可以存储不同类型的数据。
  3. 键值存储:NVS使用键值对的方式存储数据,每个键对应一个值。
  4. 数据类型支持:NVS支持多种数据类型,包括整数、浮点数、字符串等。
  5. 读写操作:NVS提供了读写操作的API,允许应用程序读取和写入数据。
  6. 安全性:NVS提供了加密功能,确保数据在存储和传输过程中的安全性。

NVS在ESP32应用程序中广泛用于存储配置信息、WiFi凭证等需要持久化的数据,以确保设备重启后仍然可以恢复这些数据。


本文章发布于 hjq.college,转载请注明出处。