feat(ethercat): 添加EtherCAT从站功能支持并优化同步机制

- 添加CAN反馈和ID快照SPI命令文件
- 移除EXMC组件依赖,精简项目配置
- 添加RAM函数段链接脚本,优化Flash等待周期抖动
- 实现EscExmcBus类,提供16位并行总线访问LAN9252
- 实现EscLan9252驱动,支持寄存器和PDI内存访问
- 实现EthercatSlave类,采用三缓冲机制进行PDO数据交换
- 实现EthercatSync同步管理,支持SYNC0/SYNC1中断和定时器模式
- 添加ISR执行时间统计和诊断功能
- 分离周期路径和事件路径通知机制,避免RMW竞态
This commit is contained in:
cbb
2026-06-29 01:51:02 +08:00
parent 1612e326ee
commit b171767023
31 changed files with 2177 additions and 290 deletions
+29 -8
View File
@@ -1,4 +1,4 @@
/**
/**
* @file task_runner.cpp
* @brief 任务执行器实现。
*/
@@ -13,9 +13,7 @@
#include "sys/ota_boot_request.h"
#include "sys/task_manager.h"
#include "sys/task_runner.h"
#if CONFIG_ETHERCAT_ENABLE
#include "comm/ethercat_slave.h"
#endif
namespace {
constexpr uint32_t kAdcFilterWindow = CONFIG_ADC_FILTER_SIZE + 1U;
@@ -214,7 +212,7 @@ void TaskRunner::taskStatusLed() { /* 预留 */ }
* @retval 无返回值。
* @note 当前仅保留任务入口。
*/
void TaskRunner::taskHeartbeat() { OtaBootRequest::process(); }
void TaskRunner::taskHeartbeat() { OtaBootRequest::process(); CanFd::refreshFeedbackSnapshot(); }
/**
* @brief 输出当前温度、电压与 CAN 诊断信息。
@@ -266,6 +264,23 @@ void TaskRunner::taskDiagnosticPrint()
static_cast<unsigned long>(diag->tx_abort_count),
static_cast<unsigned long>(diag->error_count));
#endif
{
if (EthercatSlave::isEscReady()) {
uint32_t maxCyc = 0U, avgCyc = 0U, cnt = 0U;
EthercatSlave::getIsrStats(&maxCyc, &avgCyc, &cnt);
/* 180MHz: cycles / 180 = µs;用 *1000/180 获得毫微秒精度避免浮点 */
const uint32_t maxUs_x1000 = maxCyc * 1000U / 180U;
const uint32_t avgUs_x1000 = avgCyc * 1000U / 180U;
printf("[ECAT] periodicIsr cnt=%lu max=%lu.%03luus avg=%lu.%03luus\r\n",
(unsigned long)cnt,
(unsigned long)(maxUs_x1000 / 1000U), (unsigned long)(maxUs_x1000 % 1000U),
(unsigned long)(avgUs_x1000 / 1000U), (unsigned long)(avgUs_x1000 % 1000U));
} else {
printf("[ECAT] ESC not detected (chip id=0x%08lX), EtherCAT disabled\r\n",
(unsigned long)EthercatSlave::getChipId());
}
}
}
/**
@@ -289,11 +304,7 @@ void TaskRunner::taskSpiCmdProcess()
*/
void TaskRunner::taskEthercatProcess()
{
#if CONFIG_ETHERCAT_ENABLE
EthercatSlave::process();
#else
/* 未使能 EtherCAT 时此分支不应被置位;保留空操作以避免链接错误。 */
#endif
}
/**
@@ -328,6 +339,16 @@ void TaskRunner::runPending()
{
Watchdog::feed();
/* 周期路径( SYNC0 ISR preempt=0 )用 s_periodicSeq 序列号通知主循环,
* 不再走 task_flags,避免 BASEPRI 临界区与 preempt=0 的 RMW 竞态。
* 优先于 takePending() 处理,确保周期数据及时消费。
* ESC 未焊接时 selfTest 失败,isEscReady()=false,中断未使能,
* s_periodicSeq 不会递增,此分支自然不触发——双重守卫仅为防御性编程。 */
if (EthercatSlave::isEscReady() && EthercatSlave::hasPendingPeriodic()) {
EthercatSlave::markPeriodicProcessed();
taskEthercatProcess();
}
const uint32_t pending = TaskManager::takePending();
if(pending == 0U) return;