2023-05-03 14:01:32 +03:00
|
|
|
/*
|
2023-06-06 10:27:01 +03:00
|
|
|
* eth_ecat_telegram.cpp
|
2023-05-03 14:01:32 +03:00
|
|
|
*
|
2023-06-06 10:27:01 +03:00
|
|
|
* Created on: Jun 5, 2023
|
2023-05-03 14:01:32 +03:00
|
|
|
* Author: algin
|
|
|
|
|
*/
|
|
|
|
|
|
2023-06-26 18:22:30 +03:00
|
|
|
#include "free_rtos/ethernet_industry/eth_ecat_telegram.hpp"
|
2023-05-03 14:01:32 +03:00
|
|
|
|
|
|
|
|
namespace free_rtos {
|
|
|
|
|
|
2023-06-06 10:27:01 +03:00
|
|
|
namespace telegram {
|
2023-05-03 14:01:32 +03:00
|
|
|
|
2023-09-07 13:15:47 +03:00
|
|
|
const char EcatTelegramStatus::SuccessString[] = "Success !";
|
|
|
|
|
const char EcatTelegramStatus::BusyString[] = "Busy. Transfer in progress...";
|
2023-11-01 11:48:36 +03:00
|
|
|
const char EcatTelegramStatus::WarningTransferErrorString[] = "Warning ! Transfer error";
|
|
|
|
|
const char EcatTelegramStatus::WarningTimeoutErrorString[] = "Warning ! Connection timeout error";
|
|
|
|
|
const char EcatTelegramStatus::WarningWkcErrorString[] = "Warning ! WKC error";
|
2023-09-07 13:15:47 +03:00
|
|
|
const char EcatTelegramStatus::FatalErrorString[] = "Fatal error ! Transfer attempts exceeded";
|
2023-09-06 18:09:23 +03:00
|
|
|
|
|
|
|
|
const EcatDescription EcatTelegramStatus::descriptions[] = {
|
|
|
|
|
{EcatTelegramStatus::SuccessString, sizeof(EcatTelegramStatus::SuccessString)},
|
|
|
|
|
{EcatTelegramStatus::BusyString, sizeof(EcatTelegramStatus::BusyString)},
|
2023-09-07 13:15:47 +03:00
|
|
|
{EcatTelegramStatus::WarningTransferErrorString, sizeof(EcatTelegramStatus::WarningTransferErrorString)},
|
2023-09-08 17:37:15 +03:00
|
|
|
{EcatTelegramStatus::WarningTimeoutErrorString, sizeof(EcatTelegramStatus::WarningTimeoutErrorString)},
|
2023-09-07 13:15:47 +03:00
|
|
|
{EcatTelegramStatus::WarningWkcErrorString, sizeof(EcatTelegramStatus::WarningWkcErrorString)},
|
2023-09-06 18:09:23 +03:00
|
|
|
{EcatTelegramStatus::FatalErrorString, sizeof(EcatTelegramStatus::FatalErrorString)}
|
|
|
|
|
};
|
|
|
|
|
|
2023-05-03 14:01:32 +03:00
|
|
|
int32_t EcatTelegram::Process(uint8_t *p_data, uint32_t len) {
|
2023-09-06 18:09:23 +03:00
|
|
|
// TODO: Don't forget to subtract sizeof(TEthFrameHeader) !
|
2023-09-27 15:37:10 +03:00
|
|
|
uint8_t *p_datagram_last = unpack(p_data - sizeof(TEthFrameHeader));
|
|
|
|
|
|
|
|
|
|
if(p_datagram_last == nullptr) {
|
2023-09-28 14:13:26 +03:00
|
|
|
//DebugP_log((char*)"Warning ! Repeated packet skipped\r\n");
|
2023-09-27 15:37:10 +03:00
|
|
|
return 0;
|
|
|
|
|
}
|
2023-06-09 13:57:20 +03:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
DebugP_log((char*)"Process started\r\n");
|
|
|
|
|
|
|
|
|
|
for(uint8_t *data = p_data; data < p_data + len; data++) {
|
|
|
|
|
DebugP_log((char*)"0x%01x ", *data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DebugP_log((char*)"\r\n");
|
|
|
|
|
*/
|
2023-05-26 11:06:54 +03:00
|
|
|
|
2023-05-03 14:01:32 +03:00
|
|
|
rx_sem_.post();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-26 10:21:41 +03:00
|
|
|
uint16_t EcatTelegram::Sender(HandlerArgs& handlerArgs, size_t scatter_segment) {
|
2023-10-24 14:02:04 +03:00
|
|
|
uint8_t *raw = pack(handlerArgs.buffer);
|
2023-06-08 12:27:49 +03:00
|
|
|
|
2023-06-09 13:57:20 +03:00
|
|
|
//DebugP_log((char*)"Sender started\r\n");
|
|
|
|
|
|
2023-10-24 14:02:04 +03:00
|
|
|
return raw - handlerArgs.buffer;
|
2023-06-08 12:27:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t* EcatTelegram::pack(uint8_t *raw) {
|
|
|
|
|
TEthFrameHeader *p_eth_hdr = new(raw) TEthFrameHeader{ {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
|
|
|
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
|
|
|
|
|
ETH_PROT_ECAT_LE };
|
2023-06-26 18:22:30 +03:00
|
|
|
TEcatFrameHeader *p_hdr = new(raw + sizeof(TEthFrameHeader)) TEcatFrameHeader{ .bits = { .length = 0,
|
2024-02-21 10:41:56 +03:00
|
|
|
.type = static_cast<uint16_t>(ec_network::PROTOCOL_TYPE) } };
|
2023-06-08 12:27:49 +03:00
|
|
|
uint8_t *p_datagram_first = raw + sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader);
|
2023-05-03 14:01:32 +03:00
|
|
|
uint8_t *p_datagram_last = p_datagram_first;
|
2023-09-06 18:09:23 +03:00
|
|
|
auto first = datagram_queue_.get_first();
|
2023-05-03 14:01:32 +03:00
|
|
|
|
2023-05-10 15:10:01 +03:00
|
|
|
(void)p_eth_hdr;
|
|
|
|
|
(void)p_hdr;
|
|
|
|
|
|
2023-09-27 15:37:10 +03:00
|
|
|
if(first != nullptr) {
|
|
|
|
|
p_datagram_last = first->pack_all(p_datagram_first, idx_);
|
2023-09-08 17:37:15 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-03 14:01:32 +03:00
|
|
|
p_hdr->bits.length = p_datagram_last - p_datagram_first;
|
2023-06-08 12:27:49 +03:00
|
|
|
|
|
|
|
|
return p_datagram_last;
|
2023-05-03 14:01:32 +03:00
|
|
|
}
|
|
|
|
|
|
2023-06-08 12:27:49 +03:00
|
|
|
uint8_t* EcatTelegram::unpack(uint8_t *raw) {
|
2023-05-26 11:06:54 +03:00
|
|
|
TEthFrameHeader *p_eth_hdr = reinterpret_cast<TEthFrameHeader*>(raw);
|
|
|
|
|
TEcatFrameHeader *p_hdr = reinterpret_cast<TEcatFrameHeader*>(raw + sizeof(TEthFrameHeader));
|
|
|
|
|
uint8_t *p_datagram_first = raw + sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader);
|
2023-05-03 14:01:32 +03:00
|
|
|
uint8_t *p_datagram_last = p_datagram_first;
|
2023-09-06 18:09:23 +03:00
|
|
|
auto first = datagram_queue_.get_first();
|
2023-05-03 14:01:32 +03:00
|
|
|
|
2023-09-27 15:37:10 +03:00
|
|
|
if(first != nullptr) {
|
|
|
|
|
p_datagram_last = first->unpack_all(p_datagram_first, idx_);
|
2023-09-08 17:37:15 +03:00
|
|
|
}
|
|
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
return p_datagram_last;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool EcatTelegram::transfer() {
|
2023-10-06 17:50:38 +03:00
|
|
|
MAKE_AUTO_PROFILER(transfer, 32);
|
|
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
auto first = datagram_queue_.get_first();
|
2023-10-24 14:02:04 +03:00
|
|
|
TxFlowHandlerArgs txFlowHandlerArgs;
|
2023-11-01 11:48:36 +03:00
|
|
|
uint32_t transfer_attempts = max_transfer_attempts_ + 1;
|
2023-10-06 17:50:38 +03:00
|
|
|
uint32_t tick_counter_start;
|
|
|
|
|
uint32_t tick_counter_diff;
|
2023-09-25 14:58:34 +03:00
|
|
|
bool status = (first == nullptr);
|
2023-10-06 10:44:37 +03:00
|
|
|
int32_t sts;
|
2023-06-13 12:37:00 +03:00
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
if(status == true) {
|
2023-09-06 18:09:23 +03:00
|
|
|
status_.result = EcatTelegramResult::SUCCESS;
|
2023-06-13 12:37:00 +03:00
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
return status;
|
2023-06-13 12:37:00 +03:00
|
|
|
}
|
2023-05-10 15:10:01 +03:00
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
status_.result = EcatTelegramResult::BUSY;
|
2023-06-15 15:16:51 +03:00
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
first->reset_all_wkc();
|
2023-06-16 10:18:13 +03:00
|
|
|
|
2023-10-24 14:02:04 +03:00
|
|
|
txFlowHandlerArgs.port_id = port_id_;
|
|
|
|
|
txFlowHandlerArgs.stack_handler = this;
|
2023-10-26 10:21:41 +03:00
|
|
|
txFlowHandlerArgs.buffer = nullptr;
|
2023-10-24 14:02:04 +03:00
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
while(1) {
|
2023-10-06 17:50:38 +03:00
|
|
|
tick_counter_start = ecat_timer_.Wait();
|
2023-09-25 14:58:34 +03:00
|
|
|
|
2023-11-01 11:48:36 +03:00
|
|
|
transfer_attempts--;
|
|
|
|
|
status = (transfer_attempts != 0);
|
2023-06-08 12:27:49 +03:00
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
if(status == false) {
|
2023-09-07 13:15:47 +03:00
|
|
|
DebugP_log((char*)"%s\r\n", status_.get_description().string);
|
|
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
status_.attempts_exceeded_errors++;
|
|
|
|
|
status_.result = EcatTelegramResult::FATAL_ERROR;
|
2023-05-03 14:01:32 +03:00
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
DebugP_log((char*)"%s: %d\r\n", status_.get_description().string, max_transfer_attempts_);
|
2023-11-01 11:48:36 +03:00
|
|
|
DebugP_log((char*)"%s: %d\r\n", status_.get_description(EcatTelegramResult::WARNING_TRANSFER_ERROR).string, status_.transfer_errors);
|
|
|
|
|
DebugP_log((char*)"%s: %d\r\n", status_.get_description(EcatTelegramResult::WARNING_WKC_ERROR).string, status_.expected_wkc_errors);
|
2023-10-06 17:50:38 +03:00
|
|
|
DebugP_log((char*)"Tick counter diff: %d/%d\r\n", tick_counter_diff, counter_timeout_ticks_);
|
|
|
|
|
DebugP_log((char*)"Last profiler item %lld cycles\r\n", GET_LAST_PROFILER_ITEM(transfer));
|
|
|
|
|
FORCE_DUMP_PROFILER(transfer);
|
2023-09-07 13:15:47 +03:00
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
break;
|
|
|
|
|
}
|
2023-05-03 14:01:32 +03:00
|
|
|
|
2023-10-24 14:02:04 +03:00
|
|
|
status = tx_flow_.send(txFlowHandlerArgs, 1);
|
2023-06-09 13:57:20 +03:00
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
if(status == false) {
|
2023-09-06 18:09:23 +03:00
|
|
|
status_.transfer_errors++;
|
2023-09-07 13:15:47 +03:00
|
|
|
status_.result = EcatTelegramResult::WARNING_TRANSFER_ERROR;
|
2023-07-11 12:55:52 +03:00
|
|
|
|
2023-09-18 10:25:47 +03:00
|
|
|
//DebugP_log((char*)"%s: %d\r\n", status_.get_description().string, status_.transfer_errors);
|
|
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
continue;
|
|
|
|
|
}
|
2023-05-03 14:01:32 +03:00
|
|
|
|
2023-10-06 17:50:38 +03:00
|
|
|
{
|
|
|
|
|
MAKE_PROFILER_AUTO_ITEM(transfer, 32, 0);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
sts = rx_sem_.pend(semaphore_timeout_ticks_);
|
|
|
|
|
|
|
|
|
|
tick_counter_diff = diff(tick_counter_start, ecat_timer_.GetTickCounter());
|
2023-09-25 14:58:34 +03:00
|
|
|
|
2023-11-01 11:48:36 +03:00
|
|
|
if((sts != SystemP_SUCCESS) && ( tick_counter_diff < (counter_timeout_ticks_ - semaphore_timeout_tolerance_) )) {
|
2023-10-06 17:50:38 +03:00
|
|
|
//DebugP_log((char*)"rx_sem_ fake timeout detected !\r\n", );
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
} while(1);
|
|
|
|
|
}
|
2023-10-06 10:44:37 +03:00
|
|
|
|
2023-10-06 17:50:38 +03:00
|
|
|
if(sts != SystemP_SUCCESS) {
|
2023-09-08 17:37:15 +03:00
|
|
|
status_.transfer_errors++;
|
|
|
|
|
status_.result = EcatTelegramResult::WARNING_TIMEOUT_ERROR;
|
|
|
|
|
|
2023-09-18 10:25:47 +03:00
|
|
|
//DebugP_log((char*)"%s: %d\r\n", status_.get_description().string, status_.transfer_errors);
|
2023-10-06 10:44:37 +03:00
|
|
|
//DebugP_log((char*)"Last profiler item: %lld\r\n", GET_LAST_PROFILER_ITEM(Test_static));
|
|
|
|
|
//FORCE_DUMP_PROFILER(Test_static);
|
2023-09-18 10:25:47 +03:00
|
|
|
|
2023-09-08 17:37:15 +03:00
|
|
|
continue;
|
|
|
|
|
}
|
2023-06-08 12:27:49 +03:00
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
status = first->all_as_expected();
|
2023-09-06 18:09:23 +03:00
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
if(status == false) {
|
2023-09-06 18:09:23 +03:00
|
|
|
status_.expected_wkc_errors++;
|
2023-09-07 13:15:47 +03:00
|
|
|
status_.result = EcatTelegramResult::WARNING_WKC_ERROR;
|
2023-09-06 18:09:23 +03:00
|
|
|
|
2023-09-18 10:25:47 +03:00
|
|
|
//DebugP_log((char*)"%s: %d\r\n", status_.get_description().string, status_.expected_wkc_errors);
|
|
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
status_.result = EcatTelegramResult::SUCCESS;
|
2023-09-06 18:09:23 +03:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-08 17:37:15 +03:00
|
|
|
datagram_queue_.clear();
|
2023-09-27 15:37:10 +03:00
|
|
|
++idx_;
|
2023-09-08 17:37:15 +03:00
|
|
|
|
2023-09-25 14:58:34 +03:00
|
|
|
return status;
|
2023-05-03 14:01:32 +03:00
|
|
|
}
|
2023-06-15 15:16:51 +03:00
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
bool EcatTelegram::transfer(datagram::IEcatDatagram& next) {
|
2023-06-16 13:01:24 +03:00
|
|
|
datagram_queue_ + next;
|
2023-05-03 14:01:32 +03:00
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
return transfer();
|
2023-06-16 13:01:24 +03:00
|
|
|
}
|
2023-06-15 15:16:51 +03:00
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
bool EcatTelegram::transfer(queue::Queue<datagram::IEcatDatagram>& next) {
|
2023-06-16 13:01:24 +03:00
|
|
|
datagram_queue_ + next;
|
2023-06-15 15:16:51 +03:00
|
|
|
|
2023-09-06 18:09:23 +03:00
|
|
|
return transfer();
|
2023-06-15 15:16:51 +03:00
|
|
|
}
|
2023-06-16 13:01:24 +03:00
|
|
|
|
2023-05-03 14:01:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|