/** * @file initial.cpp * @brief 应用启动初始化:模块成功置位,结束统一报告结果。 * * 顺序: * NVIC → SysTick → ESP32_EN 保持 → USART0 → AppSpi(尽早 HELLO 探活)→ * ADC → CANFD → OtaBootRequest → TaskManager → Scheduler → * EtherCAT(+Sync 可选) → Watchdog → report */ #include "sys/initial.h" #include "device/canfd.h" #include "device/usart0.h" #include "device/timer.h" #include "device/adc.h" #include "device/watchdog.h" #include "device/spi/app_spi_command.h" #include "sys/systick.h" #include "sys/ota_boot_request.h" #include "sys/task_manager.h" #include "sys/config.h" #include "comm/esc_lan9252.h" #include "comm/ethercat_slave.h" #include "comm/ethercat_sync.h" extern "C" { uint16_t MainInit(void); void MainLoop(void); } uint32_t AppInitializer::s_mask = 0U; namespace { struct InitEntry { uint32_t bit; const char *name; bool critical; }; static const InitEntry kEntries[] = { { AppInitializer::kNvic, "nvic", true }, { AppInitializer::kSysTick, "systick", true }, { AppInitializer::kEsp32Hold, "esp32_hold", true }, { AppInitializer::kUsart0, "usart0", true }, { AppInitializer::kAppSpi, "app_spi", true }, { AppInitializer::kAdc, "adc", true }, { AppInitializer::kCanFd, "canfd", true }, { AppInitializer::kOtaBootReq, "ota_boot_req", true }, { AppInitializer::kTaskManager, "task_manager", true }, { AppInitializer::kScheduler, "scheduler", true }, { AppInitializer::kEthercat, "ethercat", false }, { AppInitializer::kEthercatSync, "ethercat_sync", false }, { AppInitializer::kWatchdog, "watchdog", true }, }; } // namespace void AppInitializer::mark(ModuleBit b) { s_mask |= static_cast(b); } void AppInitializer::report() { bool critical_ok = true; bool all_ok = true; char fail_list[160] = {0}; size_t fail_len = 0U; for (size_t i = 0; i < sizeof(kEntries) / sizeof(kEntries[0]); ++i) { const InitEntry &e = kEntries[i]; const bool ok = (s_mask & e.bit) != 0U; if (ok) { continue; } all_ok = false; if (e.critical) { critical_ok = false; } if (fail_len + 2U < sizeof(fail_list)) { if (fail_len > 0U) { fail_list[fail_len++] = ','; } const char *p = e.name; while (*p != '\0' && fail_len + 1U < sizeof(fail_list)) { fail_list[fail_len++] = *p++; } fail_list[fail_len] = '\0'; } } if (critical_ok && all_ok) { printf("[APP] init: OK (all modules)\r\n"); } else if (critical_ok) { printf("[APP] init: OK (critical), skipped/failed: %s\r\n", fail_list[0] != '\0' ? fail_list : "?"); } else { printf("[APP] init: FAIL, modules: %s\r\n", fail_list[0] != '\0' ? fail_list : "?"); } } void AppInitializer::init() { s_mask = 0U; nvic_priority_group_set(CONFIG_NVIC_PRIORITY_GROUP); mark(kNvic); SysTickTimer::initMs(); mark(kSysTick); rcu_periph_clock_enable(RCU_GPIOC); gpio_bit_set(CONFIG_ESP32_RESET_PORT, CONFIG_ESP32_RESET_PIN); gpio_init(CONFIG_ESP32_RESET_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, CONFIG_ESP32_RESET_PIN); mark(kEsp32Hold); Usart0::configurePins(); Usart0::init(); mark(kUsart0); /* SPI 尽早就绪:OTA FINISH 跳转后 ESP32 用 HELLO 探活,不能等 CAN 上电延时 */ AppSpiCommandBus.init(); mark(kAppSpi); Adc::init(); mark(kAdc); CanFd::init(); /* L0 通过才置 canfd 位 */ if (CanFd::selfTestL0()) { mark(kCanFd); } OtaBootRequest::init(); mark(kOtaBootReq); TaskManager::init(); mark(kTaskManager); SchedulerTimer::init(); mark(kScheduler); /* ---- EtherCAT: EXMC 总线探活 → SSC 协议栈初始化 → SYNC0/IRQ 中断使能 ---- * EEPROM 校验/烧录延迟到主循环执行,避免阻塞 init(烧录需 ~20s)。 */ if (EscLan9252::init()) { const uint16_t sscResult = MainInit(); if (sscResult == 0U) { mark(kEthercat); EthercatSync::init(); mark(kEthercatSync); printf("[ECAT] SSC MainInit OK, sync ISR enabled\r\n"); } else { printf("[ECAT] SSC MainInit FAIL (code=0x%04X)\r\n", (unsigned)sscResult); } } else { printf("[ECAT] EXMC bus not ready, SSC skipped\r\n"); } Watchdog::init(); mark(kWatchdog); report(); }