Motion Master
Loading...
Searching...
No Matches
soem.h
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <cstdint>
5#include <functional>
6#include <map>
7#include <memory>
8#include <mutex>
9#include <sstream>
10#include <string>
11#include <type_traits>
12#include <unordered_map>
13#include <utility>
14#include <variant>
15#include <vector>
16
17#include <tl/expected.hpp>
18
19#include "base.h"
20#include "ethercat.h"
21#include "loguru.h"
22
23namespace mm::comm::soem {
24
25// 3-second SDO read/write timeout — long enough for devices with slower mailbox
26// implementations.
27inline constexpr int kSdoTimeoutUs = 3'000'000;
28
29// 10-second FoE write timeout — covers large firmware files over slow links.
30inline constexpr int kFoeTimeoutUs = 10'000'000;
31
32// 2-second FoE read timeout. Reads are small and a healthy device answers each
33// mailbox cycle within milliseconds, so a much shorter timeout than writes is
34// safe. Keeping it short bounds the cost of recovering from a transient/wedged
35// mailbox: a non-responsive read fails quickly and is retried (with a mailbox
36// drain) instead of stalling for the full write timeout on every attempt.
37inline constexpr int kFoeReadTimeoutUs = 2'000'000;
38
39// 10-second timeout for a file removal ("fs-remove=<name>" issued as an FoE
40// read). Removing a file erases flash, which can take several seconds — much
41// longer than reading one back.
42inline constexpr int kFoeRemoveTimeoutUs = 10'000'000;
43
44// 30-second timeout for removing the ESI file. It is large and its erase takes
45// considerably longer than other files (measured at ~17 s on a SOMANET drive).
46inline constexpr int kFoeRemoveEsiTimeoutUs = 30'000'000;
47
59std::map<std::string, std::string> mapMacAddressesToInterfaces();
60
76inline std::string uiConfigWithDefaultPdoMapping = R"(
77{
78 "pdoMapping": {
79 "rx": {
80 "0x1600": [
81 "0x60400010",
82 "0x60600008",
83 "0x60710010",
84 "0x607a0020",
85 "0x60ff0020",
86 "0x60b20010",
87 "0x27010020"
88 ],
89 "0x1601": [
90 "0x60fe0120",
91 "0x60fe0220"
92 ],
93 "0x1602": [
94 "0x27030020",
95 "0x60b10020",
96 "0x20120120"
97 ]
98 },
99 "tx": {
100 "0x1a00": [
101 "0x60410010",
102 "0x60610008",
103 "0x60640020",
104 "0x606c0020",
105 "0x60770010",
106 "0x60f40020",
107 "0x21110220",
108 "0x21130220"
109 ],
110 "0x1a01": [
111 "0x24010010",
112 "0x24020010",
113 "0x24030010",
114 "0x24040010",
115 "0x27020020"
116 ],
117 "0x1a02": [
118 "0x60fd0020"
119 ],
120 "0x1a03": [
121 "0x27040020",
122 "0x20f00020",
123 "0x60fc0020",
124 "0x606b0020",
125 "0x60740010",
126 "0x60790020"
127 ]
128 }
129 }
130})";
131
156int setPdoMappingFromUiConfig(ecx_contextt* context, uint16 slave);
157
175void checkPdoMapping(ecx_contextt* context, uint16 slave);
176
190uint16_t getSlaveState(ecx_contextt* context, uint16_t slave);
191
211std::string convertSlaveStateToString(int state);
212
235void updateMailboxSyncManagersOnNextState(ecx_contextt* context, uint16_t slave,
236 int targetState);
237
252
268void configureDetectedSmmModule(ecx_contextt* context, uint16_t slave);
269
307void transitionSlaves(ecx_contextt* context,
308 const std::vector<uint16_t>& positions,
309 uint16_t requiredState, uint16_t targetState,
310 const char* targetName,
311 std::chrono::steady_clock::duration timeout,
312 std::chrono::steady_clock::duration resendInterval =
313 std::chrono::seconds(2),
314 std::function<void()> tick = nullptr,
315 std::function<bool()> shouldAbort = nullptr);
316
329bool setSlaveState(
330 ecx_contextt* context, uint16_t slave, uint16_t targetState,
331 std::chrono::steady_clock::duration timeout = std::chrono::seconds(5));
332
366std::vector<uint8_t> readSii(ecx_contextt* context, uint16 position);
367
379mm::comm::base::PdoMappings readPdoMappings(ecx_contextt* context,
380 uint16_t slave);
381
397 const std::vector<mm::comm::base::PdoMappingEntry>& entries);
398
410void logIoMap(uint8_t* ioMap, size_t totalBytes);
411
426struct Fieldbus {
427 ecx_contextt context;
428 std::string iface;
429 uint8 group;
431
432 /* Used by the context */
433 uint8 map[4096];
434 ecx_portt port;
435 ec_slavet slavelist[EC_MAXSLAVE];
437 ec_groupt grouplist[EC_MAXGROUP];
438 uint8 esibuf[EC_MAXEEPBUF];
439 uint32 esimap[EC_MAXEEPBITMAP];
440 ec_eringt elist;
441 ec_idxstackT idxstack;
442 boolean ecaterror;
443 int64 DCtime;
444 ec_SMcommtypet SMcommtype[EC_MAX_MAPT];
445 ec_PDOassignt PDOassign[EC_MAX_MAPT];
446 ec_PDOdesct PDOdesc[EC_MAX_MAPT];
447 ec_eepromSMt eepSM;
448 ec_eepromFMMUt eepFMMU;
449};
450
465 uint16_t readLength;
466
473 uint16_t readOffset;
474
486
493 uint16_t writeLength;
494
501 uint16_t writeOffset;
502};
503
505 supportedProtocols, writeLength, writeOffset)
506
507
514struct SlaveInfoSyncManager {
523 uint32_t flags;
524
531 uint16_t length;
532
538 uint16_t startAddress;
539
550 uint8_t type;
551};
552
553NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SlaveInfoSyncManager, flags, length,
554 startAddress, type)
555
556
563struct SlaveInfoFmmu {
569 uint8_t active;
570
577 uint8_t logicalEndBit;
578
585 uint8_t logicalStartBit;
586
592 uint32_t logicalStartAddress;
593
599 uint16_t logicalLength;
600
607 uint8_t physicalStartBit;
608
614 uint16_t physicalStartAddress;
615
622 uint8_t type;
623};
624
625NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SlaveInfoFmmu, active, logicalEndBit,
626 logicalStartBit, logicalStartAddress,
627 logicalLength, physicalStartBit,
628 physicalStartAddress, type)
629
630
636struct SlaveInfo {
643 uint16_t alStatusCode;
644
651 uint16_t aliasAddress;
652
658 std::vector<SlaveInfoFmmu> fmmus;
659
666 SlaveInfoMailbox mailbox;
667
675 uint32_t productCode;
676
682 uint32_t position;
683
691 uint32_t revisionNumber;
692
699 std::vector<SlaveInfoSyncManager> syncManagers;
700
706 std::string name;
707
716 uint32_t vendorId;
717};
718
719NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SlaveInfo, alStatusCode, aliasAddress, fmmus,
720 mailbox, productCode, position,
721 revisionNumber, syncManagers, name, vendorId)
722
723
735SlaveInfo getSlaveInfo(ecx_contextt* context, uint16 position);
736
753void logSlaveInfo(ecx_contextt* context, uint16 position);
754
772void initFieldbus(std::unique_ptr<Fieldbus>& fieldbus,
773 const std::string& iface);
774
779class Slave {
780 public:
791 explicit Slave(ecx_contextt& context, uint16_t position);
792
801 uint16_t position() const;
802
811 uint32_t vendorId() const;
812
821 uint32_t productCode() const;
822
831 uint32_t revisionNumber() const;
832
838 int getState() const;
839
859 bool setState(int targetState, int timeoutMs = 0, int intervalMs = 100);
860
882 tl::expected<void, std::string> loadParameters(bool readValues = false);
883
896 void logParameters() const;
897
914
931
938 void clearParameters();
939
948 std::unordered_map<mm::comm::base::Parameter::Address,
951
964 mm::comm::base::Parameter& findParameter(uint16_t index, uint8_t subindex);
965
993 template <typename T = std::vector<uint8_t>>
994 T upload(uint16_t index, uint8_t subindex, bool refresh = true) {
995 // Lock the mailbox mutex to ensure thread safety
996 std::lock_guard<std::mutex> lock(mailboxMutex_);
997
998 // Check if the device is in a valid state for uploading
999 auto state = context_.slavelist[position_].state;
1000 if (state == EC_STATE_INIT || state == EC_STATE_BOOT) {
1001 throw std::runtime_error(
1002 "To upload object dictionary entries, the device must be in the (2) "
1003 "PRE-OPERATIONAL, (4) SAFE-OPERATIONAL, or (8) OPERATIONAL state. "
1004 "The current state is " +
1005 convertSlaveStateToString(state) + ".");
1006 }
1007
1008 // Find the previously loaded parameter
1009 auto& parameter = findParameter(index, subindex);
1010
1011 // Refresh data if needed (SDO read)
1012 if (refresh) {
1013 const std::unique_ptr<std::uint8_t[]> data =
1014 std::make_unique<std::uint8_t[]>(parameter.byteLength);
1015 auto wkc =
1016 ecx_SDOread(&context_, position_, parameter.index, parameter.subindex,
1017 false, &parameter.byteLength, data.get(), kSdoTimeoutUs);
1018 if (wkc <= 0) {
1019 LOG_F(ERROR, "Device %d: SDO read failed for %#04x:%02x! WKC: %d",
1020 position_, parameter.index, parameter.subindex, wkc);
1021 auto id = mm::comm::base::makeParameterId(parameter.index,
1022 parameter.subindex);
1023 throw std::runtime_error("Device " + std::to_string(position_) +
1024 ": SDO read failed for " + id +
1025 "! WKC: " + std::to_string(wkc));
1026 } else {
1027 std::vector<uint8_t> receivedData(data.get(),
1028 data.get() + parameter.byteLength);
1029 if (!parameter.trySetValue(receivedData)) {
1030 LOG_F(ERROR,
1031 "Device %d: Failed to set the value of parameter %#04x:%02x!",
1032 position_, parameter.index, parameter.subindex);
1033 }
1034 }
1035 }
1036
1037 // Return the appropriate type
1038 if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
1039 return parameter.data; // parameter.data should be std::vector<uint8_t>
1040 } else {
1041 // Otherwise, try to get the value as the requested type T
1042 auto value = parameter.getValue();
1043 if (auto ptr = std::get_if<T>(&value)) {
1044 return *ptr;
1045 } else {
1046 throw std::bad_variant_access(); // Type mismatch
1047 }
1048 }
1049 }
1050
1075 template <typename T = std::vector<uint8_t>>
1076 bool download(uint16_t index, uint8_t subindex, const T& value) {
1077 std::lock_guard<std::mutex> lock(mailboxMutex_);
1078
1079 // Check if device is in valid state for download
1080 auto state = context_.slavelist[position_].state;
1081 if (state == EC_STATE_INIT || state == EC_STATE_BOOT) {
1082 throw std::runtime_error(
1083 "To download object dictionary entries, the device must be in the "
1084 "(2) PRE-OPERATIONAL, (4) SAFE-OPERATIONAL, or (8) OPERATIONAL "
1085 "state. The current state is " +
1086 convertSlaveStateToString(state) + ".");
1087 }
1088
1089 auto& parameter = findParameter(index, subindex);
1090
1091 // Convert value to raw byte data
1092 std::vector<uint8_t> data;
1093 if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
1094 data = value;
1095 } else {
1096 // Set the value in the parameter model
1097 if (!parameter.trySetValue(value)) {
1098 LOG_F(ERROR,
1099 "Device %d: Failed to set the value of parameter %#04x:%02x!",
1100 position_, parameter.index, parameter.subindex);
1101 return false;
1102 }
1103 data = parameter.data; // Use the parameter's byte representation
1104 }
1105
1106 // Check if data size matches the expected parameter size
1107 if (data.size() != parameter.byteLength) {
1108 LOG_F(ERROR, "Data size mismatch: expected %d, got %zu",
1109 parameter.byteLength, data.size());
1110 throw std::runtime_error("Data size does not match the parameter size!");
1111 }
1112
1113 // Perform the SDO write
1114 auto wkc =
1115 ecx_SDOwrite(&context_, position_, parameter.index, parameter.subindex,
1116 false, parameter.byteLength, data.data(), kSdoTimeoutUs);
1117
1118 // Check write result
1119 if (wkc <= 0) {
1120 LOG_F(ERROR, "Device %d: SDO write failed for %#04x:%02x! WKC: %d",
1121 position_, parameter.index, parameter.subindex, wkc);
1122 return false;
1123 }
1124
1125 return true;
1126 }
1127
1137
1146 void updatePdoMappings();
1147
1159 void logPdoMappings() const;
1160
1166 mm::comm::base::PdoMappings& getPdoMappings();
1167
1190 void updateOutputs();
1191
1213 void updateParametersFromInputs();
1214
1240 tl::expected<std::vector<uint8_t>, std::string> readFile(
1241 const std::string& filename,
1242 size_t maxFileSize = 1 * 1024 * 1024, // 1 MB default max file size
1243 int retries = 5,
1244 std::chrono::steady_clock::duration retryWait =
1245 std::chrono::milliseconds(100));
1246
1260 tl::expected<std::vector<std::uint8_t>, std::string> readSdo(
1261 uint16_t index, uint8_t subindex);
1262
1276 tl::expected<ec_ODlistt, std::string> readODList(
1277 int retries = 5, std::chrono::steady_clock::duration retryWait =
1278 std::chrono::milliseconds(100));
1279
1298 tl::expected<void, std::string> readODDescription(
1299 uint16_t item, ec_ODlistt& odList, int retries = 5,
1300 std::chrono::steady_clock::duration retryWait =
1301 std::chrono::milliseconds(100));
1302
1319 tl::expected<ec_OElistt, std::string> readOE(
1320 uint16_t item, ec_ODlistt& odList, int retries = 5,
1321 std::chrono::steady_clock::duration retryWait =
1322 std::chrono::milliseconds(100));
1323
1324 private:
1325 ecx_contextt& context_;
1326 const uint16_t position_;
1329 std::mutex mailboxMutex_;
1330 std::unordered_map<mm::comm::base::Parameter::Address,
1332 parametersMap_;
1335 pdoMappings_;
1336};
1337
1338class Master {
1339 public:
1346 explicit Master();
1347
1358 explicit Master(const std::string& iface);
1359
1411 void init(const std::string& iface);
1412
1423 void deinit();
1424
1431 ~Master();
1432
1442 Fieldbus& getFieldbus() const;
1443
1452 std::string getInterfaceName() const;
1453
1462 size_t getIoMapSize() const;
1463
1526 tl::expected<int, std::string> initSlaves();
1527
1539 const std::vector<std::unique_ptr<Slave>>& slaves() const;
1540
1550 inline int expectedWkc() const {
1551 return fieldbus_->context.grouplist[fieldbus_->group].outputsWKC * 2 +
1552 fieldbus_->context.grouplist[fieldbus_->group].inputsWKC;
1553 }
1554
1564 int roundtrip();
1565
1595
1606 bool start();
1607
1608 private:
1622 std::unique_ptr<Fieldbus> fieldbus_;
1623
1635 std::vector<std::unique_ptr<Slave>> slaves_;
1636};
1637}; // namespace mm::comm::soem
Represents a device parameter identified by index and subindex.
Definition base.h:529
std::pair< uint16_t, uint8_t > Address
Alias for a pair of uint16_t and uint8_t representing a parameter address.
Definition base.h:539
int roundtrip()
Performs a complete send/receive process data cycle on the fieldbus.
Definition soem.cc:1629
Master()
Default constructor for the Master class.
Definition soem.cc:1546
const std::vector< std::unique_ptr< Slave > > & slaves() const
Returns a reference to the list of slaves.
Definition soem.cc:1625
tl::expected< int, std::string > initSlaves()
Initializes the slave devices on the EtherCAT network.
Definition soem.cc:1598
void exchangeProcessDataAndUpdateParameters()
Exchanges process data with slaves and updates parameters based on the response.
Definition soem.cc:1634
size_t getIoMapSize() const
Returns the total size of the I/O map for the current group.
Definition soem.cc:1593
Fieldbus & getFieldbus() const
Returns a reference to the Fieldbus instance.
Definition soem.cc:1589
void init(const std::string &iface)
Initializes the fieldbus using the specified network interface.
Definition soem.cc:1553
std::string getInterfaceName() const
Retrieves the interface name used by the fieldbus.
Definition soem.cc:1591
void deinit()
Deinitializes the fieldbus and releases associated resources.
Definition soem.cc:1571
bool start()
Initializes and starts the fieldbus master.
Definition soem.cc:1657
~Master()
Destructor for the Master class.
Definition soem.cc:1587
int expectedWkc() const
Calculates the expected working counter (WKC) for the current fieldbus group.
Definition soem.h:1550
uint32_t productCode() const
Gets the Product Code of the slave device.
Definition soem.cc:1047
uint32_t vendorId() const
Gets the Vendor ID of the slave device.
Definition soem.cc:1043
std::unordered_map< mm::comm::base::Parameter::Address, mm::comm::base::Parameter > & parametersMap()
Returns a reference to the internal parameters map.
Definition soem.cc:1340
mm::comm::base::Parameter & findParameter(uint16_t index, uint8_t subindex)
Finds and returns a reference to a Parameter in the parameters map.
Definition soem.cc:1344
uint32_t revisionNumber() const
Gets the Revision Number of the slave device.
Definition soem.cc:1051
T upload(uint16_t index, uint8_t subindex, bool refresh=true)
Uploads a parameter value from the device's object dictionary.
Definition soem.h:994
tl::expected< void, std::string > loadParameters(bool readValues=false)
Loads the parameters (object dictionary entries) from the EtherCAT slave device.
Definition soem.cc:1152
void clearParameters()
Clears all loaded object dictionary parameters.
Definition soem.cc:1336
void logTxPdoMappedParameters()
Logs all mapped TxPDO parameters with their current values.
Definition soem.cc:1321
Slave(ecx_contextt &context, uint16_t position)
Constructs a Slave object with a given context and position.
Definition soem.cc:1038
void logRxPdoMappedParameters()
Logs all mapped RxPDO parameters with their current values.
Definition soem.cc:1306
bool setState(int targetState, int timeoutMs=0, int intervalMs=100)
Attempts to set the slave to the specified EtherCAT state and optionally waits until it is reached.
Definition soem.cc:1057
void logParameters() const
Logs all loaded object dictionary parameters.
Definition soem.cc:1300
int getState() const
Reads the current state of the slave directly from the device.
Definition soem.cc:1055
uint16_t position() const
Gets the position of the slave.
Definition soem.cc:1041
bool download(uint16_t index, uint8_t subindex, const T &value)
Downloads a value to the specified object dictionary entry via SDO.
Definition soem.h:1076
uint8_t type
Definition co_dictionary.h:1
const char ** name
Definition co_dictionary.h:7
uint8_t * value
Definition co_dictionary.h:9
uint16_t index
Definition co_dictionary.h:0
std::string makeParameterId(int index, int subindex)
Formats the given index and subindex into a parameter identifier string.
Definition base.h:1657
Definition soem.cc:41
constexpr int kFoeReadTimeoutUs
Definition soem.h:37
mm::comm::base::PdoMappings readPdoMappings(ecx_contextt *context, uint16_t slave)
Read and parse all mapped PDO entries for a given slave.
Definition soem.cc:945
uint16_t getSlaveState(ecx_contextt *context, uint16_t slave)
Reads the current state of a specific EtherCAT slave directly from the device via an FPRD datagram.
Definition soem.cc:550
constexpr int kFoeTimeoutUs
Definition soem.h:30
void logPdoMappingEntries(const std::vector< mm::comm::base::PdoMappingEntry > &entries)
Logs PDO mapping entries grouped by PDO index.
Definition soem.cc:1007
std::string convertSlaveStateToString(int state)
Converts a numeric EtherCAT state value into a human-readable string.
Definition soem.cc:565
void resetBootMailboxTracking()
Clears the internal record of which slaves hold BOOT-sized mailbox sync managers.
Definition soem.cc:603
constexpr int kSdoTimeoutUs
Definition soem.h:27
void transitionSlaves(ecx_contextt *context, const std::vector< uint16_t > &positions, uint16_t requiredState, uint16_t targetState, const char *targetName, std::chrono::steady_clock::duration timeout, std::chrono::steady_clock::duration resendInterval, std::function< void()> tick, std::function< bool()> shouldAbort)
Transitions multiple EtherCAT slaves to a target state using a single-threaded fire-then-poll pattern...
Definition soem.cc:608
std::string uiConfigWithDefaultPdoMapping
Default UI configuration used for PDO mapping.
Definition soem.h:76
void initFieldbus(std::unique_ptr< Fieldbus > &fieldbus, const std::string &iface)
Initializes a Fieldbus instance for EtherCAT communication.
Definition soem.cc:1513
void updateMailboxSyncManagersOnNextState(ecx_contextt *context, uint16_t slave, int targetState)
Updates the mailbox and sync manager (SM) configurations for an EtherCAT slave when transitioning to ...
Definition soem.cc:742
void logIoMap(uint8_t *ioMap, size_t totalBytes)
Logs the I/O map as a formatted hexadecimal string.
Definition soem.cc:1028
void checkPdoMapping(ecx_contextt *context, uint16 slave)
Diagnoses and prints the PDO mapping for a given slave.
Definition soem.cc:468
void configureDetectedSmmModule(ecx_contextt *context, uint16_t slave)
Reads the detected SMM module ID from the slave device and configures the module identification objec...
Definition soem.cc:872
constexpr int kFoeRemoveTimeoutUs
Definition soem.h:42
std::map< std::string, std::string > mapMacAddressesToInterfaces()
Maps MAC addresses to their corresponding network interface names.
Definition soem.cc:49
int setPdoMappingFromUiConfig(ecx_contextt *context, uint16 slave)
Sets PDO mapping for a specified EtherCAT slave using UI configuration.
Definition soem.cc:285
uint16 position
Definition soem.h:735
void logSlaveInfo(ecx_contextt *context, uint16 position)
Logs detailed information about a specific EtherCAT slave in JSON format.
Definition soem.cc:222
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SlaveInfoMailbox, readLength, readOffset, supportedProtocols, writeLength, writeOffset) struct SlaveInfoSyncManager
Information about a slave's Sync Manager (SM) configuration.
Definition soem.h:504
constexpr int kFoeRemoveEsiTimeoutUs
Definition soem.h:46
SlaveInfo getSlaveInfo(ecx_contextt *context, uint16 position)
Definition soem.cc:170
std::vector< uint8_t > readSii(ecx_contextt *context, uint16 position)
Read the complete Slave Information Interface (SII) EEPROM from an EtherCAT slave device.
Definition soem.cc:902
bool setSlaveState(ecx_contextt *context, uint16_t slave, uint16_t targetState, std::chrono::steady_clock::duration timeout)
Transitions a single EtherCAT slave to targetState.
Definition soem.cc:734
Specialization of std::hash for std::pair<uint16_t, uint8_t>.
Definition util.h:612
Represents the mapped PDO entries for a slave device.
Definition base.h:171
Structure representing the Fieldbus configuration and context for EtherCAT communication.
Definition soem.h:426
boolean ecaterror
Definition soem.h:442
ec_idxstackT idxstack
Definition soem.h:441
ec_eepromFMMUt eepFMMU
Definition soem.h:448
ec_groupt grouplist[EC_MAXGROUP]
Definition soem.h:437
std::string iface
Definition soem.h:428
uint8 group
Definition soem.h:429
int slavecount
Definition soem.h:436
uint8 esibuf[EC_MAXEEPBUF]
Definition soem.h:438
uint32 esimap[EC_MAXEEPBITMAP]
Definition soem.h:439
int64 DCtime
Definition soem.h:443
ec_eepromSMt eepSM
Definition soem.h:447
ec_PDOassignt PDOassign[EC_MAX_MAPT]
Definition soem.h:445
uint8 map[4096]
Definition soem.h:433
ecx_contextt context
Definition soem.h:427
int roundtripTime
Definition soem.h:430
ec_PDOdesct PDOdesc[EC_MAX_MAPT]
Definition soem.h:446
ecx_portt port
Definition soem.h:434
ec_slavet slavelist[EC_MAXSLAVE]
Definition soem.h:435
ec_SMcommtypet SMcommtype[EC_MAX_MAPT]
Definition soem.h:444
ec_eringt elist
Definition soem.h:440
Information about a slave's mailbox configuration.
Definition soem.h:458
uint16_t writeOffset
Offset of the mailbox write area within the slave's memory.
Definition soem.h:501
uint16_t supportedProtocols
Supported mailbox protocols as a bitmask.
Definition soem.h:485
uint16_t readOffset
Offset of the mailbox read area within the slave's memory.
Definition soem.h:473
uint16_t readLength
Length of the mailbox read area (in bytes).
Definition soem.h:465
uint16_t writeLength
Length of the mailbox write area (in bytes).
Definition soem.h:493