2026-07-15 02:23:25 +08:00
|
|
|
|
/*
|
2026-04-27 00:42:26 +08:00
|
|
|
|
* ESP32-C3FH4 OTA 中继 - 程序入口
|
2026-07-16 23:00:15 +08:00
|
|
|
|
* FreeRTOS 任务:健康监控 / OTA Relay / WiFi Server / BLE GATT / CAN 反馈
|
2026-05-31 03:20:26 +08:00
|
|
|
|
*
|
2026-07-16 23:00:15 +08:00
|
|
|
|
* 使用各模块单例初始化并创建任务;入口只做装配,不实现协议。
|
2026-04-27 00:42:26 +08:00
|
|
|
|
*/
|
|
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
|
|
#include "freertos/task.h"
|
|
|
|
|
|
#include "esp_chip_info.h"
|
2026-04-28 01:06:17 +08:00
|
|
|
|
#include "esp_system.h"
|
|
|
|
|
|
#include "esp_netif.h"
|
2026-05-05 03:28:44 +08:00
|
|
|
|
#include "esp_event.h"
|
2026-06-14 17:10:24 +08:00
|
|
|
|
#include "esp_ota_ops.h"
|
2026-04-27 00:42:26 +08:00
|
|
|
|
|
2026-04-27 02:34:47 +08:00
|
|
|
|
#include "monitor/health_monitor.h"
|
2026-07-16 01:24:12 +08:00
|
|
|
|
#include "monitor/cpu_stats.h"
|
2026-04-27 02:34:47 +08:00
|
|
|
|
#include "relay/ota_relay.h"
|
2026-06-17 02:18:42 +08:00
|
|
|
|
#include "ota/ota_coordinator.h"
|
2026-04-27 02:34:47 +08:00
|
|
|
|
#include "transport/spi_master.h"
|
|
|
|
|
|
#include "server/wifi_ota.h"
|
|
|
|
|
|
#include "server/ble_ota.h"
|
|
|
|
|
|
#include "transport/protocol.h"
|
|
|
|
|
|
#include "monitor/debug_log.h"
|
2026-06-14 17:10:24 +08:00
|
|
|
|
#include "app_config.h"
|
2026-06-22 01:53:16 +08:00
|
|
|
|
#include "ota/esp32_ota_core.h"
|
2026-06-29 01:51:44 +08:00
|
|
|
|
#include "monitor/can_feedback_task.h"
|
2026-04-27 00:42:26 +08:00
|
|
|
|
|
2026-05-05 04:48:31 +08:00
|
|
|
|
/**
|
2026-07-16 23:00:15 +08:00
|
|
|
|
* @brief 创建关键任务;失败则打 ERR 并 ESP_ERROR_CHECK 触发重启。
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void createCriticalTask(TaskFunction_t entry, const char *name,
|
|
|
|
|
|
uint32_t stack, UBaseType_t prio)
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseType_t xRet = xTaskCreatePinnedToCore(
|
|
|
|
|
|
entry, name, stack, NULL, prio, NULL, 0);
|
|
|
|
|
|
if (xRet != pdPASS) {
|
|
|
|
|
|
DEBUG_ERR("MAIN", "创建关键任务 %s 失败", name);
|
|
|
|
|
|
ESP_ERROR_CHECK(ESP_FAIL);
|
|
|
|
|
|
}
|
|
|
|
|
|
DEBUG_INFO("MAIN", "任务已创建: %s (prio=%u stack=%lu)",
|
|
|
|
|
|
name, (unsigned)prio, (unsigned long)stack);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 程序主入口:初始化组件并创建 FreeRTOS 任务。
|
2026-05-05 04:48:31 +08:00
|
|
|
|
*/
|
2026-04-27 02:34:47 +08:00
|
|
|
|
extern "C" void app_main(void)
|
2026-04-27 00:42:26 +08:00
|
|
|
|
{
|
|
|
|
|
|
esp_chip_info_t chip_info;
|
|
|
|
|
|
esp_chip_info(&chip_info);
|
2026-05-05 03:28:44 +08:00
|
|
|
|
|
2026-06-22 01:53:16 +08:00
|
|
|
|
Esp32OtaCore::initMutex();
|
2026-06-14 17:10:24 +08:00
|
|
|
|
|
2026-05-05 03:28:44 +08:00
|
|
|
|
ESP_ERROR_CHECK(esp_netif_init());
|
|
|
|
|
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
|
|
|
|
|
|
2026-05-31 03:20:26 +08:00
|
|
|
|
DebugLog::instance().init();
|
2026-05-05 03:28:44 +08:00
|
|
|
|
|
2026-07-16 23:00:15 +08:00
|
|
|
|
/* earlyInit:true=已启动 STA 连接流程;false=将走 AP(或 CONFIG 直选 AP) */
|
|
|
|
|
|
const bool wifi_early_started_sta = WifiOta::instance().earlyInit();
|
2026-05-05 03:28:44 +08:00
|
|
|
|
|
2026-05-31 03:20:26 +08:00
|
|
|
|
HealthMonitor::instance().init();
|
2026-05-05 03:28:44 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "健康监控状态已初始化");
|
2026-04-27 00:42:26 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "========================================");
|
2026-07-16 23:00:15 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "ESP32-C3 OTA Relay %s 启动", FW_VERSION);
|
2026-04-27 00:42:26 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "Chip: %s, Rev %d", CONFIG_IDF_TARGET, chip_info.revision);
|
2026-07-16 23:00:15 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "Free heap: %lu bytes", (unsigned long)esp_get_free_heap_size());
|
2026-04-28 01:06:17 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "CPU Freq: %d MHz", CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ);
|
2026-07-16 23:00:15 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "WiFi early: %s(最终 STA/AP 由 wifi_ota 任务确认)",
|
|
|
|
|
|
wifi_early_started_sta ? "STA 连接中" : "非 STA 优先/将切 AP");
|
2026-04-27 00:42:26 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "========================================");
|
|
|
|
|
|
|
2026-07-16 23:00:15 +08:00
|
|
|
|
/* 健康监控:温度/RSSI;缺失则运维盲区 → 关键 */
|
|
|
|
|
|
createCriticalTask(HealthMonitor::taskEntry, "health_mon",
|
|
|
|
|
|
TASK_STACK_HEALTH_MON, configMAX_PRIORITIES - 4);
|
2026-04-27 02:34:47 +08:00
|
|
|
|
|
2026-07-16 23:00:15 +08:00
|
|
|
|
/* CPU 1Hz 采样:非致命 */
|
2026-07-16 01:24:12 +08:00
|
|
|
|
CpuStats::instance().start();
|
|
|
|
|
|
|
2026-05-31 03:20:26 +08:00
|
|
|
|
Protocol::instance().init();
|
2026-04-27 00:42:26 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "协议层初始化完成");
|
|
|
|
|
|
|
2026-06-17 02:18:42 +08:00
|
|
|
|
OtaCoordinator::instance().init();
|
2026-06-22 01:53:16 +08:00
|
|
|
|
OtaCoordinator::instance().setBleCoexListener(&WifiOta::instance());
|
2026-06-17 02:18:42 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "OTA 全局协调器已初始化");
|
|
|
|
|
|
|
2026-07-16 23:00:15 +08:00
|
|
|
|
/* SPI 是中继/CAN 反馈根基:失败则无法完成核心职责,按关键失败处理 */
|
|
|
|
|
|
{
|
|
|
|
|
|
esp_err_t ret = SpiMaster::instance().init();
|
|
|
|
|
|
if (ret != ESP_OK) {
|
|
|
|
|
|
DEBUG_ERR("MAIN", "SPI 总线初始化失败: %s", esp_err_to_name(ret));
|
|
|
|
|
|
ESP_ERROR_CHECK(ret);
|
|
|
|
|
|
}
|
2026-04-27 00:42:26 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "SPI 总线初始化完成");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 23:00:15 +08:00
|
|
|
|
createCriticalTask(OtaRelay::taskEntry, "ota_relay",
|
|
|
|
|
|
TASK_STACK_OTA_RELAY, configMAX_PRIORITIES - 2);
|
2026-04-27 00:42:26 +08:00
|
|
|
|
|
2026-07-16 23:00:15 +08:00
|
|
|
|
createCriticalTask(WifiOta::taskEntry, "wifi_ota",
|
|
|
|
|
|
TASK_STACK_WIFI_OTA, configMAX_PRIORITIES - 3);
|
2026-04-27 00:42:26 +08:00
|
|
|
|
|
2026-07-16 23:00:15 +08:00
|
|
|
|
createCriticalTask(BleOta::taskEntry, "ble_ota",
|
|
|
|
|
|
TASK_STACK_BLE_OTA, configMAX_PRIORITIES - 3);
|
2026-04-27 00:42:26 +08:00
|
|
|
|
|
2026-06-29 01:51:44 +08:00
|
|
|
|
if (startCanFeedbackTask()) {
|
|
|
|
|
|
DEBUG_INFO("MAIN", "CAN 反馈轮询任务已创建");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
DEBUG_WARN("MAIN", "CAN 反馈轮询任务创建失败(非致命,OTA 不受影响)");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 23:00:15 +08:00
|
|
|
|
/* 任务就绪后尽快标记 app 有效,避免后续探测拖太久导致回滚窗口拉长 */
|
|
|
|
|
|
{
|
|
|
|
|
|
esp_err_t ota_valid_err = esp_ota_mark_app_valid_cancel_rollback();
|
|
|
|
|
|
if (ota_valid_err == ESP_OK) {
|
|
|
|
|
|
DEBUG_INFO("MAIN", "OTA 回滚保护: 当前固件已标记有效");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
DEBUG_WARN("MAIN", "OTA 回滚保护: 标记失败 (%s),可能非 OTA 启动",
|
|
|
|
|
|
esp_err_to_name(ota_valid_err));
|
|
|
|
|
|
}
|
2026-06-14 17:10:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-28 01:06:17 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "========================================");
|
2026-04-27 00:42:26 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "所有任务创建完成,OTA Relay 运行中");
|
2026-07-16 23:00:15 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "GD32 版本探测由 ota_relay 任务负责(hello+probe)");
|
2026-05-31 03:20:26 +08:00
|
|
|
|
DEBUG_INFO("MAIN", "调试日志输出: UDP(%s:%d) + UART0(GPIO21/TX, 115200)",
|
2026-04-28 01:06:17 +08:00
|
|
|
|
DEBUG_LOG_IP, DEBUG_LOG_PORT);
|
|
|
|
|
|
DEBUG_INFO("MAIN", "========================================");
|
2026-05-31 19:09:11 +08:00
|
|
|
|
}
|