/** * @file systick.cpp * @brief SysTick 时基模块实现。 */ #include "main.h" #include "sys/systick.h" volatile uint32_t SysTickTimer::s_ms = 0U; /** * @brief SysTick 中断处理入口。 * @param[in] 无。 * @param[out] 无。 * @retval 无返回值。 * @note 每次 SysTick 中断到来时,将毫秒计数器自增 1。 */ void SysTickTimer::onInterrupt() { s_ms++; } /** * @brief 执行毫秒级阻塞延时。 * @param[in] ms 需要延时的毫秒数。 * @param[out] 无。 * @retval 无返回值。 * @note 基于 SysTick 维护的毫秒计数器忙等,适用于短时初始化等待。 */ void SysTickTimer::delayMs(uint32_t ms) { uint32_t start = s_ms; while((s_ms - start) < ms) { } } /** * @brief SysTick 失效时的致命停机:裸寄存器 USART0(PA9) 输出 FATAL 后挂死。 * @param[in] 无。 * @param[out] 无。 * @retval 无返回值(不返回)。 * @note 此时 USART0 驱动尚未初始化,只能裸写寄存器; * 时钟树已是 180MHz(SystemInit 完成),BAUD=60 对应 3M(与工程 printf 一致)。 * 注意 system_gd32e50x.c 的 HXTAL FAIL 段有寄存器 bug(CTL0 写到 STAT0 偏移、 * 漏开 USART0EN),本段使用修正后的地址:APB2EN bit14=USART0EN、CTL0 @ +0x0C。 */ static void fatalSystickHalt() { *((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0); /* USART0EN|PAEN|AFEN */ { volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U); /* PA9 → AF_PP */ _ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4); *((volatile uint32_t *)0x40010804U) = _ctl; } *((volatile uint32_t *)0x40013808U) = 60U; /* BAUD: 180MHz/3M */ *((volatile uint32_t *)0x4001380CU) = (1U << 3) | (1U << 13); /* CTL0: TEN | UEN */ { const char *_msg = "[APP] init: FATAL systick\r\n"; for(int i=0; _msg[i]; i++){ *((volatile uint32_t *)0x40013804U) = _msg[i]; /* DATA */ while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } } /* STAT0.TBE */ while(1){ } } /** * @brief 初始化 1ms SysTick 时基并验证中断真实触发。 * @param[in] 无。 * @param[out] 无。 * @retval bool true=节拍已前进;false=配置失败(不返回,直接 FATAL 停机)。 * @note 先更新 `SystemCoreClock`,再按 1kHz 频率配置 SysTick。 * 节拍验证失败时系统失去一切超时/延时基础,继续运行等于盲跑, * 按致命错误处理(裸串口报告 + 挂死,与 HXTAL FAIL 同级)。 */ bool SysTickTimer::initMs() { SystemCoreClockUpdate(); if (SysTick_Config(SystemCoreClock / 1000U) != 0U) { fatalSystickHalt(); } /* 有界等待节拍前进:guard 预算约 50ms+,覆盖 1ms 节拍; * 若无界等待,中断未触发时此处即死循环且无任何诊断。 */ const uint32_t start = s_ms; volatile uint32_t guard = 2000000U; while (s_ms == start) { if (--guard == 0U) { fatalSystickHalt(); } } return true; } /* ----- 中断入口 C 包装 ---------------------------------------------- */ /** * @brief SysTick 中断向量入口。 * @param[in] 无。 * @param[out] 无。 * @retval 无返回值。 * @note C 向量包装函数,内部转调 `SysTickTimer::onInterrupt()`。 */ extern "C" void SysTick_Handler(void) { SysTickTimer::onInterrupt(); }