- 在DCU_APP项目中添加cpu_load.h和cpu_load.cpp模块用于CPU负载率监测 - 修改csolution配置将构建目标从Debug切换为Release - 在EtherCAT PDO协议栈中新增段5诊断区(632-639字节),包含负载率和序列号 - 在所有关键中断服务程序中添加CpuLoad::isrEnter()/isrExit()钩子用于准确统计中断占用 - 增强EtherCAT同步中断处理,改进AL事件掩码守护机制,修复OP状态下PDI中断门控问题 - 解决SSC源码中指针地址对齐警告和打包成员访问警告问题 - 在主循环中集成CPU负载率采样tick()调用,实现1秒滚动窗口统计 BREAKING CHANGE: 构建配置从Debug改为Release,EtherCAT协议栈增加新的诊断数据区
103 lines
3.5 KiB
C++
103 lines
3.5 KiB
C++
/**
|
||
* @file systick.cpp
|
||
* @brief SysTick 时基模块实现。
|
||
*/
|
||
|
||
#include "main.h"
|
||
#include "sys/systick.h"
|
||
#include "sys/cpu_load.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)
|
||
{
|
||
CpuLoad::isrEnter();
|
||
SysTickTimer::onInterrupt();
|
||
CpuLoad::isrExit();
|
||
}
|