The lcec_mdp_coupler driver supports modular EtherCAT bus couplers
that follow the ETG.5001 Modular Device Profile (MDP): one EtherCAT
slave hosting up to 32 pluggable I/O modules on a backplane. The
couplers differ only in data (slot geometry, module idents, each
module’s PDO layout), and all of it comes from the vendor’s ESI file,
so the driver works from tables generated by
scripts/esi2coupler.py instead of
hand-written per-brand code.
| Type | Coupler | VID:PID | Slots |
|---|---|---|---|
UC20 |
UTRIO UC20-RTU-EC-A | 0x00000fc4:0x0100000a | 32 |
GL20 |
Inovance GL20(GL20S)-RTU-ECT32 | 0x00100000:0x10f41001 | 32 |
Each populated slot is described with a
<subModule> tag inside the
<slave>. id is the backplane slot, counting from 0 next to the
coupler; ident is the module’s ident from the vendor ESI; name is
used in the module’s pin names (default: the slot id).
<slave idx="7" type="GL20" name="io">
<subModule id="0" ident="0x10F41024" name="do1"/>
<subModule id="1" ident="0x10F41024" name="do2"/>
<subModule id="2" ident="0x10F41010" name="di3"/>
<subModule id="3" ident="0x10F41010" name="di4"/>
</slave>
<slave idx="4" type="UC20" name="io">
<subModule id="0" ident="12" name="do1"/>
<subModule id="2" ident="1" name="di3"/>
</slave>
The type name is case-sensitive, like every other driver’s.
Slots may be sparse (the UC20 example leaves slot 1 empty). At startup
the driver checks that every slot id is below the coupler’s slot count,
and that slot ids and names are unique; any violation is a
configuration error. The parser rejects an ident the coupler’s module
table does not contain.
Module parameters are not supported yet. A <modParam> inside a
<subModule> is rejected at parse time; modules run with their power-on
defaults (input filters, safe-state outputs, analog ranges). If a
module needs a non-default setting, use an <sdoConfig> on the slave
for its configuration object (it is re-applied on runtime
re-initialization, see below).
Pin names are lcec.<master>.<slave>.<submodule-name>-<kind>-<n>,
numbered per module from 0:
...-din-<n> and ...-din-<n>-not (bit, out)...-dout-<n> (bit, in), with the invert param...-ain-<n>-raw, -val, -scale, -bias...-aout-<n>-value, -scale, -offset, -enable, …Mixed I/O modules export both their digital inputs and outputs.
Temperature, counter, serial and fieldbus modules (OTHER and ENC in
the generated tables) are mapped into the process image so the byte
offsets of the following slots are correct, but they get no pins yet.
The generated tables are the source of truth:
lcec_mdp_uc20.h (28 modules) and
lcec_mdp_gl20.h (43 modules).
Each entry lists the ident, the ESI module name and the pin kind.
Common ones:
| Coupler | ident | module | kind |
|---|---|---|---|
| UC20 | 0x00000001 | UC20-8DI-NP | digital in, 8 |
| UC20 | 0x00000002 | UC20-16DI-NP | digital in, 16 |
| UC20 | 0x0000000c | UC20-8DO-P | digital out, 8 |
| UC20 | 0x00000004 | UC20-16DO-P | digital out, 16 |
| UC20 | 0x00000006 | UC20-4AI-U | analog in, 4 |
| UC20 | 0x00000009 | UC20-4AO-U | analog out, 4 |
| GL20 | 0x10f41010 | GL20(GL20S)-1600END | digital in, 16 |
| GL20 | 0x10f41011 | GL20(GL20S)-3200END | digital in, 32 |
| GL20 | 0x10f41024 | GL20(GL20S)-0016ETP | digital out, 16 |
| GL20 | 0x10f41060 | GL20(GL20S)-0808ETN | mixed I/O, 8+8 |
| GL20 | 0x10f41030 | GL20(GL20S)-4AD | analog in, 4 |
| GL20 | 0x10f41040 | GL20(GL20S)-4DA | analog out, 4 |
0xF030, for couplers whose ESI
sets DownloadModuleIdentList (both the UC20 and the GL20). Gap
subindices are cleared. The UC20 marks the count 0xF030:00
read-only; that rejection is logged as a warning.The module list is kept in the coupler’s RAM only. The driver
provides a proc_reinit hook, so when the coupler loses power or its
cable while LinuxCNC runs and then comes back, the module list (and,
for couplers that need it, the PDO assignment) is written again before
the coupler returns to OP. Watch slave-reconfig,
slave-reconfig-count and slave-reconfig-error. This needs the
linuxcnc-ethercat EtherCAT master; see
runtime-reinit.md.
scripts/esi/ and generate its table:
./scripts/esi2coupler.py --esi scripts/esi/<file>.xml --family <id> > src/devices/lcec_mdp_<id>.h.
The <slave type> name is <id> in uppercase.registrations[] in
lcec_mdp_coupler.c.scripts/check-generated-headers.sh,
which CI runs to keep the committed header in sync with the
generator.LCEC_MDP_QUIRK_EXPLICIT_SM_ASSIGN writes 0x1C12/0x1C13 by SDO
for couplers that ignore the master’s assignment;
LCEC_MDP_QUIRK_NO_PDO_ASSIGN gives the master no PDO layout at all,
for couplers that reject PDO assignment.