Files
DCU_APP/GD32E508_DCU_APP/sys/initial.h
T

121 lines
5.2 KiB
C++
Raw Normal View History

#ifndef SYS_INITIAL_H
#define SYS_INITIAL_H
#include <stdint.h>
#include <stdbool.h>
/**
* @brief 应用初始化器:按固定顺序启动模块,成功位置 1,末尾汇总。
* @note 汇总结果(模块位图 / critical 失败位图 / 复位源 / init 状态)经静态 getter 导出,
* 供 SPI 0xA3 INIT_STATUS 命令与身份块 [15] 上报 ESP32。
*/
class AppInitializer {
public:
/** 启动模块位(成功置 1);与 SPI 0xA3 上报位图共用,改动须同步 ESP32 侧注释 */
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,
};
/** 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) */
};
/**
* @brief 按固定顺序完成模块初始化(过程只置位,结束统一报告成败/失败模块)。
*/
static void init();
/** @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);
private:
static uint32_t s_mask;
static uint8_t s_initState;
static uint8_t s_resetCause;
static uint8_t s_faultCodes[kModuleCount];
static void mark(ModuleBit b);
static void setFault(ModuleBit b, uint8_t code);
static void captureResetCause();
static void report();
};
#endif /* SYS_INITIAL_H */