- 将设备相关文件重新组织为device/spi和comm分组 - 添加EtherCAT从站通信模块(esc_exmc_bus、esc_lan9252、ethercat_slave等) - 添加EXMC外设组件支持 - 统一文件命名规范为小写 refactor(canfd): 优化CANFD模块中断安全性和配置方式 - 替换自定义临界区函数为RT_CRITICAL_SAVE/RESTORE宏 - 使用配置常量CONFIG_IRQ_PREEMPT_CAN替代硬编码值 - 简化邮箱满时的处理逻辑,移除不必要的SysTick等待 - 移除废弃的中断保存头文件引用 refactor(timer): 更新定时器配置以使用配置常量 - 修复头文件包含路径大小写问题 - 使用CONFIG_NVIC_PRIORITY_GROUP配置项替代硬编码值
71 lines
2.2 KiB
C++
71 lines
2.2 KiB
C++
/**
|
|
* @file ethercat_slave.cpp
|
|
* @brief EtherCAT 从站周期处理实现。
|
|
*/
|
|
#include "comm/ethercat_slave.h"
|
|
#include "comm/esc_lan9252.h"
|
|
#include "sys/config.h"
|
|
#include "sys/task_manager.h"
|
|
#include "main.h"
|
|
|
|
#if CONFIG_ETHERCAT_ENABLE
|
|
|
|
PdoBuffer EthercatSlave::s_inputs[2] = {};
|
|
PdoBuffer EthercatSlave::s_outputs[2] = {};
|
|
volatile uint8_t EthercatSlave::s_inputReadIndex = 0U;
|
|
volatile uint8_t EthercatSlave::s_outputWriteIndex = 0U;
|
|
|
|
void EthercatSlave::init()
|
|
{
|
|
EscLan9252::init();
|
|
if (EscLan9252::selfTest()) {
|
|
/* ESC 自检通过:TODO 启用周期同步 */
|
|
}
|
|
s_inputReadIndex = 0U;
|
|
s_outputWriteIndex = 0U;
|
|
}
|
|
|
|
__attribute__((section(".ramfunc")))
|
|
void EthercatSlave::periodicIsr()
|
|
{
|
|
/* 1. 读取输入 PDO 到另一块缓冲(当前可读缓冲的配对) */
|
|
const uint8_t write_idx = s_inputReadIndex ^ 1U;
|
|
EscLan9252::readPdi(0x0000U, s_inputs[write_idx].data, CONFIG_ETHERCAT_PDO_SIZE);
|
|
s_inputs[write_idx].len = CONFIG_ETHERCAT_PDO_SIZE;
|
|
|
|
/* 2. 写入输出 PDO(从应用层未写入的那个缓冲读取) */
|
|
const uint8_t out_read_idx = s_outputWriteIndex ^ 1U;
|
|
EscLan9252::writePdi(0x0000U, s_outputs[out_read_idx].data, s_outputs[out_read_idx].len);
|
|
|
|
/* 3. 翻转输入缓冲指针,使新完成的缓冲成为可读缓冲 */
|
|
s_inputReadIndex = write_idx;
|
|
|
|
/* 4. 置位非实时任务,通知主循环处理应用层 PDO 映射 */
|
|
TaskManager::set(1UL << TASK_ETHERCAT_PROCESS);
|
|
}
|
|
|
|
const PdoBuffer* EthercatSlave::getLatestInputs()
|
|
{
|
|
/* s_inputReadIndex 始终指向最新完成的输入缓冲 */
|
|
return &s_inputs[s_inputReadIndex];
|
|
}
|
|
|
|
void EthercatSlave::setOutputs(const PdoBuffer *outputs)
|
|
{
|
|
if (outputs == nullptr) {
|
|
return;
|
|
}
|
|
/* 写入应用层缓冲(ISR 当前不读取的那个) */
|
|
const uint8_t write_idx = s_outputWriteIndex ^ 1U;
|
|
s_outputs[write_idx] = *outputs;
|
|
s_outputWriteIndex = write_idx;
|
|
}
|
|
|
|
void EthercatSlave::process()
|
|
{
|
|
/* 应用层 PDO 映射入口(非实时,由主循环 TASK_ETHERCAT_PROCESS 调用)。
|
|
* TODO: 将 getLatestInputs() 数据映射到应用对象字典;将应用输出填入 setOutputs()。 */
|
|
}
|
|
|
|
#endif /* CONFIG_ETHERCAT_ENABLE */
|