Motion Master 6.0.0-alpha.111
Next-generation motion control software
Loading...
Searching...
No Matches
soem_fieldbus_driver.h
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4#include <cstddef>
5#include <cstdint>
6#include <memory>
7#include <set>
8#include <span>
9#include <string>
10#include <vector>
11
14
15struct ecx_context;
16
17namespace mm::comm::soem {
18
27 std::string ifname;
34 bool mailboxStatusFmmu = false;
35};
36
53 public:
57
59 ~SoemFieldbusDriver() override;
60
63
70 std::expected<void, std::string> init() override;
71
79 std::expected<int, std::string> scan() override;
80
83 SlaveInfo slaveInfo(uint16_t position) const override;
84
86 uint16_t slaveState(uint16_t position) const override;
87
89 uint16_t mailboxProtocols(uint16_t position) const override;
90
92 std::expected<void, std::string> configureProcessData() override;
93
96
98 std::vector<SlaveConfig> busConfig() const override;
99
108 int exchangeProcessData(std::span<const uint8_t> outputs, std::span<uint8_t> inputs) override;
109
111 void stop() override;
112
117 std::optional<int> readDevicesOnWire() override;
118
120 std::expected<std::vector<FieldbusDriver::SlaveStateRaw>, std::string> readStates(
121 const std::vector<uint16_t>& positions) override;
122
124 std::expected<std::vector<SlaveDiagnostics>, std::string> readDiagnostics(
125 const std::vector<uint16_t>& positions) override;
126
128 std::expected<std::vector<DcSyncDiagnostics>, std::string> readDcSync(
129 const std::vector<uint16_t>& positions) override;
130
132 std::string adapter() const override { return ifname_; }
133
135 std::expected<std::vector<uint8_t>, std::string> readSdo(uint16_t slavePosition, uint16_t index,
136 uint8_t subindex) override;
137
139 std::expected<std::vector<uint8_t>, std::string> readSdoComplete(uint16_t slavePosition,
140 uint16_t index) override;
141
143 std::expected<void, std::string> writeSdo(uint16_t slavePosition, uint16_t index,
144 uint8_t subindex,
145 std::span<const uint8_t> data) override;
146
148 std::expected<OdRead, std::string> readObjectDictionary(uint16_t slavePosition) override;
149
151 std::expected<std::vector<uint8_t>, std::string> readSii(uint16_t slavePosition) override;
152
154 std::expected<void, std::string> writeSii(uint16_t slavePosition,
155 std::span<const uint8_t> data) override;
156
158 std::expected<std::vector<uint8_t>, FoeError> readFile(
159 uint16_t slavePosition, const std::string& filename,
160 std::chrono::milliseconds timeout) override;
161
163 std::expected<void, FoeError> writeFile(uint16_t slavePosition, const std::string& filename,
164 std::span<const uint8_t> data) override;
165
171 std::expected<void, std::string> readRegister(uint16_t slavePosition, uint16_t address,
172 std::span<uint8_t> data) override;
173
179 std::expected<void, std::string> writeRegister(uint16_t slavePosition, uint16_t address,
180 std::span<const uint8_t> data) override;
181
183 std::expected<ProcessDataWatchdogConfig, std::string> processDataWatchdog(
184 uint16_t slavePosition) override;
185
187 std::expected<ProcessDataWatchdogConfig, std::string> setProcessDataWatchdog(
188 uint16_t slavePosition, std::chrono::nanoseconds timeout) override;
189
191 int slaveCount() const;
192
195 const std::vector<uint16_t>& positions, std::optional<EtherCatState> requiredState,
196 EtherCatState targetState, std::chrono::steady_clock::duration timeout,
197 std::chrono::steady_clock::duration resendInterval = std::chrono::seconds(2),
198 std::function<void()> tick = nullptr, std::function<bool()> shouldAbort = nullptr) override;
199
200 private:
210 std::expected<void, std::string> deactivateMailboxStatusFmmus();
211
227 std::expected<void, std::string> blockLrwOnPruIcssSlaves();
228
234 void closeContext();
235
243 void publishSlaveStates();
244
245 std::string ifname_;
246 // One lock for the bus and one per position. Sized to slavelist in the constructor, so every
247 // position the driver accepts has a lock.
248 mutable ControlPlaneLocks controlPlane_;
249 // Keep SOEM 2.0's mailbox-status FMMU active (see the constructor). Default false: the FMMU is
250 // deactivated after every map by deactivateMailboxStatusFmmus().
251 bool mailboxStatusFmmu_ = false;
252 // ecx_contextt is several hundred KB (EC_MAXSLAVE slave entries) — heap-
253 // allocated and null until init() succeeds.
254 std::unique_ptr<ecx_context> ctx_;
255 // EtherCAT IOmap: ecx_config_map_group lays the whole bus's process data out here as
256 // [all outputs | all inputs]. Sized to kMaxProcessImageBytes so it matches the cap
257 // configureProcessData() enforces and the ProcessBuffer scratch layered on top — the
258 // three must agree, or a bus the rest of the stack accepts would overflow or be rejected
259 // here. At ~100 bytes per axis across both directions this holds ~320 axes — far beyond the
260 // ~50 the stack targets.
261 uint8_t map_[kMaxProcessImageBytes]{};
262 // Lock-free mirror of every slave's cached AL status, indexed by position exactly as SOEM's
263 // slavelist is (index 0 being the master). This exists so slaveState() can honour the
264 // "must not block" contract on FieldbusDriver::slaveState: the value it serves lives in SOEM's
265 // slavelist, which is only safe to touch under the drive's lock, and an FoE transfer holds that
266 // lock for the whole transfer. Rather than make every reader wait on a flash write to learn an AL
267 // state, the writers publish here at the end of each locked scope and readers take it without a
268 // lock.
269 //
270 // Allocated once in the constructor at SOEM's compile-time maximum and never reallocated, so a
271 // reader may index it for the driver's whole lifetime with nothing to synchronise against — the
272 // reason it is not a vector<atomic>, whose reallocation paths are ill-formed on libc++ and MSVC.
273 // Sized from the .cc so this header keeps SOEM out of its includes.
274 std::unique_ptr<std::atomic<uint16_t>[]> slaveStates_;
275 // Immutable after construction, so it needs no synchronisation of its own.
276 std::size_t slaveStatesSize_ = 0;
277 // 1-based positions whose context currently holds BOOT-sized mailbox sync
278 // managers (set when we drive a slave into BOOT). ecx_config_init programs the
279 // correct PRE-OP mailbox SMs for every slave during scan(), so a fresh-scan
280 // INIT→PRE-OP needs no reprogramming; only a slave returning from BOOT (e.g.
281 // after a firmware download) carries stale BOOT SMs that must be reset.
282 // Guarded by the bus lock held exclusive. Cleared by scan() (which re-runs ecx_config_init).
283 std::set<uint16_t> bootMailboxSlaves_;
284 // The low byte of ESC register 0x0000 of each slave, 1-based like the slave list, read by scan()
285 // and empty where the read failed. Guarded by the bus lock like the slave list.
286 std::vector<std::optional<uint8_t>> escTypes_;
287};
288
289} // namespace mm::comm::soem
The control-plane locks of one fieldbus driver: one for the bus, one per drive.
Definition control_plane_locks.h:87
Abstract interface for an EtherCAT fieldbus driver.
Definition fieldbus_driver.h:474
SOEM-backed EtherCAT fieldbus driver.
Definition soem_fieldbus_driver.h:52
std::optional< int > readDevicesOnWire() override
Counts the devices on the wire, or returns nothing when the transport cannot.
Definition soem_fieldbus_driver.cc:777
std::expected< void, FoeError > writeFile(uint16_t slavePosition, const std::string &filename, std::span< const uint8_t > data) override
Writes a file to the slave via File over EtherCAT (FoE).
Definition soem_fieldbus_driver.cc:1616
std::expected< void, std::string > writeSdo(uint16_t slavePosition, uint16_t index, uint8_t subindex, std::span< const uint8_t > data) override
Writes an object dictionary entry to a slave (CoE SDO download).
Definition soem_fieldbus_driver.cc:1074
void transitionToState(const std::vector< uint16_t > &positions, std::optional< EtherCatState > requiredState, EtherCatState targetState, std::chrono::steady_clock::duration timeout, std::chrono::steady_clock::duration resendInterval=std::chrono::seconds(2), std::function< void()> tick=nullptr, std::function< bool()> shouldAbort=nullptr) override
Commands a set of devices to targetState and blocks until all arrive or timeout elapses.
Definition soem_fieldbus_driver.cc:1901
int exchangeProcessData(std::span< const uint8_t > outputs, std::span< uint8_t > inputs) override
Copies outputs into the IOmap, sends and receives, copies inputs back out.
Definition soem_fieldbus_driver.cc:679
std::expected< void, std::string > writeRegister(uint16_t slavePosition, uint16_t address, std::span< const uint8_t > data) override
Writes bytes to an ESC register via FPWR.
Definition soem_fieldbus_driver.cc:1660
std::expected< OdRead, std::string > readObjectDictionary(uint16_t slavePosition) override
Enumerates the entire CoE object dictionary of a slave via SDO Info.
Definition soem_fieldbus_driver.cc:1341
std::expected< std::vector< SlaveDiagnostics >, std::string > readDiagnostics(const std::vector< uint16_t > &positions) override
Reads live link-quality and watchdog diagnostics for each slave in positions.
Definition soem_fieldbus_driver.cc:822
std::expected< void, std::string > init() override
Opens the NIC and initialises the SOEM master context.
Definition soem_fieldbus_driver.cc:110
std::expected< void, std::string > writeSii(uint16_t slavePosition, std::span< const uint8_t > data) override
Writes a raw SII (EEPROM) image to a slave.
Definition soem_fieldbus_driver.cc:1535
std::expected< std::vector< DcSyncDiagnostics >, std::string > readDcSync(const std::vector< uint16_t > &positions) override
Reads live distributed-clock synchronisation status for each slave in positions.
Definition soem_fieldbus_driver.cc:882
SlaveInfo slaveInfo(uint16_t position) const override
Returns the immutable identity fields for the slave at position.
Definition soem_fieldbus_driver.cc:719
void stop() override
Closes the NIC and releases all driver resources.
Definition soem_fieldbus_driver.cc:698
std::expected< std::vector< uint8_t >, FoeError > readFile(uint16_t slavePosition, const std::string &filename, std::chrono::milliseconds timeout) override
Reads a file from the slave via File over EtherCAT (FoE).
Definition soem_fieldbus_driver.cc:1570
std::expected< ProcessDataWatchdogConfig, std::string > processDataWatchdog(uint16_t slavePosition) override
Reads the process-data (sync-manager) watchdog configuration of one slave.
Definition soem_fieldbus_driver.cc:1703
SoemFieldbusDriver(const SoemFieldbusDriver &)=delete
~SoemFieldbusDriver() override
Closes the NIC if init() succeeded.
Definition soem_fieldbus_driver.cc:48
std::expected< ProcessDataWatchdogConfig, std::string > setProcessDataWatchdog(uint16_t slavePosition, std::chrono::nanoseconds timeout) override
Sets the process-data (sync-manager) watchdog timeout of one slave.
Definition soem_fieldbus_driver.cc:1733
std::expected< std::vector< FieldbusDriver::SlaveStateRaw >, std::string > readStates(const std::vector< uint16_t > &positions) override
Reads the current AL Status for each slave in positions.
Definition soem_fieldbus_driver.cc:790
std::expected< std::vector< uint8_t >, std::string > readSdoComplete(uint16_t slavePosition, uint16_t index) override
Reads an entire object in one CoE SDO upload using Complete Access.
Definition soem_fieldbus_driver.cc:1031
std::expected< int, std::string > scan() override
Scans the bus for slaves and configures their sync managers and FMMUs.
Definition soem_fieldbus_driver.cc:141
uint16_t slaveState(uint16_t position) const override
Returns the last-known AL status for a slave without any bus I/O.
Definition soem_fieldbus_driver.cc:741
std::string adapter() const override
The network adapter the bus is on, as the OS names it, or empty for a transport that sends no EtherCA...
Definition soem_fieldbus_driver.h:132
std::expected< void, std::string > readRegister(uint16_t slavePosition, uint16_t address, std::span< uint8_t > data) override
Reads bytes from an ESC register via FPRD.
Definition soem_fieldbus_driver.cc:1641
int slaveCount() const
Returns the number of discovered slaves, or 0 before discovery.
Definition soem_fieldbus_driver.cc:736
std::expected< std::vector< uint8_t >, std::string > readSdo(uint16_t slavePosition, uint16_t index, uint8_t subindex) override
Reads an object dictionary entry via CoE SDO upload.
Definition soem_fieldbus_driver.cc:980
uint16_t mailboxProtocols(uint16_t position) const override
Returns the slave's advertised mailbox-protocol bits without any bus I/O.
Definition soem_fieldbus_driver.cc:770
SoemFieldbusDriver & operator=(const SoemFieldbusDriver &)=delete
std::vector< SlaveConfig > busConfig() const override
Returns the static ESC configuration of every slave, as last programmed by the master.
Definition soem_fieldbus_driver.cc:609
PdoLayout processDataLayout() override
Returns the current process-data layout established by configureProcessData.
Definition soem_fieldbus_driver.cc:571
std::expected< void, std::string > configureProcessData() override
Maps the process data and lays out the IOmap (one-time, control-plane).
Definition soem_fieldbus_driver.cc:397
std::expected< std::vector< uint8_t >, std::string > readSii(uint16_t slavePosition) override
Reads the raw Slave Information Interface (SII / EEPROM) image of a slave.
Definition soem_fieldbus_driver.cc:1503
uint8_t subindex
Definition esi_entry.cc:283
Definition soem_fieldbus_driver.cc:35
EtherCatState
EtherCAT Application Layer state values.
Definition fieldbus_driver.h:45
constexpr std::size_t kMaxProcessImageBytes
Maximum size in bytes of the combined process-data image (all outputs + all inputs).
Definition fieldbus_driver.h:30
std::chrono::milliseconds timeout
Definition somanet_procedures.cc:464
A structured FoE failure. String-like where a caller only forwards it (operator<<,...
Definition foe_error.h:110
Layout of the process-data images, produced by configureProcessData.
Definition fieldbus_driver.h:241
Immutable identity fields read from a slave's EEPROM during configuration.
Definition fieldbus_driver.h:159
Construction-time configuration for SoemFieldbusDriver.
Definition soem_fieldbus_driver.h:25
std::string ifname
Resolved OS network interface name (e.g. "eth0", "enp3s0").
Definition soem_fieldbus_driver.h:27
bool mailboxStatusFmmu
Definition soem_fieldbus_driver.h:34