Skip to content

I/O Binding

Address Examples: %IX0.0, %QX0.0, %IW0, %QW0

Use %IX0.0 when you need a concrete boolean input example, %QX0.0 for a boolean output example, %IW0 for a word input example, and %QW0 for a word output example.

Symbolic variables bind to physical I/O channels through direct addresses, VAR_CONFIG, or io.toml.

At this point the problem is signal identity, not transport selection.

Keep one binding path authoritative for each signal so diagnostics and operator views describe the same process image.

Guide

This guide explains how to map hardware I/O to Structured Text variables using the Web UI or io.toml and IEC addresses (%IX, %QX, %MX).

Tip: The Web UI supports driver selection, GPIO pin mapping, Modbus/TCP settings, and safe‑state outputs under I/O → I/O configuration (no manual file editing needed).

1) Addressing Basics

Use IEC-style addresses in ST:

VAR_GLOBAL
  InSignal AT %IX0.0 : BOOL;
  OutSignal AT %QX0.0 : BOOL;
END_VAR

  • %I = input, %Q = output, %M = memory
  • X = bit address (use for GPIO and discrete I/O)

Marker (%M) address variants:

  • %MX<byte>.<bit> (bit, BOOL), example: %MX0.7
  • %MB<byte> (byte), example: %MB12
  • %MW<byte> (word), example: %MW50
  • %MD<byte> (double word), example: %MD200
  • %ML<byte> (long word), example: %ML8
  • %M* (wildcard, resolved by VAR_CONFIG)

Runtime cycle semantics for %M bindings:

  • Cycle start: %M process image is read into bound variables.
  • Cycle end: bound variable values are written back to %M process image.

2) io.toml Structure (v1)

Single-driver form (legacy + still supported):

[io]
driver = "simulated"
params = {}

Multi-driver form (composed drivers, executed in order):

[io]
drivers = [
  { name = "modbus-tcp", params = { address = "192.168.0.10:502", unit_id = 1, input_start = 0, output_start = 0, timeout_ms = 500, on_error = "fault" } },
  { name = "mqtt", params = { broker = "192.168.0.20:1883", topic_in = "line/in", topic_out = "line/out", reconnect_ms = 500, keep_alive_s = 5, allow_insecure_remote = true } }
]

Rule:

  • Use either io.driver + io.params or io.drivers (do not mix both in one file).

Optional safe state outputs:

[[io.safe_state]]
address = "%QX0.0"
value = "FALSE"

If io.toml is missing, the runtime uses system IO config:

  • Linux/macOS: /etc/trust/io.toml
  • Windows: C:\\ProgramData\\truST\\io.toml

3) GPIO Example (Raspberry Pi)

[io]
driver = "gpio"

[io.params]
backend = "sysfs"
inputs = [
  { address = "%IX0.0", line = 17, debounce_ms = 5 }
]
outputs = [
  { address = "%QX0.0", line = 27, initial = false }
]

[[io.safe_state]]
address = "%QX0.0"
value = "FALSE"

4) Loopback (Local Testing)

[io]
driver = "loopback"
params = {}

This copies outputs to inputs for local testing without hardware.

5) Modbus/TCP Example

[io]
driver = "modbus-tcp"

[io.params]
address = "192.168.0.10:502"
unit_id = 1
input_start = 0
output_start = 0
timeout_ms = 500
on_error = "fault"

6) MQTT Example

[io]
driver = "mqtt"

[io.params]
broker = "192.168.0.20:1883"
topic_in = "line/in"
topic_out = "line/out"
reconnect_ms = 500
keep_alive_s = 5
allow_insecure_remote = true

7) Transport Gating Notes (Critical)

EtherCAT hardware transport (non-mock adapter):

  • requires build feature ethercat-wire
  • supported on unix targets only in this build
  • adapter = "mock" remains valid for deterministic local/CI validation

OPC UA wire server:

  • requires build feature opcua-wire
  • if [runtime.opcua].enabled = true without opcua-wire, runtime startup fails with a feature-disabled error
  • when enabled, configure either:
  • allow_anonymous = true (local commissioning only), or
  • allow_anonymous = false plus both username and password

Communication examples with step-by-step commissioning flow:

  • examples/communication/modbus_tcp/README.md
  • examples/communication/mqtt/README.md
  • examples/communication/opcua/README.md
  • examples/communication/ethercat/README.md
  • examples/communication/ethercat_field_validated_es/README.md
  • examples/communication/gpio/README.md
  • examples/communication/multi_driver/README.md

8) Validate + Inspect

EtherCAT backend details (module chain profile, diagnostics, and hardware setup): docs/guides/ETHERCAT_BACKEND_V1.md.

Validate a project folder:

trust-runtime validate --project <project-folder>

Read current I/O snapshot:

trust-runtime ctl --project <project-folder> io-read

Write output (for testing):

trust-runtime ctl --project <project-folder> io-write %QX0.0 TRUE