355 lines
12 KiB
C++
355 lines
12 KiB
C++
|
/*
|
||
|
* eth_ecat_buffer.hpp
|
||
|
*
|
||
|
* Created on: May 3, 2023
|
||
|
* Author: algin
|
||
|
*/
|
||
|
|
||
|
#ifndef FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_BUFFER_HPP_
|
||
|
#define FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_BUFFER_HPP_
|
||
|
|
||
|
#include <vector>
|
||
|
#include <kernel/dpl/ClockP.h>
|
||
|
|
||
|
#include "ethernet_industry/eth_ecat.hpp"
|
||
|
|
||
|
namespace free_rtos {
|
||
|
|
||
|
namespace ecat_buffer {
|
||
|
|
||
|
struct FMMUSettings {
|
||
|
uint32_t log_start_address;
|
||
|
uint16_t log_data_len;
|
||
|
uint8_t log_start_bit;
|
||
|
uint8_t log_end_bit;
|
||
|
uint16_t phys_start_address;
|
||
|
uint8_t phys_start_bit;
|
||
|
uint8_t direction;
|
||
|
uint8_t activate;
|
||
|
//uint8_t param1;
|
||
|
//uint16_t param2;
|
||
|
} __attribute__ ((packed));
|
||
|
|
||
|
struct FMMUProperties {
|
||
|
address::Logical address;
|
||
|
uint16_t length;
|
||
|
};
|
||
|
|
||
|
struct BufferSettings {
|
||
|
uint8_t control;
|
||
|
uint8_t status;
|
||
|
uint8_t activate;
|
||
|
uint8_t pdi_control;
|
||
|
};
|
||
|
|
||
|
struct BufferProperties {
|
||
|
address::Offset offset;
|
||
|
uint16_t length;
|
||
|
} __attribute__ ((packed));
|
||
|
|
||
|
struct SyncManager {
|
||
|
address::Offset offset;
|
||
|
uint32_t default_setting;
|
||
|
};
|
||
|
|
||
|
class EcatBufferSlave {
|
||
|
public:
|
||
|
EcatBufferSlave(EcatSlave& slave)
|
||
|
: slave_(slave) { }
|
||
|
|
||
|
EcatSlave& get_slave()
|
||
|
{
|
||
|
return slave_;
|
||
|
}
|
||
|
|
||
|
std::array<address::Offset, 4>& get_buffer_regs() {
|
||
|
return buffer_regs_;
|
||
|
}
|
||
|
|
||
|
void set_buffer_offset(uint16_t rx_offset, uint16_t tx_offset) {
|
||
|
buffer_properties_write_.offset = static_cast<address::Offset>(rx_offset);
|
||
|
buffer_properties_read_.offset = static_cast<address::Offset>(tx_offset);
|
||
|
|
||
|
buffer_regs_[MailboxesRegs::WRITE] = buffer_properties_write_.offset;
|
||
|
buffer_regs_[MailboxesRegs::READ] = buffer_properties_read_.offset;
|
||
|
}
|
||
|
|
||
|
// Размер в байтах !
|
||
|
void set_buffer_length(uint16_t rx_length, uint16_t tx_length) {
|
||
|
buffer_properties_write_.length = rx_length;
|
||
|
buffer_properties_read_.length = tx_length;
|
||
|
}
|
||
|
|
||
|
BufferProperties& get_buffer_properties_write() {
|
||
|
return buffer_properties_write_;
|
||
|
}
|
||
|
|
||
|
BufferProperties& get_buffer_properties_read() {
|
||
|
return buffer_properties_read_;
|
||
|
}
|
||
|
|
||
|
FMMUProperties& get_fmmu_properties_write() {
|
||
|
return fmmu_properties_write_;
|
||
|
}
|
||
|
|
||
|
FMMUProperties& get_fmmu_properties_read() {
|
||
|
return fmmu_properties_read_;
|
||
|
}
|
||
|
|
||
|
uint32_t get_logical_full_length_write() {
|
||
|
return logical_full_length_write_;
|
||
|
}
|
||
|
|
||
|
uint32_t get_logical_full_length_read() {
|
||
|
return logical_full_length_read_;
|
||
|
}
|
||
|
|
||
|
template<typename TypeT>
|
||
|
void read_buffer_info_from_eeprom(eeprom::EEPROM& eeprom, uint16_t rx_eeprom_addr, uint16_t tx_eeprom_addr) {
|
||
|
auto slave_address = slave_.get_slave_address<TypeT>();
|
||
|
|
||
|
eeprom.read<TypeT>(slave_address, rx_eeprom_addr, buffer_properties_write_);
|
||
|
eeprom.read<TypeT>(slave_address, tx_eeprom_addr, buffer_properties_read_);
|
||
|
|
||
|
buffer_regs_[MailboxesRegs::WRITE] = buffer_properties_write_.offset;
|
||
|
buffer_regs_[MailboxesRegs::READ] = buffer_properties_read_.offset;
|
||
|
|
||
|
DebugP_log("buffer_properties_write_ = 0x%04x\r\n", buffer_properties_write_);
|
||
|
DebugP_log("buffer_properties_read_ = 0x%04x\r\n", buffer_properties_read_);
|
||
|
}
|
||
|
|
||
|
template<typename TypeT>
|
||
|
void init_sync_manager(datagram::EcatTelegram& telegram, sync_manager sm, BufferProperties& buffer, address::Offset& reg) {
|
||
|
using TCommand = command::EcatCommand<TypeT, command::WR>;
|
||
|
|
||
|
auto slave_address = slave_.get_slave_address<TypeT>();
|
||
|
|
||
|
SyncManager sync_manager = sync_managers_[static_cast<size_t>(sm)];
|
||
|
datagram::EcatDatagram<TCommand, BufferProperties, uint32_t> datagram{ {{slave_address, sync_manager.offset}},
|
||
|
buffer,
|
||
|
sync_manager.default_setting };
|
||
|
|
||
|
telegram.transfer(datagram);
|
||
|
|
||
|
reg = sync_manager.offset + 0x05;
|
||
|
|
||
|
DebugP_log("datagram.get_wkc() = %d\r\n", datagram.get_wkc());
|
||
|
}
|
||
|
|
||
|
template<typename TypeT>
|
||
|
void init_sync_manager(datagram::EcatTelegram& telegram, sync_manager sm_write, sync_manager sm_read) {
|
||
|
using TCommand = command::EcatCommand<TypeT, command::WR>;
|
||
|
|
||
|
auto slave_address = slave_.get_slave_address<TypeT>();
|
||
|
|
||
|
SyncManager sync_manager_write = sync_managers_[static_cast<size_t>(sm_write)];
|
||
|
/*
|
||
|
BufferSettings buffer_settings_write{ .control = 0x26,
|
||
|
.status = 0x00,
|
||
|
.activate = 0x01,
|
||
|
.pdi_control = 0x00 };
|
||
|
*/
|
||
|
datagram::EcatDatagram<TCommand, BufferProperties, uint32_t> datagram_write{ {{slave_address, sync_manager_write.offset}},
|
||
|
buffer_properties_write_,
|
||
|
sync_manager_write.default_setting };
|
||
|
//register_sync_manager<TypeT>(telegram, sm_write, buffer_properties_write_, buffer_regs_[MailboxesRegs::EMPTY]);
|
||
|
|
||
|
SyncManager sync_manager_read = sync_managers_[static_cast<size_t>(sm_read)];
|
||
|
/*
|
||
|
BufferSettings buffer_settings_read{ .control = 0x22,
|
||
|
.status = 0x00,
|
||
|
.activate = 0x01,
|
||
|
.pdi_control = 0x00 };
|
||
|
*/
|
||
|
datagram::EcatDatagram<TCommand, BufferProperties, uint32_t> datagram_read{ {{slave_address, sync_manager_read.offset}},
|
||
|
buffer_properties_read_,
|
||
|
sync_manager_read.default_setting };
|
||
|
//register_sync_manager<TypeT>(telegram, sm_read, buffer_properties_read_, buffer_regs_[MailboxesRegs::AVAILABLE]);
|
||
|
/*
|
||
|
datagram_write + datagram_read;
|
||
|
|
||
|
do {
|
||
|
telegram.transfer(datagram_write);
|
||
|
} while((datagram_write.get_wkc() < 0x0001) || (datagram_read.get_wkc() < 0x0001));
|
||
|
*/
|
||
|
|
||
|
do {
|
||
|
telegram.transfer(datagram_write);
|
||
|
} while(datagram_write.get_wkc() < 0x0001);
|
||
|
|
||
|
do {
|
||
|
telegram.transfer(datagram_read);
|
||
|
} while(datagram_read.get_wkc() < 0x0001);
|
||
|
|
||
|
buffer_regs_[MailboxesRegs::EMPTY] = sync_manager_write.offset + 0x05;
|
||
|
buffer_regs_[MailboxesRegs::AVAILABLE] = sync_manager_read.offset + 0x05;
|
||
|
|
||
|
DebugP_log("datagram_write.get_wkc() = %d\r\n", datagram_write.get_wkc());
|
||
|
DebugP_log("datagram_read.get_wkc() = %d\r\n", datagram_read.get_wkc());
|
||
|
}
|
||
|
|
||
|
template<typename TypeT>
|
||
|
void init_fmmu( datagram::EcatTelegram& telegram, fmmu fmmu_x, FMMUSettings& settings) {
|
||
|
using TCommand = command::EcatCommand<TypeT, command::WR>;
|
||
|
|
||
|
auto slave_address = slave_.get_slave_address<TypeT>();
|
||
|
datagram::EcatDatagram<TCommand, FMMUSettings> datagram{ {{slave_address, fmmu_regs_[static_cast<size_t>(fmmu_x)]}}, settings};
|
||
|
|
||
|
telegram.transfer(datagram);
|
||
|
}
|
||
|
|
||
|
template<typename TypeT>
|
||
|
void init_fmmu(datagram::EcatTelegram& telegram, fmmu fmmu_write, fmmu fmmu_read) {
|
||
|
using TCommand = command::EcatCommand<TypeT, command::WR>;
|
||
|
|
||
|
static address::Logical logical_end_address{logical_start_address_};
|
||
|
|
||
|
auto slave_address = slave_.get_slave_address<TypeT>();
|
||
|
|
||
|
fmmu_write_ = fmmu_write;
|
||
|
fmmu_read_ = fmmu_read;
|
||
|
|
||
|
FMMUSettings settings_write {
|
||
|
.log_start_address = logical_end_address,
|
||
|
.log_data_len = buffer_properties_write_.length,
|
||
|
.log_start_bit = 0,
|
||
|
.log_end_bit = 7,
|
||
|
.phys_start_address = buffer_properties_write_.offset,
|
||
|
.phys_start_bit = 0,
|
||
|
.direction = static_cast<uint8_t>(DataDirection::WRITE),
|
||
|
.activate = 0x01,
|
||
|
//.param1 = 0x00,
|
||
|
//.param2 = 0x00
|
||
|
};
|
||
|
|
||
|
datagram::EcatDatagram<TCommand, FMMUSettings> datagram_write{ {{slave_address, fmmu_regs_[static_cast<size_t>(fmmu_write)]}}, settings_write};
|
||
|
//init_fmmu<TypeT>(telegram, fmmu_write, settings_write);
|
||
|
|
||
|
fmmu_properties_write_.address = logical_end_address;
|
||
|
fmmu_properties_write_.length = buffer_properties_write_.length;
|
||
|
logical_full_length_write_ += buffer_properties_write_.length;
|
||
|
logical_end_address += buffer_properties_write_.length;
|
||
|
|
||
|
FMMUSettings settings_read {
|
||
|
.log_start_address = logical_end_address,
|
||
|
.log_data_len = buffer_properties_read_.length,
|
||
|
.log_start_bit = 0,
|
||
|
.log_end_bit = 7,
|
||
|
.phys_start_address = buffer_properties_read_.offset,
|
||
|
.phys_start_bit = 0,
|
||
|
.direction = static_cast<uint8_t>(DataDirection::READ),
|
||
|
.activate = 0x01,
|
||
|
//.param1 = 0x00,
|
||
|
//.param2 = 0x00
|
||
|
};
|
||
|
|
||
|
datagram::EcatDatagram<TCommand, FMMUSettings> datagram_read{ {{slave_address, fmmu_regs_[static_cast<size_t>(fmmu_read)]}}, settings_read};
|
||
|
//init_fmmu<TypeT>(telegram, fmmu_read, settings_read);
|
||
|
|
||
|
fmmu_properties_read_.address = logical_end_address;
|
||
|
fmmu_properties_read_.length = buffer_properties_read_.length;
|
||
|
logical_full_length_read_ += buffer_properties_read_.length;
|
||
|
logical_end_address += buffer_properties_read_.length;
|
||
|
|
||
|
datagram_write + datagram_read;
|
||
|
|
||
|
do {
|
||
|
telegram.transfer(datagram_write);
|
||
|
} while((datagram_write.get_wkc() < 0x0001) || (datagram_read.get_wkc() < 0x0001));
|
||
|
/*
|
||
|
do {
|
||
|
telegram.transfer(datagram_write);
|
||
|
} while(datagram_write.get_wkc() < 0x0001);
|
||
|
|
||
|
do {
|
||
|
telegram.transfer(datagram_read);
|
||
|
} while(datagram_read.get_wkc() < 0x0001);
|
||
|
*/
|
||
|
DebugP_log("datagram_read.get_wkc() = %d\r\n", datagram_read.get_wkc());
|
||
|
DebugP_log("datagram_write.get_wkc() = %d\r\n", datagram_write.get_wkc());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
static constexpr std::array<SyncManager, 4> sync_managers_ = {{
|
||
|
{ECT_REG_SM0, EC_DEFAULTMBXSM0},
|
||
|
{ECT_REG_SM1, EC_DEFAULTMBXSM1},
|
||
|
{ECT_REG_SM2, EC_DEFAULTMBXSM2},
|
||
|
{ECT_REG_SM3, EC_DEFAULTMBXSM3}
|
||
|
}};
|
||
|
|
||
|
static constexpr std::array<address::Offset, 4> fmmu_regs_ = {{
|
||
|
ECT_REG_FMMU0,
|
||
|
ECT_REG_FMMU1,
|
||
|
ECT_REG_FMMU2,
|
||
|
ECT_REG_FMMU3
|
||
|
}};
|
||
|
|
||
|
static constexpr uint32_t logical_start_address_{0x00000000};
|
||
|
|
||
|
static uint32_t logical_full_length_write_;
|
||
|
static uint32_t logical_full_length_read_;
|
||
|
|
||
|
std::array<address::Offset, 4> buffer_regs_ = {
|
||
|
static_cast<address::Offset>(0x0000),
|
||
|
static_cast<address::Offset>(0x0000),
|
||
|
static_cast<address::Offset>(0x0000),
|
||
|
static_cast<address::Offset>(0x0000),
|
||
|
};
|
||
|
|
||
|
BufferProperties buffer_properties_write_;
|
||
|
BufferProperties buffer_properties_read_;
|
||
|
|
||
|
fmmu fmmu_write_;
|
||
|
fmmu fmmu_read_;
|
||
|
|
||
|
FMMUProperties fmmu_properties_write_;
|
||
|
FMMUProperties fmmu_properties_read_;
|
||
|
|
||
|
EcatSlave& slave_;
|
||
|
};
|
||
|
|
||
|
|
||
|
class EthEcatBuffer {
|
||
|
public:
|
||
|
EthEcatBuffer(EthEcat& ecat): ecat_{ecat} { }
|
||
|
|
||
|
EthEcat& get_ecat()
|
||
|
{
|
||
|
return ecat_;
|
||
|
}
|
||
|
|
||
|
std::vector<EcatBufferSlave>& get_buffer_slaves()
|
||
|
{
|
||
|
return buffer_slaves_;
|
||
|
}
|
||
|
|
||
|
void init(uint16_t rx_eeprom_addr, uint16_t tx_eeprom_addr);
|
||
|
|
||
|
void set_buffer_offset(uint16_t rx_offset, uint16_t tx_offset) {
|
||
|
for(EcatBufferSlave& buffer_slave : buffer_slaves_) {
|
||
|
buffer_slave.set_buffer_offset(rx_offset, tx_offset);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Размер в байтах !
|
||
|
void set_buffer_length(uint16_t rx_length, uint16_t tx_length) {
|
||
|
for(EcatBufferSlave& buffer_slave : buffer_slaves_) {
|
||
|
buffer_slave.set_buffer_length(rx_length, tx_length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void init_sync_manager(sync_manager sm_write, sync_manager sm_read);
|
||
|
void init_fmmu(fmmu fmmu_write, fmmu fmmu_read);
|
||
|
|
||
|
private:
|
||
|
EthEcat& ecat_;
|
||
|
|
||
|
std::vector<EcatBufferSlave> buffer_slaves_;
|
||
|
};
|
||
|
|
||
|
} // namespace ecat_buffer
|
||
|
|
||
|
} // namespace free_rtos
|
||
|
|
||
|
#endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_BUFFER_HPP_ */
|