204 lines
10 KiB
Markdown
204 lines
10 KiB
Markdown
# atMb native TCP + RTU + TCP slave — development revision 0.9
|
|
|
|
The IEC export and C implementation have no ModbusFB dependency. All socket/
|
|
serial/frame processing runs in the native component. Public namespace: atMb.
|
|
Standard and SysTime are still required for IEC timers and time measurement.
|
|
|
|
This is a tested host development build, not a compiled CODESYS library or a
|
|
hardware-qualified Pi release. Full CODESYS compilation and physical RTU testing
|
|
remain required. Online-change ownership/pointer relocation is future work.
|
|
|
|
## Rebuild on the Pi (required)
|
|
|
|
Extract this bundle on the Pi, preserving component-source and ExtensionSDK
|
|
as siblings. Install build-essential, m4, dos2unix, make and python3 if absent.
|
|
|
|
```sh
|
|
cd component-source
|
|
make -C component SDKDIR="$(realpath ../ExtensionSDK)" clean
|
|
make -C component SDKDIR="$(realpath ../ExtensionSDK)" all
|
|
file component/out/libCmpAtomModbus.so
|
|
make test
|
|
```
|
|
|
|
The component registration version is now 0.3.0.0. The external atMbCall_cext
|
|
function ABI, signature 0x709EE65B and generated API version 0.2.0.0 are unchanged.
|
|
No regeneration of runtime interface files is required for these extra commands.
|
|
Keep the supplied generated interface; do not regenerate blindly from a changed
|
|
library title/version. No prebuilt Pi binary is included. A strict host compile
|
|
of the component function used the supplied SDK headers and original real
|
|
parameter struct; the full SDK/M4/component frame build must run on your Pi.
|
|
|
|
## Build the IEC library without legacy objects
|
|
|
|
1. Create a fresh library project saved as CmpAtomModbus.library (or a backup copy
|
|
with the old Modbus master/slave folders removed). Import atMb-Native.export.
|
|
A fresh project is preferred because import does not delete omitted old methods.
|
|
2. Keep Project Information title CmpAtomModbus and default namespace atMb, as
|
|
supplied in the export. This is one combined library, not a wrapper referencing
|
|
a second CmpAtomModbus/atMb library. Remove those self/wrapper references.
|
|
3. Add only Standard and SysTime references needed by this IEC code. Remove the
|
|
ModbusFB reference. Resolve their ordinary dependencies if the IDE requests it.
|
|
4. Add a C Implemented Library object and embed your NEWLY BUILT ARM64
|
|
component/out/libCmpAtomModbus.so for the exact Raspberry Pi 64 SL target.
|
|
Use CmpAtomModbus for the component name. The old TCP-only embedded object was
|
|
deliberately omitted from this export; do not reuse its binary.
|
|
5. Compile, save/install and update references in the Atom library/application.
|
|
6. Perform a full download. Verify runtime loads the new component version.
|
|
|
|
For automatic deployment, stop using the old manually preloaded component
|
|
before testing the embedded one: remove only its ComponentManager entry, then
|
|
restart the runtime during maintenance. Alternatively, for a manual bench test,
|
|
stop the runtime and replace /usr/lib/libCmpAtomModbus.so with the new binary.
|
|
Inspect /var/log/codesyscontrol.log. No production install is performed by this kit.
|
|
|
|
## TCP client
|
|
|
|
Existing atMb.Client and ReqReadHolding/ReqReadInput/ReqReadCoil/ReqReadDiscrete/
|
|
ReqWriteHolding/ReqWriteCoil calls remain. Supported C function codes are
|
|
1,2,3,4,5,6,15,16. Automatic retry continues while enabled; normal Modbus
|
|
exception replies do not force reconnects. The default retry delay is 100 ms.
|
|
|
|
## Native RTU
|
|
|
|
```iecst
|
|
VAR
|
|
bus : atMb.ClientRTU;
|
|
read : atMb.ReqReadHolding;
|
|
registers : ARRAY[0..9] OF UINT;
|
|
END_VAR
|
|
```
|
|
|
|
```iecst
|
|
bus(
|
|
in_device := '/dev/ttyUSB0',
|
|
in_baudRate := 9600,
|
|
in_parity := 0,
|
|
in_dataBits := 8,
|
|
in_stopBits := 1,
|
|
in_timeout := T#500MS,
|
|
in_reconnectDelay := T#100MS
|
|
);
|
|
read(client := bus, in_unitId := 1, in_startAddr := 0,
|
|
in_quantity := 10, in_dataOffset := 0, in_minDelay := T#100MS,
|
|
data := registers);
|
|
```
|
|
|
|
Call client/requests every scan in ONE task. One RTU client owns each serial bus;
|
|
register different unit IDs on that same client, rather than opening multiple
|
|
clients on the same tty. The native open uses exclusive serial access.
|
|
|
|
Use /dev/serial/by-id/... when it fits the 127-byte path limit, or a stable
|
|
short udev symlink. The runtime OS user must have access to the device; check the
|
|
actual service user and device group on your Pi. Stop other serial consumers.
|
|
The old numeric in_port selection was removed; a numeric index is not a portable
|
|
Linux device mapping. in_baudRate is now UDINT so 115200 fits.
|
|
|
|
Supported baud rates: 1200,2400,4800,9600,19200,38400,57600,115200.
|
|
RTU uses 8 data bits; parity 0 none/1 odd/2 even; stop bits 1 or 2.
|
|
Unit IDs 1..247 are accepted. Broadcast unit 0 is explicitly rejected because
|
|
broadcast completion cannot be reported as an acknowledged write.
|
|
|
|
For automatic-direction USB RS485 adapters leave in_rs485 FALSE. TRUE requests
|
|
Linux TIOCSRS485 with RTS during transmit; unsupported drivers report an OS error.
|
|
No software GPIO direction control or adapter-specific configuration is included.
|
|
|
|
CRC, unit/function, length and write echo are validated before accepting replies.
|
|
Faults close/reopen the tty after the configured retry delay. No raw write packet
|
|
is replayed by the engine. The existing scheduler can issue fresh cyclic writes;
|
|
use in_holdUncertainWrites TRUE for commands requiring an application decision.
|
|
Delayed serial replies have no transaction ID: use suitable timeout/retry settings
|
|
for slow devices. Serial silence is conservatively scheduled in milliseconds;
|
|
physical adapter/baud/parity/line-turnaround tests are still necessary. PTY tests
|
|
cannot certify electrical timing, parity generation or RS485 direction behavior.
|
|
|
|
out_connected on RTU means the tty is open/ready, not proof that a remote unit
|
|
responds. Use per-request online/stale/error status. out_socketError carries the
|
|
OS errno for tty failures too. All existing client status counters are shared.
|
|
|
|
## Native TCP slave
|
|
|
|
atMb.ModbusSlave and atMb.SlaveTCP both run the C server (no ModbusFB server).
|
|
Map four BOOL/UINT arrays using aDiscreteInputsMemory/aCoilsMemory/
|
|
aInputRegistersMemory/aHoldingRegistersMemory. Their actual LOWER_BOUND is their
|
|
zero-based protocol starting address; each table is limited to 2000 items and
|
|
must fit within addresses 0..65535. A full 65536-item table is not supported.
|
|
|
|
Use in_ipAddress DWORD = 0 to bind all addresses, or numeric IPv4 in human octet
|
|
order (16#7F000001 for 127.0.0.1). port defaults to 502. The legacy interfaceName
|
|
field is retained but must be empty; numeric bind IP replaces interface-name
|
|
binding. Nonempty names are reported as parameter errors rather than ignored.
|
|
|
|
Example: `slave : atMb.ModbusSlave;` with all four arrays passed every scan:
|
|
|
|
```iecst
|
|
slave(in_enable := TRUE, in_ipAddress := DWORD#0, port := 502,
|
|
aDiscreteInputsMemory := discreteInputs,
|
|
aCoilsMemory := coils,
|
|
aInputRegistersMemory := inputRegisters,
|
|
aHoldingRegistersMemory := holdingRegisters);
|
|
```
|
|
|
|
FC1/2/3/4/5/6/15/16 are implemented, with exception replies for unsupported
|
|
functions, invalid quantities or unmapped addresses. Four server contexts,
|
|
eight simultaneous peers per server. Requests are bounded and processed in
|
|
order per connection. A server tick accepts at most one peer and performs at
|
|
most one nonblocking I/O action per peer per IEC call. Incomplete frames/send
|
|
stall timeout after 5 seconds; idle peers close after 60 seconds.
|
|
|
|
The wrapper pushes PLC table snapshots, ticks the engine, then pulls completed
|
|
remote writes in the same scan. C retains no PLC pointers between calls. Application
|
|
writes between calls become the next snapshot. Arrange application order accordingly.
|
|
The fixed server limits and scan-bounded throughput differ from the old ModbusFB
|
|
server; load test your actual client count/polling rates. No RTU slave is provided.
|
|
|
|
in_enable controls listening, in_reset recreates the context, endpoint changes
|
|
recreate it, and listener failures retry automatically after in_reconnectDelay.
|
|
Outputs: out_running/out_error/out_errorId/out_parameterError/out_socketError,
|
|
out_connectedClients/out_requestsReceived/out_repliesSent/out_exceptionReplies.
|
|
|
|
## Native lifecycle and API
|
|
|
|
All bridge/server contexts are fixed-pool, generation-checked and single-task.
|
|
No RETAIN/PERSISTENT handles. release() disables client enable and closes its
|
|
context. STOP alone does not guarantee FB_exit: disable and scan before STOP.
|
|
New full download required; online-change safety is not claimed in this revision.
|
|
|
|
Own Error and ExceptionCodes DUTs replace the ModbusFB enums. Error retains the
|
|
named compatibility labels used by request statistics. Legacy dynamically
|
|
allocated request methods are removed or become native recreateRequest BOOL.
|
|
Old allocation-alarm outputs/legacy request reset fields were removed because
|
|
these contexts use fixed native pools. A pool-full result is native error 257.
|
|
|
|
Command 20: open RTU. data contains one device-path ASCII byte per WORD, quantity
|
|
is path length; ipAddress=baud; unitId=parity; functionCode=bits;
|
|
startAddress=stop bits; connectTimeoutMs=kernel RS485 flag (0/1).
|
|
The existing commands 2..11 configure/tick/submit/close this client normally.
|
|
Commands 30..36: server open/close/enable/disable/tick/push/pull. Push/pull use
|
|
functionCode as table 0 coils/1 discrete/2 holding/3 input, startAddress as base
|
|
and quantity as length. Server handles use distinct low-byte tags from clients.
|
|
Server status indices: 0 handle,1 running,2 error,3 result,4 OS errno,5 peers,
|
|
6 requests,7 replies,8 exception replies. Client status layout is unchanged.
|
|
|
|
## Tests and remaining checks
|
|
|
|
Run make test on Linux. Includes existing nine TCP scenarios directly and through
|
|
the bridge, pool/handle tests, PTY RTU read/fragment/CRC/timeout/recovery/exception/
|
|
register-write/coil-write/invalid-write-echo recovery tests and native slave FC1/2/3/4/5/6/15/16, nonzero mapping,
|
|
exception/listener-recovery/stale-handle tests. All passed on the development host.
|
|
The CODESYS XML has no ModbusFB identifiers and passes structural checks. It has
|
|
not been compiled in the IDE; hardware Pi/serial and embedded deployment tests
|
|
remain. Do not interpret host tests as target or online-change qualification.
|
|
|
|
|
|
v0.9.1 export correction
|
|
------------------------
|
|
Restores ClientBase public diagnostics: msgLastSecondCnt, msgLastSecondTime,
|
|
numMsgSent, numMsgReply, allRequestsOnline and reqStats. The generator now
|
|
checks these declarations and balanced VAR sections. Replace matching objects
|
|
when importing the corrected export. C sources are unchanged from v0.9; this
|
|
correction alone does not require rebuilding an already installed v0.9 component.
|
|
The full native migration still requires the C build and embedding described above.
|
|
Validated XML and declaration checks locally; CODESYS compilation must be checked
|
|
in the IDE.
|