first commit
This commit is contained in:
+54
@@ -0,0 +1,54 @@
|
||||
# Bridge contract
|
||||
|
||||
Return: 0 = accepted, 1..10 = am_error values in atom_mb.h.
|
||||
256 = invalid/stale handle, 257 = pool full, 258 = insufficient/null buffer,
|
||||
259 = unknown command. Always inspect return codes. A rejected call is not a
|
||||
completed Modbus request.
|
||||
|
||||
Commands: 1 Open, 2 Close, 3 Enable, 4 Disable, 5 Tick, 6 Submit,
|
||||
7 CopyRead, 8 Reconnect, 9 Configure, 10 Acknowledge,
|
||||
11 Set request timeout (responseTimeoutMs only; permitted while not busy).
|
||||
Configure only while disabled; all three timeouts must be nonzero.
|
||||
Open receives an IPv4 DWORD in human octet order: 16#C0A80132 = 192.168.1.50.
|
||||
Open returns its handle in status[0], NOT in the function return value.
|
||||
Close returns status[0]=0; old handles fail even when their slot is reused.
|
||||
Capacity values count WORD/UDINT elements, not bytes. Pass separate buffers.
|
||||
CopyRead copies `quantity` WORDs; coils/discretes are unpacked WORD 0/1.
|
||||
|
||||
| Status index | Meaning |
|
||||
|---|---|
|
||||
| 0 | Handle |
|
||||
| 1 | State: 0 Disabled, 1 Retry, 2 Connecting, 3 Ready, 4 Sending, 5 Receiving |
|
||||
| 2 | Busy |
|
||||
| 3 | Done |
|
||||
| 4 | Error |
|
||||
| 5 | Latest transaction result |
|
||||
| 6 | Last failure, retained after success |
|
||||
| 7 | OS socket error |
|
||||
| 8 | Modbus exception |
|
||||
| 9 | Write outcome uncertain |
|
||||
| 10 | Connection attempts |
|
||||
| 11 | Attempts after first attempt |
|
||||
| 12 | Completed successful requests |
|
||||
| 13 | Failed requests |
|
||||
| 14 | Has successful transaction |
|
||||
| 15 | Last success timestamp, low 32 bits |
|
||||
| 16 | Last success timestamp, high 32 bits |
|
||||
| 17 | Quantity of latest request |
|
||||
| 18 | Function code |
|
||||
| 19 | Unit ID |
|
||||
| 20 | Enabled |
|
||||
| 21 | Connect timeout milliseconds |
|
||||
| 22 | Whole-request timeout milliseconds |
|
||||
| 23 | Retry delay milliseconds |
|
||||
|
||||
The PLC wrapper consumes Done/Error then Acknowledge before submitting a new
|
||||
request. For Done reads, call CopyRead BEFORE Acknowledge. Completed read data
|
||||
is retained internally but CopyRead requires Done. For writes, do not replay
|
||||
an uncertain result without an application decision.
|
||||
|
||||
All calls to the entire bridge pool must originate from ONE IEC task. Contexts
|
||||
and the pool are not thread-safe. Handles must not be RETAIN/PERSISTENT. Closing
|
||||
on program disposal and invalidating on application reset/download remain PLC
|
||||
wrapper responsibilities. Component unload cleanup alone does not cover an IEC
|
||||
application stop or download.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Linux builds
|
||||
|
||||
A binary must match CPU architecture, libc and the CODESYS component interface.
|
||||
One .so cannot cover every Linux version. Build on the oldest supported target
|
||||
OS within each architecture, or use its sysroot in a matching cross toolchain.
|
||||
|
||||
Native Pi build, from Library:
|
||||
|
||||
```sh
|
||||
sudo apt-get install build-essential make m4 sed dos2unix python3
|
||||
./tools/build-linux.sh linux-aarch64
|
||||
```
|
||||
|
||||
Native x86-64 Linux build: `./tools/build-linux.sh linux-x86_64`.
|
||||
32-bit ARM requires a matching ARM hard-float compiler/OS; do not use the ARM64
|
||||
binary. The target argument labels output; it does not choose a compiler.
|
||||
|
||||
Cross-build example, provided a matching compiler and libc sysroot are installed:
|
||||
|
||||
```sh
|
||||
CC=aarch64-linux-gnu-gcc ./tools/build-linux.sh linux-aarch64
|
||||
```
|
||||
|
||||
For a custom compiler/sysroot use a compiler wrapper as CC. Cross builds have
|
||||
not been validated in this bundle. The supplied SDK's makefile controls linking;
|
||||
check its options before adding toolchain flags. CC must be one executable path.
|
||||
Build targets sequentially because component/out is shared and cleaned each run.
|
||||
|
||||
The build script accepts an SDKDIR environment override. Preserve the supplied
|
||||
SDK unchanged and use separate folders for replacement SDK versions. Record
|
||||
and test compatibility before changing the generated external function ABI.
|
||||
For ABI changes, regenerate C/M4 from the external CODESYS library and review
|
||||
tools/prepare_component.py; do not overwrite component implementations blindly.
|
||||
|
||||
Build metadata includes compiler, host, SDK file hashes and output architecture.
|
||||
Host OS/glibc describes the build host, not necessarily a cross-compiler sysroot.
|
||||
Add the actual sysroot and tested target runtime to build-info.txt before release.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Embed the shared object in the IEC library
|
||||
|
||||
1. Copy the built libCmpAtomModbus.so to the development PC.
|
||||
2. Open the CmpAtomModbus library containing atMbCall_cext.
|
||||
3. In POUs add a C Implemented Library object (C Code Integration functionality).
|
||||
4. Add an Object file for devices: choose the .so and the exact Raspberry Pi
|
||||
64 SL device/version. If a component name is requested, use CmpAtomModbus.
|
||||
5. Save/install the library and update the application's library reference.
|
||||
6. Perform a full download and verify loading and function resolution.
|
||||
|
||||
Add separate object files for other device/architecture targets. CODESYS chooses
|
||||
the matching device entry; do not assign ARM64 binaries to 32-bit devices.
|
||||
For automatic deployment testing, remove only the old manually added
|
||||
CmpAtomModbus ComponentManager entry and restart the runtime before download.
|
||||
Do this while the PLC application is stopped for maintenance.
|
||||
|
||||
Official instructions:
|
||||
https://content.helpme-codesys.com/en/CODESYS%20Control/_rtsl_extension_extension_sdk.html
|
||||
https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_obj_c_implemented_library.html
|
||||
@@ -0,0 +1,14 @@
|
||||
# Validation
|
||||
|
||||
Run `make test` on Linux with a C compiler and Python 3. Tests use a local
|
||||
socket server and cover normal/fragmented replies, close/reconnect, timeout,
|
||||
bad transaction IDs, bad MBAP length, Modbus exceptions, uncertain writes and
|
||||
coils. They run through the direct engine and bridge. Pool/handle tests are
|
||||
included. These tests do not compile or execute Structured Text.
|
||||
|
||||
In CODESYS compile both libraries and start a read-only bench application.
|
||||
Verify first scan with zero registered requests, then registered requests,
|
||||
reply timeouts, priorities, data freshness, disconnect/reconnect and disposal.
|
||||
Test full download/reset and online-change lifecycle separately. Only then test
|
||||
writes with appropriate device registers. Validate embedded deployment on a
|
||||
target without the manually configured component.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Troubleshooting
|
||||
|
||||
On the user's Pi the active runtime log is /var/log/codesyscontrol.log.
|
||||
/var/opt/codesys/codesyscontrol.log contained old logs. Check timestamps.
|
||||
|
||||
```sh
|
||||
sudo /etc/init.d/codesyscontrol status
|
||||
sudo tail -n 100 /var/log/codesyscontrol.log
|
||||
file component/out/libCmpAtomModbus.so
|
||||
nm -D component/out/libCmpAtomModbus.so
|
||||
```
|
||||
|
||||
Look for CmpAtomModbus, undefined symbol, signature mismatch or load errors.
|
||||
ComponentEntry and atmbcall_cext must be exported. The observed manual load was
|
||||
component ID 0xffff2001, version 0.2.0.0. Ensure custom component IDs do not collide.
|
||||
|
||||
External function signature: 0x709EE65B, API version: 0x00020000.
|
||||
A valid component load does not prove the request scheduler or device I/O works.
|
||||
|
||||
AccessViolation in processAllRequests: use the current export with zero-count,
|
||||
bounds and null checks and do a full download. Nonzero stale pointers still need
|
||||
lifecycle investigation. Keep requests and their data arrays alive for the client
|
||||
lifetime, and do not change a registered request's client while running.
|
||||
|
||||
Use one IEC task for all native clients. Handles must not be retained/persistent.
|
||||
For STOP/download, disable the client and let a scan run, or call release().
|
||||
See compat/README.md for lifecycle limitations and uncertain-write handling.
|
||||
Reference in New Issue
Block a user