Files
DCU_APP/GD32E508_DCU_APP/sys/systick.cpp
T

97 lines
3.4 KiB
C++
Raw Normal View History

/**
* @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(); }