小智聊天机器人主程序代码解读
- 源码main.cc:
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();
// Dump CPU usage every 10 second
while (true) {
vTaskDelay(10000 / portTICK_PERIOD_MS);
// SystemInfo::PrintRealTimeStats(pdMS_TO_TICKS(1000));
int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
int min_free_sram = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
ESP_LOGI(TAG, "Free internal: %u minimal internal: %u", free_sram, min_free_sram);
}
}
- 这段代码是一个典型的嵌入式应用程序入口函数
app_main
,通常用于ESP32等基于FreeRTOS的嵌入式系统。下面是对代码的详细讲解:
1. extern "C" void app_main(void)
extern "C"
:这是C++中的链接指示符,用于告诉编译器按照C语言的方式处理函数名。因为ESP-IDF(ESP32的官方开发框架)是用C语言编写的,所以需要使用extern "C"
来确保C++编译器不会对函数名进行名称修饰(name mangling)。app_main
:这是ESP-IDF应用程序的入口函数,类似于C语言中的main
函数。当系统启动时,app_main
会被自动调用。
2. ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_event_loop_create_default()
:这个函数用于创建默认的事件循环(event loop)。事件循环是ESP-IDF中处理事件(如WiFi事件、网络事件等)的核心机制。ESP_ERROR_CHECK
:这是一个宏,用于检查函数返回值是否为ESP_OK
。如果返回值不是ESP_OK
,则会打印错误信息并终止程序。
3. NVS Flash 初始化
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);
nvs_flash_init()
:初始化NVS(Non-Volatile Storage)闪存。NVS用于存储持久化数据,如WiFi配置、设备配置等。ESP_ERR_NVS_NO_FREE_PAGES
和ESP_ERR_NVS_NEW_VERSION_FOUND
:这两个错误码表示NVS闪存可能已损坏或版本不兼容。在这种情况下,代码会擦除NVS闪存并重新初始化。ESP_LOGW(TAG, "Erasing NVS flash to fix corruption")
:打印警告日志,表示正在擦除NVS闪存以修复损坏。nvs_flash_erase()
:擦除NVS闪存。ESP_ERROR_CHECK(ret)
:再次检查NVS闪存初始化是否成功。
4. 启动应用程序
Application::GetInstance().Start();
Application::GetInstance().Start()
:这行代码调用了一个单例类Application
的Start
方法,启动应用程序的主要逻辑。GetInstance()
是单例模式的常见实现方式,确保只有一个Application
实例。
5. 定期打印CPU使用率和内存信息
while (true) {
vTaskDelay(10000 / portTICK_PERIOD_MS);
// SystemInfo::PrintRealTimeStats(pdMS_TO_TICKS(1000));
int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
int min_free_sram = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
ESP_LOGI(TAG, "Free internal: %u minimal internal: %u", free_sram, min_free_sram);
}
while (true)
:这是一个无限循环,用于定期执行某些任务。vTaskDelay(10000 / portTICK_PERIOD_MS)
:让当前任务(Task)延迟10秒。portTICK_PERIOD_MS
是FreeRTOS中表示每个tick的毫秒数。heap_caps_get_free_size(MALLOC_CAP_INTERNAL)
:获取当前内部SRAM(静态随机存取存储器)的可用内存大小。heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL)
:获取内部SRAM的最小可用内存大小(即系统运行过程中内存使用的最低点)。ESP_LOGI(TAG, "Free internal: %u minimal internal: %u", free_sram, min_free_sram)
:打印日志,显示当前和最小可用内存大小。
总结
这段代码的主要功能是初始化ESP32的系统组件(如事件循环和NVS闪存),启动应用程序,并在后台定期打印内存使用情况。代码结构清晰,遵循了ESP-IDF的开发规范,适合用于嵌入式系统的开发。