first commit

This commit is contained in:
2026-09-30 21:17:41 -06:00
commit 07244fc761
57 changed files with 30094 additions and 0 deletions
+137
View File
@@ -0,0 +1,137 @@
# Existing atMb interface backed by the C TCP engine
Import AtomModbus-Compatible.export into a BACKUP COPY of your existing
atomLibrary, accepting replacement of the matching ModbusMaster objects.
This preserves the other Atom helpers referenced by the original code.
Do not import it into your small CmpAtomModbus external-function library.
In the copied atomLibrary's Library Manager add your CmpAtomModbus 0.2.0.0
library. Ensure its namespace/alias is exactly `CmpAtomModbus`, as the wrapper
calls `CmpAtomModbus.atMbCall_cext`. Keep existing dependencies including
ModbusFB, SysTime, the standard timer library and your other Atom helpers.
ModbusFB remains for legacy enum types and RTU; TCP no longer creates or calls
its client/request objects.
The native export preserves all 78 original object IDs and adds 10 methods.
Review source is in All_Source_Review.st. Original_HomeCodesys.export is the
unchanged supplied original. The export's XML/schema structure and public
declaration preservation have been checked, but the revised IEC code has NOT
been compiled in CODESYS here. Compile the copied atomLibrary and test before
replacing the installed production version.
## Same application calls
Your export's exact request names include `Req`:
```iecst
VAR
mbClient : atMbClientTCP;
mbRead : atMbReqReadHolding;
mbWrite : atMbReqWriteHolding;
holding : ARRAY[0..9] OF UINT;
setpoints : ARRAY[0..1] OF UINT;
END_VAR
```
```iecst
mbClient(
in_ipAddress := To_IPAddress(192,168,1,50),
in_port := 502,
in_timeout := T#1S
);
mbRead(
client := mbClient,
in_unitId := 1,
in_startAddr := 0,
in_quantity := 10,
in_dataOffset := 0,
in_minDelay := T#200MS,
data := holding
);
mbWrite(
client := mbClient,
in_unitId := 1,
in_startAddr := 100,
in_quantity := 2,
in_dataOffset := 0,
in_minDelay := T#1S,
data := setpoints
);
// mbWrite.writeNow(); // Existing method boosts priority, respecting min delay.
```
Only use mapped register ranges for your device; the write example is an API
example, not part of the read-only bench test. Existing names, input defaults,
BOOL/UINT open arrays, client reference, stats properties and writeNow are kept.
Use your existing library namespace prefix if required by Library Manager.
`in_dataOffset` remains an ACTUAL ARRAY INDEX as in the old implementation,
not a relative offset from LOWER_BOUND. Native capacity clipping now considers
that starting index. Bad indices set out_parameterError and disable scheduling
until corrected. Quantity zero disables a request. Protocol-excessive quantities
are rejected with a request parameter error. Don't change the client reference
of a registered request while running; request registrations are persistent.
## Added diagnostics/options (old call sites need no new arguments)
Client: out_connected, out_connectionState, out_lastNativeError,
out_socketError, out_reconnectCount, out_registrationFull.
State: 0 disabled, 1 retry, 2 connecting, 3 ready, 4 sending, 5 receiving.
Request: out_nativeError, out_socketError, out_writeUncertain, out_validData,
out_dataAgeMs, out_stale, out_parameterError. Existing stats remain available.
Extra TCP inputs: in_enable (TRUE), in_connectTimeout (2s),
in_reconnectDelay (1s), in_holdUncertainWrites (FALSE).
Extra request input: in_staleAfter (2s).
Priorities/minimum polling delays and cyclic writes are preserved. The C engine
never automatically replays a failed packet, but the IEC scheduler submits a
fresh snapshot on the next eligible write cycle, as the original code does.
For command writes where that is inappropriate, set in_holdUncertainWrites=TRUE:
an uncertain write holds that request until its existing writeNow() is called.
A valid Modbus exception counts as responsive communication, but does not
refresh read-data freshness. A client endpoint change closes the old context,
cancels its transaction and invalidates its old read data.
The client processes its registered requests, as before. Request FB calls bind
their arrays/register the requests; they must still run every scan. After an
online change registrations are rebuilt by those calls. The native base's
FB_reinit resets in-flight state and TCP FB_exit closes the C context when
disposed. These lifecycle paths require target testing. An application STOP
alone does not guarantee FB_exit; set in_enable=FALSE and run one scan (or call
release()) before STOP/download. Re-enable afterwards.
All native clients/requests must be owned by ONE IEC task because the C pool
is not thread-safe. Up to 16 native clients and 100 registered requests/client.
Do not retain/persist client handles. Arrays/instances must live for the client
lifetime. No IEC data pointer is held in the C engine between calls.
## Rebuild the Pi component once
This wrapper uses new command 11 for per-request timeouts. Rebuild the included
component; do not use the previous .so. No external function declaration,
checksum or library interface regeneration is needed. Version stays 0.2.0.0.
```sh
cd ~/modbus-build/atom-modbus
make -C component SDKDIR="$(realpath sdk/ExtensionSDK)" clean
make -C component SDKDIR="$(realpath sdk/ExtensionSDK)" all
sudo /etc/init.d/codesyscontrol stop
sudo cp component/out/libCmpAtomModbus.so /usr/lib/
sudo /etc/init.d/codesyscontrol start
```
The stop/start requires the same safe bench maintenance conditions as before.
The existing ComponentManager entry stays valid. Add the copied/compiled Atom
library to a test application, use only the read block initially and verify
disconnect/reconnect, per-request timeouts, priorities and lifecycle handling.
## Validation
Public input/output/in-out declarations from the original export are retained.
The C engine and bridge regression tests cover TCP recovery, framing and
exceptions. The new per-request timeout command is exercised by the TCP bridge
driver. This does not substitute for CODESYS compile, target scheduler tests or
production commissioning.