2026-05-10 17:28:14 +08:00
|
|
|
|
#ifndef SYS_INITIAL_H
|
|
|
|
|
|
#define SYS_INITIAL_H
|
|
|
|
|
|
|
2026-07-17 02:03:00 +08:00
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
2026-05-10 17:28:14 +08:00
|
|
|
|
/**
|
2026-07-17 02:03:00 +08:00
|
|
|
|
* @brief 应用初始化器:按固定顺序启动模块,成功位置 1,末尾汇总。
|
2026-09-02 02:38:35 +08:00
|
|
|
|
* @note 汇总结果(模块位图 / critical 失败位图 / 复位源 / init 状态)经静态 getter 导出,
|
|
|
|
|
|
* 供 SPI 0xA3 INIT_STATUS 命令与身份块 [15] 上报 ESP32。
|
2026-05-10 17:28:14 +08:00
|
|
|
|
*/
|
|
|
|
|
|
class AppInitializer {
|
|
|
|
|
|
public:
|
2026-09-02 02:38:35 +08:00
|
|
|
|
/** 启动模块位(成功置 1);与 SPI 0xA3 上报位图共用,改动须同步 ESP32 侧注释 */
|
2026-07-17 02:03:00 +08:00
|
|
|
|
enum ModuleBit : uint32_t {
|
|
|
|
|
|
kNvic = 1u << 0,
|
|
|
|
|
|
kSysTick = 1u << 1,
|
|
|
|
|
|
kEsp32Hold = 1u << 2,
|
|
|
|
|
|
kUsart0 = 1u << 3,
|
|
|
|
|
|
kAdc = 1u << 4,
|
|
|
|
|
|
kCanFd = 1u << 5,
|
|
|
|
|
|
kOtaBootReq = 1u << 6,
|
|
|
|
|
|
kAppSpi = 1u << 7,
|
|
|
|
|
|
kTaskManager = 1u << 8,
|
|
|
|
|
|
kScheduler = 1u << 9,
|
|
|
|
|
|
kEthercat = 1u << 10,
|
|
|
|
|
|
kEthercatSync = 1u << 11,
|
|
|
|
|
|
kWatchdog = 1u << 12,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-09-02 02:38:35 +08:00
|
|
|
|
/** init 总体状态(身份块 [15] 与 0xA3 payload[9] 共用编码) */
|
|
|
|
|
|
enum InitState : uint8_t {
|
|
|
|
|
|
kInitOk = 0U, /**< 全部模块成功 */
|
|
|
|
|
|
kInitDegraded = 1U, /**< critical 全成功,非 critical 有失败/跳过 */
|
|
|
|
|
|
kInitCriticalFail = 2U, /**< 有 critical 模块失败 */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** 复位源位图(0xA3 payload[8] 编码),多位置位属正常(如 POR 常伴随其它标志) */
|
|
|
|
|
|
enum ResetCauseBit : uint8_t {
|
|
|
|
|
|
kRstPor = 1u << 0, /**< 上电/掉电复位 */
|
|
|
|
|
|
kRstEpr = 1u << 1, /**< 外部引脚复位(NRST) */
|
|
|
|
|
|
kRstFwdgt = 1u << 2, /**< 独立看门狗复位 */
|
|
|
|
|
|
kRstWwdgt = 1u << 3, /**< 窗口看门狗复位 */
|
|
|
|
|
|
kRstSw = 1u << 4, /**< 软件复位(含 OTA 跳转) */
|
|
|
|
|
|
kRstLp = 1u << 5, /**< 低功耗复位 */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** 模块数量(fault code 数组长度,与 ModuleBit 位序一致:bit N → 索引 N) */
|
|
|
|
|
|
static constexpr uint8_t kModuleCount = 13U;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 模块故障码(0xA3 payload[12..24],每模块 1B,0=成功)。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 各模块码值定义位置:
|
|
|
|
|
|
* - nvic : kFaultNvic*(本类下)
|
|
|
|
|
|
* - systick : kFaultSystick*(本类下;实际失败时 FATAL 停机不上报,仅备查)
|
|
|
|
|
|
* - esp32_hold : kFaultEsp32Hold*(本类下)
|
|
|
|
|
|
* - usart0 : Usart0::InitFault(device/usart0.h)
|
|
|
|
|
|
* - adc : Adc::InitFault(device/adc.h)
|
|
|
|
|
|
* - canfd : CanFd::SelfTestFault(device/canfd.h),
|
|
|
|
|
|
* **编码 = 原因码 | (首个失败通道号 << 4)**,通道 0/1/2
|
|
|
|
|
|
* - ota_boot_req: 纯软件,恒 0
|
|
|
|
|
|
* - app_spi : 无自证手段,恒 0
|
|
|
|
|
|
* - task_manager: 纯软件,恒 0
|
|
|
|
|
|
* - scheduler : SchedulerTimer::InitFault(device/timer.h)
|
|
|
|
|
|
* - ethercat : kFaultEthercat*(本类下)
|
|
|
|
|
|
* - ethercat_sync: 跟随 ethercat,恒 0
|
|
|
|
|
|
* - watchdog : Watchdog::InitFault(device/watchdog.h)
|
|
|
|
|
|
*/
|
|
|
|
|
|
enum NvicFault : uint8_t {
|
|
|
|
|
|
kFaultNvicOk = 0U,
|
|
|
|
|
|
kFaultNvicPrigroupMismatch = 1U, /**< AIRCR.PRIGROUP 回读与配置不一致 */
|
|
|
|
|
|
};
|
|
|
|
|
|
enum SystickFault : uint8_t {
|
|
|
|
|
|
kFaultSystickOk = 0U,
|
|
|
|
|
|
kFaultSystickConfig = 1U, /**< SysTick_Config 失败(备查,实际 FATAL 停机) */
|
|
|
|
|
|
kFaultSystickNoTick = 2U, /**< 节拍未前进(备查,实际 FATAL 停机) */
|
|
|
|
|
|
};
|
|
|
|
|
|
enum Esp32HoldFault : uint8_t {
|
|
|
|
|
|
kFaultEsp32HoldOk = 0U,
|
|
|
|
|
|
kFaultEsp32HoldClamped = 1U, /**< PC9 输出高后回读仍为 0(被外部钳低) */
|
|
|
|
|
|
};
|
|
|
|
|
|
enum EthercatFault : uint8_t {
|
|
|
|
|
|
kFaultEthercatOk = 0U,
|
|
|
|
|
|
kFaultEthercatBusNotReady = 1U, /**< EXMC/HBI 总线探活失败(BYTE_TEST 未通过) */
|
|
|
|
|
|
kFaultEthercatSscFail = 2U, /**< SSC MainInit 返回非 0 */
|
|
|
|
|
|
kFaultEthercatCoreNotReady = 3U, /**< EEPROM 未加载完成,EtherCAT 核心未使能(1.5.39) */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-10 21:27:51 +08:00
|
|
|
|
/**
|
2026-07-17 02:03:00 +08:00
|
|
|
|
* @brief 按固定顺序完成模块初始化(过程只置位,结束统一报告成败/失败模块)。
|
2026-05-10 21:27:51 +08:00
|
|
|
|
*/
|
2026-05-10 17:28:14 +08:00
|
|
|
|
static void init();
|
2026-07-17 02:03:00 +08:00
|
|
|
|
|
2026-09-02 02:38:35 +08:00
|
|
|
|
/** @brief 已成功初始化的模块位图。 */
|
|
|
|
|
|
static uint32_t moduleMask() { return s_mask; }
|
|
|
|
|
|
/** @brief 初始化失败的 critical 模块位图(0=无 critical 失败)。 */
|
|
|
|
|
|
static uint32_t criticalFailMask();
|
|
|
|
|
|
/** @brief init 总体状态(InitState 编码)。 */
|
|
|
|
|
|
static uint8_t initState() { return s_initState; }
|
|
|
|
|
|
/** @brief 本次上电复位源位图(ResetCauseBit 编码,init 开头采集并已清硬件标志)。 */
|
|
|
|
|
|
static uint8_t resetCause() { return s_resetCause; }
|
|
|
|
|
|
/** @brief 指定模块(ModuleBit 位序索引 0..12)的故障码,0=成功。 */
|
|
|
|
|
|
static uint8_t faultCode(uint8_t module_index);
|
|
|
|
|
|
/** @brief 将全部模块故障码拷贝到 out(至少 kModuleCount 字节),返回长度。 */
|
|
|
|
|
|
static uint8_t faultCodes(uint8_t *out);
|
|
|
|
|
|
|
2026-07-17 02:03:00 +08:00
|
|
|
|
private:
|
|
|
|
|
|
static uint32_t s_mask;
|
2026-09-02 02:38:35 +08:00
|
|
|
|
static uint8_t s_initState;
|
|
|
|
|
|
static uint8_t s_resetCause;
|
|
|
|
|
|
static uint8_t s_faultCodes[kModuleCount];
|
2026-07-17 02:03:00 +08:00
|
|
|
|
|
|
|
|
|
|
static void mark(ModuleBit b);
|
2026-09-02 02:38:35 +08:00
|
|
|
|
static void setFault(ModuleBit b, uint8_t code);
|
|
|
|
|
|
static void captureResetCause();
|
2026-07-17 02:03:00 +08:00
|
|
|
|
static void report();
|
2026-05-10 17:28:14 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-17 02:03:00 +08:00
|
|
|
|
#endif /* SYS_INITIAL_H */
|