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:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user