Files
DCU_APP/GD32E508_DCU_APP/comm/ethercat_slave.cpp
T

71 lines
2.2 KiB
C++
Raw Normal View History

/**
* @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 */