sitara_depot/components/free_rtos/ethernet_industry/eth_ecat_buffer.hpp

355 lines
12 KiB
C++
Raw Normal View History

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