First library, its tested and working
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user