800B PDO variant + long-term stability evidence + analysis docs
- twin_layout_blob_sized generalized: multi-entry TwinCAT line format (1 real @240bit + N continuation + remainder entry); 1024B path kept byte-identical; 800B = 27 entries verified on hardware - 800B constants (PAYLOAD/SM 800), deployed as el6695_rt_800b - 10-min + 5h stability runs: 18M cycles, zero errors, zero mismatches, PLC nMismatch frozen over the whole run (monitor_5h.csv evidence) - docs: 800B plan/design/verification/test-report chapters, jitter analysis (NFS rootfs stall primary cause), D2000 dev plan - scripts: 800B deploy/relink/verify, mismatch-delta, 5h monitor
This commit is contained in:
parent
8c1f519526
commit
f0163d8d70
124
docs/800b-pdo-plan.md
Normal file
124
docs/800b-pdo-plan.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# EL6695 PDO 扩展至 800 字节 — 方案文档
|
||||
|
||||
> **版本**: 1.0
|
||||
> **日期**: 2026-07-27
|
||||
> **状态**: 待评审
|
||||
> **前置文档**: `8b-bridge-design.md`(8B 实现)、`500us-latency-plan.md`(延迟优化)
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标
|
||||
|
||||
在现有 8B 工程基础上,新建 **800 字节 PDO** 变体工程 `TwinCAT_EL6695_Primary_800B`,实现 TwinCAT ↔ J1900 双向 800B/周期数据交换,并保持逐字节可验证性。
|
||||
|
||||
选型说明:800B 介于 8B(验证通路)与 1024B(ESI 默认上限)之间,可作为实际应用的带宽档位;同时验证任意尺寸的映射 blob 生成规则。
|
||||
|
||||
---
|
||||
|
||||
## 2. 关键技术点(复用既有经验)
|
||||
|
||||
| # | 经验 | 应用到 800B |
|
||||
|---|---|---|
|
||||
| 1 | 链接必须整数组(`LinkVariables`) | 同 8B,PLC 数组与 PDO 条目同类型同尺寸 |
|
||||
| 2 | 类型 GUID 必须复用 PLC 构建生成的随机 GUID | 先建 PLC `ARRAY[0..799]`,构建取 GUID 填 PDO 条目 |
|
||||
| 3 | SM3 不挂 0x1A01 诊断 PDO,否则设备报 `size not allowed` | SM3 纯 800B,不含诊断(若含诊断则需 802B) |
|
||||
| 4 | EL6695 固件按 PDO 赋值总和校验 SM 长度 | SM2=SM3=800(0x0320),两侧一致 |
|
||||
| 5 | 映射 blob 须为 TwinCAT 行格式(240bit 条目 + 余量) | 见 §3 数学 |
|
||||
| 6 | 先激活 TwinCAT,再启动 J1900 ticker(同一会话) | 部署顺序不变 |
|
||||
|
||||
---
|
||||
|
||||
## 3. PDO 映射 blob 数学(800B)
|
||||
|
||||
EL6695 固件要求映射为 TwinCAT 行格式:真实对象条目 @240bit + 若干 0x0000:00 延续条目,总位数 = payload 位数。
|
||||
|
||||
```
|
||||
800 B = 6400 bit = 26 × 240 bit + 160 bit
|
||||
blob = [条目数=27 (u16 LE)]
|
||||
+ [240, 1, obj_lo, obj_hi] (真实对象 0x6000/0x7000 子索引1)
|
||||
+ 25 × [240, 0, 0, 0] (延续)
|
||||
+ 1 × [160, 0, 0, 0] (余量延续)
|
||||
```
|
||||
|
||||
`bridge.rs` 的 `twin_layout_blob_sized` 需泛化:`payload_bytes ≤ 30` 走单条目;否则按 `ceil` 生成多条目(1 真实 + (n-2) 延续 + 1 余量延续),1024B 时退化为现有 35 条目格式(字节级兼容已验证)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 工程结构
|
||||
|
||||
```
|
||||
twincat3-auto-cli/
|
||||
├─ TwinCAT_EL6695_Primary\ (8B, 不动)
|
||||
├─ TwinCAT_EL6695_Primary_2kHz\ (2kHz, 不动)
|
||||
├─ TwinCAT_EL6695_Primary_4kHz\ (4kHz, 不动)
|
||||
└─ TwinCAT_EL6695_Primary_800B\ (新建, 本方案)
|
||||
```
|
||||
|
||||
J1900 二进制: `/root/gateway/el6695_rt_800b`(新构建,旧的全部保留)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 实施步骤
|
||||
|
||||
### 5.1 TwinCAT 侧(副本工程)
|
||||
|
||||
| 步骤 | 内容 |
|
||||
|---|---|
|
||||
| 1 | robocopy 复制 `TwinCAT_EL6695_Primary` → `_800B`;修 sln 为相对路径(防绝对路径 bug) |
|
||||
| 2 | PLC: `GVL_Sync.aIn1/aOut1` → `ARRAY[0..799] OF BYTE`;MAIN 协议改 800B 布局(§6) |
|
||||
| 3 | 构建 PLC → 从 tsproj 取 `ARRAY [0..799]` 的随机 GUID |
|
||||
| 4 | tsproj PDO 条目(0x1608/0x1A08)类型替换为该 GUID 的 `ARRAY [0..799] OF BYTE` |
|
||||
| 5 | SM2 记录: `001c200364...`(len=0x0320=800);SM3 记录: `008e200320...`(len=800),0x1A01 仍不挂 SM3 |
|
||||
| 6 | `tc-relink.ps1` 整数组重建链接;部署激活;验证 _Boot tszip 中 SM2/SM3=800 |
|
||||
|
||||
### 5.2 J1900 侧
|
||||
|
||||
| 步骤 | 内容 |
|
||||
|---|---|
|
||||
| 1 | `twin_layout_blob_sized` 泛化为多条目(§3) |
|
||||
| 2 | 常量: `PAYLOAD_LEN=SM_TX_LEN=SM_RX_LEN=SM_RX_PLD_LEN=800` |
|
||||
| 3 | SM 长度写 800;FMMU len 写 800 |
|
||||
| 4 | ticker 走 1KB 式协议路径(f(x)=x·7+3 + 图案回显 + 时间戳字段),现有编译期守卫 `PAYLOAD_LEN>=256/280` 自动生效 |
|
||||
| 5 | 交叉编译(rust-lld)→ scp 为 `el6695_rt_800b` |
|
||||
|
||||
### 5.3 数据协议(800B 布局)
|
||||
|
||||
| 偏移 | 内容 | 方向 |
|
||||
|---|---|---|
|
||||
| [0..7] | TwinCAT `nCycles`(ULINT) → J1900 回 `nCycles*7+3` | 双向 |
|
||||
| [8..15] | J1900 本地周期号 | J→T |
|
||||
| [16..799] | 逐字节图案 `(nCycles + i) mod 256`,J1900 原样回显 | 双向 |
|
||||
| [264..267] | J1900 周期抖动 ns | J→T |
|
||||
| [268..271] | J1900 图案失配计数 | J→T |
|
||||
| [272..279] | J1900 回存的原始 tc_seq | J→T |
|
||||
|
||||
TwinCAT 校验(复用 1KB 逻辑):从 `nProcessedSeq` 反推原始 seq → 按 seq 重建预期图案逐字节比对 [16..799] → `bSync`;RTT = nCycles − nReturnedSeq。
|
||||
|
||||
### 5.4 验证
|
||||
|
||||
1. J1900 日志:SM2/SM3 len=800、OP、stale=0%、mism=0;
|
||||
2. TwinCAT ADS: `bSync=True`、`aIn1` 非零字节数 ≈ 784(图案区)、RTT 稳定;
|
||||
3. 逐字节证据:抽 [16..799] 中多个偏移核对 `(seq+i) mod 256`;
|
||||
4. 连续 10 分钟:nMismatch 零增长、tx/rx 零错误;
|
||||
5. 频率:保持 1kHz(带宽目标,不引入 2k/4k 变量)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 风险与注意点
|
||||
|
||||
| # | 风险 | 缓解 |
|
||||
|---|---|---|
|
||||
| R1 | 多条目 blob 被固件拒绝(余量条目不认) | 先用 verify 模式观察 AL 状态码;备选:全部按 240bit 进位到 27×240(6480bit,多 80bit 填 0) |
|
||||
| R2 | 800B 时 SM 长度设备校验失败 | 事件日志看 `min/max size`;按报告值对齐 |
|
||||
| R3 | PLC 构建后 tsproj 类型 GUID 抓取失败 | 构建后 rg 校验 GUID 存在再替换 |
|
||||
| R4 | 1kHz 下 800B 帧对 E-bus 其他端子无影响 | 既有端子已在 1kHz 验证过,800B 增量小 |
|
||||
|
||||
## 7. 工时估计
|
||||
|
||||
约 2–3 小时(含一次失败重试余量):tsproj 手术 30min、PLC 30min、J1900 blob 泛化+构建 40min、联调验证 40min。
|
||||
|
||||
## 8. 修订历史
|
||||
|
||||
| 日期 | 内容 |
|
||||
|---|---|
|
||||
| 2026-07-27 | 初版方案 |
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# EL6695 桥接 8 字节双向实时通讯 — 设计文档
|
||||
|
||||
> **版本**: 1.0
|
||||
> **版本**: 1.1(新增 §8 800B 变体)
|
||||
> **日期**: 2026-07-27
|
||||
> **状态**: 已实现并验证通过
|
||||
> **前置文档**: `1kb-verification-progress.md`(1KB 版本演进史)
|
||||
|
|
@ -224,3 +224,64 @@ scp -J tonycao@192.168.58.8 target/x86_64-unknown-linux-musl/release/el6695-rt `
|
|||
1. **无诊断 PDO**: 8B 配置不含 "External device not connected" 等状态位。若需要,须在 SM3 同时赋值 0x1A01+0x1A08 并保持 SM3=10(TwinCAT 侧重算逻辑需相应修正)。
|
||||
2. **延迟**: 往返固定 4 个 PLC 周期(≈4ms @1kHz),未做 DC 同步优化。
|
||||
3. **尺寸扩展**: 本设计的修改方法(GUID 类型 + SM 记录 + J1900 常量)适用于任意 ≤240bit 的单条目尺寸;更大尺寸需在 `twin_layout_blob_sized` 中恢复多条目延续格式。
|
||||
|
||||
---
|
||||
|
||||
## 8. 800B 变体(已实现并验证)
|
||||
|
||||
在 8B 验证通路基础上,扩展出 800 字节 PDO 工程 `TwinCAT_EL6695_Primary_800B`,作为实际应用的带宽档位,并验证了任意尺寸的映射 blob 生成规则。
|
||||
|
||||
### 8.1 与 8B 设计的差异
|
||||
|
||||
| 项 | 8B | 800B |
|
||||
|---|---|---|
|
||||
| PDO 条目类型 | `ARRAY [0..7] OF BYTE` | `ARRAY [0..799] OF BYTE`(GUID `{7D10FDFE-13E3-A012-D822-BE30F7D36D23}`,PLC 构建生成) |
|
||||
| SM2/SM3 长度 | 8 / 8 | **800 / 800**(0x0320) |
|
||||
| 0x1A01 诊断 PDO | 不挂 SM3 | 同左(沿用,否则设备报 `size not allowed`) |
|
||||
| 映射 blob | 单条目 64bit | **27 条目**(见 §8.2) |
|
||||
| 数据协议 | 每字节 XOR 0x5A + 历史环 | seq + f(x)=x·7+3 + 逐字节图案 + 反推校验(类 1KB) |
|
||||
| 周期 | 1kHz(基线) | 1kHz |
|
||||
|
||||
### 8.2 多条目映射 blob 生成规则
|
||||
|
||||
EL6695 固件接受 TwinCAT 行格式:1 真实对象条目 @240bit + N 延续条目(0x0000:00)@240bit + 1 余量延续条目。
|
||||
|
||||
```
|
||||
800 B = 6400 bit = 26 × 240 bit + 160 bit
|
||||
blob = [27 (u16 LE)]
|
||||
+ [240, 1, obj_lo, obj_hi] 真实对象 (0x6000:01 / 0x7000:01)
|
||||
+ 25 × [240, 0, 0, 0] 延续
|
||||
+ 1 × [160, 0, 0, 0] 余量延续
|
||||
```
|
||||
|
||||
`twin_layout_blob_sized(obj, n)` 泛化实现:≤240bit 单条目;>240bit 按上式多条目;1024B 特判保持原 35 条目格式(字节级兼容)。
|
||||
|
||||
### 8.3 800B 数据布局
|
||||
|
||||
| 偏移 | 内容 | 方向 |
|
||||
|---|---|---|
|
||||
| [0..7] | TwinCAT `nCycles` → J1900 回 `nCycles*7+3` | 双向 |
|
||||
| [8..15] | J1900 本地周期号 | J→T |
|
||||
| [16..263] | 逐字节图案 `(nCycles+i) mod 256`,J1900 原样回显 | 双向 |
|
||||
| [264..267] | J1900 周期抖动 ns | J→T |
|
||||
| [268..271] | J1900 图案失配计数 | J→T |
|
||||
| [272..279] | J1900 回存的原始 tc_seq | J→T |
|
||||
| [280..799] | 逐字节图案(同上) | 双向 |
|
||||
|
||||
**设计要点:图案区必须避开 [264..279] 统计字段**——首版实现按 [16..799] 连续图案,J1900 统计字段覆盖 16 字节导致 PLC 每周期 16 字节失配。
|
||||
|
||||
### 8.4 新增陷阱(800B 实测)
|
||||
|
||||
| # | 现象 | 根因 | 解决 |
|
||||
|---|---|---|---|
|
||||
| 8 | 激活时 EL6695 SAFEOP 失败,AL 状态码 0x0003 | **激活与 J1900 ticker 会话并发**:relink 激活时 ticker 正在跑,桥两侧主站会话冲突 | 激活必须在 J1900 空闲时进行;失败后空载重新激活即恢复 |
|
||||
| 9 | 数据通但 PLC bSync=False,每周期固定 16 字节失配 | 图案区 [16..799] 与 J1900 统计字段 [264..279] 重叠 | 图案区改为 [16..263]+[280..799](见 §8.3) |
|
||||
|
||||
### 8.5 800B 实测性能
|
||||
|
||||
| 指标 | 值 |
|
||||
|---|---|
|
||||
| J1900 exec(800B,同步写) | 均值 384µs / p99 400µs |
|
||||
| FPRD(读 800B) | 均值 139µs / p99 156µs(8B 时为 71µs) |
|
||||
| FPWR(写 800B) | 均值 244µs / p99 260µs(与 8B 基本持平) |
|
||||
| 桥接 RTT(1kHz) | 4 周期(lag=4,同 8B/1KB 结构) |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# EL6695 8B 双向通讯 — 测试文档
|
||||
|
||||
> **版本**: 1.0
|
||||
> **版本**: 1.1(新增 §8 800B 测试)
|
||||
> **日期**: 2026-07-27
|
||||
> **结论**: ✅ 全部通过
|
||||
> **配套文档**: `8b-bridge-design.md`、`8b-verification-methodology.md`
|
||||
|
|
@ -172,3 +172,60 @@ Copy-Item "C:\Users\tonycao\work\twincat3-auto-cli\TwinCAT_EL6695_Primary\TwinCA
|
|||
| 日期 | 内容 |
|
||||
|---|---|
|
||||
| 2026-07-27 | 初版:8B 双向交换全部测试通过 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 800B 变体测试(2026-07-28)
|
||||
|
||||
### 8.1 环境差异
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| TwinCAT 工程 | `TwinCAT_EL6695_Primary_800B`(1kHz 任务) |
|
||||
| PDO 尺寸 | 800B(SM2/SM3 = 0x0320) |
|
||||
| J1900 二进制 | `/root/gateway/el6695_rt_800b` |
|
||||
| 校验脚本 | `scripts/tc-ads-verify-800b.ps1`、`tc-ads-mismatch-delta.ps1`、`tc-relink-800b.ps1`、`tc-deploy-retry-800b.ps1` |
|
||||
|
||||
### 8.2 配置确认(激活后 _Boot tszip)
|
||||
|
||||
```
|
||||
SM2: 001c200364... (start=0x1C00 len=0x0320=800 ✓ 保留)
|
||||
SM3: 008e200320... (start=0x8E00 len=0x0320=800 ✓ 保留)
|
||||
PDO 条目: ARRAY [0..799] OF BYTE (GUID {7D10FDFE-13E3-A012-D822-BE30F7D36D23})
|
||||
事件日志: 无 EL6695 错误
|
||||
```
|
||||
|
||||
### 8.3 功能验证
|
||||
|
||||
| 项 | 结果 |
|
||||
|---|---|
|
||||
| J1900 映射 blob | 27 条目(26×240+160bit)被固件接受,SAFEOP/OP 通过 |
|
||||
| 处理证明 | `proc = raw*7+3` 逐样本精确(如 107636 → 753455) |
|
||||
| PLC 校验 | bSync=True,lag=4 |
|
||||
| 图案覆盖 | aIn1 非零 775–776/800;[16..263]+[280..799] 逐字节 `(seq+i)%256` 抽查全对 |
|
||||
|
||||
### 8.4 10 分钟稳定性(600,000 周期)
|
||||
|
||||
| 指标 | 结果 |
|
||||
|---|---|
|
||||
| 周期完整 | 600000 周期 / 600.0s,零丢失 |
|
||||
| 传输错误 | tx_err=0, rx_err=0 |
|
||||
| J1900 图案失配 | mism=0 |
|
||||
| PLC nMismatch | 295s 运行窗口零增长;90s 确认测试 delta=0 |
|
||||
| stale | 2999 周期(0.5%) |
|
||||
| 周期抖动 | 均值 4.89µs / p99 5.4µs(单次 499µs 离群) |
|
||||
| exec | 均值 384µs / p99 400µs |
|
||||
| FPRD / FPWR | 139µs / 244µs |
|
||||
|
||||
注:起止时刻的 nMismatch 增长均为**对端缺席期**的预期累积(ticker 未启动/已停止),运行窗口内零失配。
|
||||
|
||||
### 8.5 800B 特有故障记录
|
||||
|
||||
| # | 故障 | 根因 | 处置 |
|
||||
|---|---|---|---|
|
||||
| F1 | relink 激活时 EL6695 SAFEOP 失败(AL 0x0003) | 激活与运行中的 ticker 会话并发冲突 | J1900 空闲后重新激活即恢复;流程约定:**先激活 TwinCAT,后启动 ticker,激活期间 J1900 必须空闲** |
|
||||
| F2 | 数据通但每周期固定 16 字节失配 | 图案区 [16..799] 覆盖 J1900 统计字段 [264..279] | 图案区改为 [16..263]+[280..799](MAIN 与校验循环同步修改) |
|
||||
|
||||
### 8.6 回退
|
||||
|
||||
800B 工程为独立副本,不影响 8B/1kHz 主工程;切回:重新激活 `TwinCAT_EL6695_Primary`(`tc-deploy-retry.ps1`),J1900 使用 `el6695_rt_8b_xor`。
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# EL6695 8B 双向通讯 — 验证说明文档
|
||||
|
||||
> **版本**: 1.0
|
||||
> **版本**: 1.1(新增 §7 800B 验证)
|
||||
> **日期**: 2026-07-27
|
||||
> **配套文档**: `8b-bridge-design.md`(设计)、`8b-test-report.md`(测试记录)
|
||||
|
||||
|
|
@ -151,3 +151,47 @@ aIn1^5A = 98-B8-D8-F8-18-38-58-78 ← 8/8 全等
|
|||
1. 验证图案为周期性确定图案,未做随机负载压力测试;
|
||||
2. `lag=4` 为当前拓扑/周期下的实测值,未验证不同任务周期下的行为;
|
||||
3. 8B 配置不含诊断 PDO,"对端是否在线"需以数据流本身判断(失配即掉线)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 800B 变体的验证方法
|
||||
|
||||
800B 工程采用**序列号 + 图案 + 反推校验**协议(类 1KB),与 8B 的 XOR 历史环不同,原因是 800B 要同时验证"大载荷每个字节"与"序号处理"两个维度。
|
||||
|
||||
### 7.1 协议与验证链
|
||||
|
||||
```
|
||||
TwinCAT 发送: aOut1[0..7] = nCycles; aOut1[i] = (nCycles+i) mod 256
|
||||
(i ∈ [16..263] ∪ [280..799], 避开 [264..279] 统计字段)
|
||||
J1900 处理: tx[0..7] = rx_seq*7+3; tx[8..15] = 本地周期号;
|
||||
tx[264..279] = 抖动/失配/原始 seq; 其余字节原样回显
|
||||
TwinCAT 校验: nProcessedSeq = aIn1[0..7]
|
||||
nReturnedSeq = (nProcessedSeq - 3) / 7 (MOD 7 = 0 才有效)
|
||||
逐字节比对 aIn1[i] == (nReturnedSeq + i) mod 256
|
||||
```
|
||||
|
||||
- **反推校验**:J1900 的 f(x)=x·7+3 可逆,PLC 从回传值反推原始发送周期,无需预设管线延迟(实测 lag=4);
|
||||
- **J1900 侧自检**:ticker 对图案区 [16..255] 做 `(tc_seq+i) mod 256` 独立校验(`mism` 计数),与 PLC 侧校验互为对侧证据。
|
||||
|
||||
### 7.2 与 8B 方法的取舍
|
||||
|
||||
| 维度 | 8B(XOR 历史环) | 800B(seq+图案反推) |
|
||||
|---|---|---|
|
||||
| 每字节独立性 | 强(每字节独立 XOR) | 中(图案含周期序号,错位立现) |
|
||||
| 延迟测量 | 直接(nMatchLag) | 直接(nCycles − nReturnedSeq) |
|
||||
| 大载荷成本 | 历史环 16×8B 比对/周期 | 768 字节比对/周期 |
|
||||
| 适合 | 小载荷通路证明 | 应用级带宽验证 |
|
||||
|
||||
### 7.3 ADS 快照判读(800B 特有)
|
||||
|
||||
外部 ADS 校验脚本用 `nReturnedSeq` 重建预期图案时,因 `nCycles/nReturnedSeq/aIn1` 分次读取,可能出现 `nReturnedSeq > nCycles`(显示 lag 为负)与全图案"失配"的假象——**以 PLC 内部 1kHz 实时计算的 `bSync` 为唯一权威判据**;ADS 全数组读取仅用于非零覆盖率统计(800B 时应 ≈770+/800)。
|
||||
|
||||
### 7.4 800B 稳定性判据
|
||||
|
||||
| 判据 | 通过条件 | 实测 |
|
||||
|---|---|---|
|
||||
| J1900 周期完整 | 周期数 = 时长 × 频率 | 600000 / 600.0s ✅ |
|
||||
| J1900 `mism` | 0 | ✅ |
|
||||
| PLC `nMismatch` | 运行窗口内零增长 | 295s 窗口 delta=0;90s 确认 delta=0 ✅ |
|
||||
| 传输错误 | tx/rx = 0 | ✅ |
|
||||
| 非零覆盖率 | ≈770/800 | 775–776 ✅ |
|
||||
|
|
|
|||
122
docs/d2000-dev-plan.md
Normal file
122
docs/d2000-dev-plan.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# 飞腾 D2000 ↔ EL6695 ↔ TwinCAT 通讯链路 — 开发计划
|
||||
|
||||
> **版本**: 1.0
|
||||
> **日期**: 2026-07-28
|
||||
> **状态**: 待启动
|
||||
> **前置成果**: J1900 链路全部方法论(8B/800B 设计、验证体系、脚本集、Rust 代码库)
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标与拓扑
|
||||
|
||||
在现有 J1900 链路之外,新增一条**并列**通讯链路:飞腾 D2000(ARM64)经 EL6695#2 与 TwinCAT PC 实时数据交换,复用已验证的配置方法与验证体系。
|
||||
|
||||
```
|
||||
TwinCAT PC (169.254.176.217)
|
||||
│
|
||||
├─ [现有链路] EK1100 → ... → EL6695#1 → J1900 (x86_64, Debian13+RT) ✅ 已验收
|
||||
│
|
||||
└─ [新增链路] E-bus 扩展或独立网口 → EL6695#2 → 飞腾 D2000 (aarch64) 🆕
|
||||
▲
|
||||
跳板机#2 网口 (SSH 管理通道)
|
||||
```
|
||||
|
||||
### 待确认事项(启动前)
|
||||
|
||||
| # | 问题 | 影响 |
|
||||
|---|---|---|
|
||||
| Q1 | EL6695#2 挂在哪里?(现有 E-bus 末端 EL9011 前扩展,还是 TwinCAT 第二网口独立段?) | TwinCAT 工程拓扑/网卡规划 |
|
||||
| Q2 | D2000 的 OS 与内核(麒麟 V10? UOS? Ubuntu? 内核版本? 是否有 PREEMPT_RT?) | RT 性能预期、移植工作量 |
|
||||
| Q3 | D2000 管理通道:跳板机#2 的地址、SSH 凭据、能否免密 | 自动化部署方式 |
|
||||
| Q4 | D2000 接 EL6695 的网口(板载 GbE? 独立网卡? 驱动?) | ethercrab 裸 socket 可用性 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 阶段计划
|
||||
|
||||
### 阶段 1:环境与可达性(0.5 天)
|
||||
|
||||
| # | 任务 | 产出 |
|
||||
|---|---|---|
|
||||
| 1.1 | 经跳板机#2 SSH 到 D2000,采集:`uname -a`、`/etc/os-release`、`/proc/version`、CPU/核数、网口列表(`ip link`)、中断分布(`/proc/interrupts`) | 环境档案 |
|
||||
| 1.2 | 确认 PREEMPT_RT(`uname -v` 含 rt?)、`chrt`/`mlockall` 可用性 | RT 基线判定 |
|
||||
| 1.3 | 网络打通:D2000 → EL6695#2 网线;D2000 → 跳板机 管理网 | 拓扑照片/记录 |
|
||||
| 1.4 | 空口探测:tcpdump/裸 socket 读 ethX,确认能收发二层帧 | 网卡可用性 |
|
||||
|
||||
### 阶段 2:Rust 交叉编译 aarch64(0.5 天)
|
||||
|
||||
| # | 任务 | 备注 |
|
||||
|---|---|---|
|
||||
| 2.1 | `rustup target add aarch64-unknown-linux-musl`;`cargo build --target aarch64-unknown-linux-musl --release` | ethercrab 为纯 Rust,理论上零改动;libc 裸 socket(AF_PACKET)在 aarch64 内核同样支持 |
|
||||
| 2.2 | 链接器:沿用 `RUSTFLAGS="-C linker=rust-lld"`(musl 静态,免去 D2000 上 glibc 版本问题) | musl 静态二进制通吃 Kylin/UOS/Debian |
|
||||
| 2.3 | 部署 scp → D2000,跑 `--mode probe`(只读扫描) | 首次上机验证 |
|
||||
| 2.4 | 若 AF_PACKET 在目标内核异常,备选 `aarch64-unknown-linux-gnu` + 检查目标 glibc | 风险预案 |
|
||||
|
||||
### 阶段 3:EL6695 链路开通(0.5–1 天,方法全部现成)
|
||||
|
||||
| # | 任务 | 复用资产 |
|
||||
|---|---|---|
|
||||
| 3.1 | TwinCAT 侧:复制 8B 工程为 `TwinCAT_EL6695_Primary_D2000`(或在 EL6695#2 所在段新建拓扑),激活确认 SM2/SM3 | `tc-deploy-retry.ps1` 模式 |
|
||||
| 3.2 | D2000 侧:`el6695_rt ethX --mode verify` CoE 审计 → ConfigOwner 到 OP | 与 J1900 完全相同的流程 |
|
||||
| 3.3 | **严格遵守顺序:TwinCAT 激活时 D2000 侧空闲;先激活,后启 ticker**(800B 踩坑 F1) | 教训文档化 |
|
||||
| 3.4 | ticker 8B XOR 模式联通,PLC bSync=True | `GVL_Sync` 验证体系 |
|
||||
|
||||
### 阶段 4:数据验证与实时性测量(0.5 天)
|
||||
|
||||
| # | 任务 | 判据 |
|
||||
|---|---|---|
|
||||
| 4.1 | 8B 逐字节验证(图案+XOR+历史环) | bSync=True,lag 稳定 |
|
||||
| 4.2 | 10 分钟稳定性 | 60 万周期零错误,nMismatch 零增长 |
|
||||
| 4.3 | D2000 实时性基线:周期抖动/exec/FPRD/FPWR 统计 | 与 J1900 对照(7µs 抖动基准) |
|
||||
| 4.4 | 如需 800B:换 `el6695_rt_800b` 对应构建(同源码,常量切换) | 800B 工程现成 |
|
||||
|
||||
### 阶段 5:D2000 RT 调优(按需,0.5–1 天)
|
||||
|
||||
| # | 措施 | 场景 |
|
||||
|---|---|---|
|
||||
| 5.1 | IRQ 亲和:管理网口 IRQ 钉到非 RT 核 | 必做 |
|
||||
| 5.2 | 核隔离 `isolcpus` + ticker 绑核(程序已支持 `--core`) | 推荐 |
|
||||
| 5.3 | 若无 RT 补丁且抖动不可接受:评估编译 aarch64 PREEMPT_RT 内核(源码 kernel.org + rt patch,交叉编译) | 兜底 |
|
||||
| 5.4 | 抖动向因分析:hwlatdetect/cyclictest 对照 | 诊断工具 |
|
||||
|
||||
### 阶段 6:文档与归档(0.5 天)
|
||||
|
||||
- 新增 `docs/d2000-bringup.md`(环境档案、移植记录、与 J1900 的性能对照)
|
||||
- 更新三份主文档的适用范围章节;git 提交
|
||||
|
||||
---
|
||||
|
||||
## 3. 复用率评估
|
||||
|
||||
| 资产 | 复用程度 |
|
||||
|---|---|
|
||||
| el6695_rt 源码(main.rs/bridge.rs) | ~100%(唯一改动:默认网口名/可能的字节序检查——ARM 与 x86 同小端,无影响) |
|
||||
| TwinCAT 工程与 PLC 验证程序 | 100%(复制副本改拓扑) |
|
||||
| 部署/诊断/监视脚本(20+ 个) | ~90%(J1900 地址替换为 D2000 地址) |
|
||||
| 配置方法论(SM/PDO/blob/链接/激活顺序) | 100% |
|
||||
|
||||
## 4. 风险登记
|
||||
|
||||
| # | 风险 | 概率 | 缓解 |
|
||||
|---|---|---|---|
|
||||
| R1 | D2000 OS 无 PREEMPT_RT,抖动大(几十~几百 µs) | 高 | 阶段 5.3 自编译 RT 内核;或先测后判,1kHz 场景通常可接受 |
|
||||
| R2 | 麒麟/UOS 老内核(4.19)与 ethercrab 兼容性 | 低 | musl 静态;AF_PACKET 自 2.2 内核即有 |
|
||||
| R3 | D2000 网口驱动不支持混杂/裸包或性能差 | 低 | 阶段 1.4 提前探测;备 USB 网卡 |
|
||||
| R4 | 跳板机#2 到 D2000 的 SSH 不稳定 | 中 | 串口兜底;长会话用 nohup+日志(既有模式) |
|
||||
| R5 | 双链路并存时 TwinCAT 两张网卡/两段总线资源冲突 | 低 | Q1 拓扑确认后评审 |
|
||||
|
||||
## 5. 里程碑
|
||||
|
||||
| 里程碑 | 判据 |
|
||||
|---|---|
|
||||
| M1 | D2000 SSH 通,环境档案完成(Q1–Q4 全部答案) |
|
||||
| M2 | aarch64 二进制在 D2000 上 `--mode probe` 发现 EL6695 |
|
||||
| M3 | 链路 OP,8B bSync=True |
|
||||
| M4 | 10 分钟零错误 + 抖动基线报告 |
|
||||
| M5 | 文档归档 + git 提交 |
|
||||
|
||||
## 6. 修订历史
|
||||
|
||||
| 日期 | 内容 |
|
||||
|---|---|
|
||||
| 2026-07-28 | 初版计划 |
|
||||
69
docs/jitter-analysis.md
Normal file
69
docs/jitter-analysis.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# J1900 实时性能偶发最大抖动分析
|
||||
|
||||
> **日期**: 2026-07-28
|
||||
> **对象**: J1900 (Debian 13, Linux 6.6.135-rt74 PREEMPT_RT) 上 el6695_rt ticker 的周期抖动
|
||||
> **数据来源**: 1kHz 8B 600s 测试、800B 10 分钟测试、4kHz 测试、800B 5 小时(1800 万周期)测试
|
||||
|
||||
---
|
||||
|
||||
## 1. 现象
|
||||
|
||||
周期抖动(实际周期相对名义周期的偏差)的**均值极小(5–7µs)**,但偶发数百微秒的最大值:
|
||||
|
||||
| 测试 | 样本数 | jitter 均值 | jitter max |
|
||||
|---|---|---|---|
|
||||
| 1kHz 8B, 600s | 600,000 | 7.29µs | **10.0µs** |
|
||||
| 800B, 10 分钟 | 600,000 | 4.89µs | **499.1µs** |
|
||||
| 4kHz, 120s | 352,917 | 90µs(含滑相) | **1549µs** |
|
||||
| **800B, 5 小时** | **18,000,000** | **7.39µs** | **41.8µs** |
|
||||
|
||||
关键观察:尖峰幅度**不是系统固有属性**——5 小时静默运行(1800 万样本)最大仅 41.8µs,而活动密集的 10 分钟测试出现 499µs。尖峰与并发系统活动强相关。
|
||||
|
||||
## 2. 诊断证据
|
||||
|
||||
### 2.1 系统环境(J1900 实测)
|
||||
|
||||
| 项 | 值 | 影响 |
|
||||
|---|---|---|
|
||||
| 根文件系统 | **NFS**:`192.168.68.1:/j1900-node2/rootfs`(TwinCAT PC 做 NFS 服务器) | 一切文件访问走网络 |
|
||||
| /tmp | tmpfs(内存) | ticker 日志不落盘 ✓ |
|
||||
| 设备中断 | eth0-rx 30 万次全在 CPU0;ahci/ttyS0 也在 CPU0/1 | ticker 核 CPU2 无设备 IRQ ✓ |
|
||||
| 调度 | ticker 绑定核 2,SCHED_FIFO 80,mlockall,栈预缺页 | 基础保障已做 |
|
||||
| dmesg | 无热事件、无异常;sshd 栈深度提示(良性) | 排除过热 |
|
||||
|
||||
### 2.2 相关性
|
||||
|
||||
尖峰最频繁的测试(10 分钟、4kHz)期间,Windows 侧正密集进行 TwinCAT 构建/激活与 SSH 会话;5 小时静默期几乎无尖峰。
|
||||
|
||||
## 3. 原因排序
|
||||
|
||||
| # | 原因 | 机理 | 符合度 |
|
||||
|---|---|---|---|
|
||||
| 1 | **NFS 根文件系统停顿** | Windows NFS 服务器忙(VS 构建、大文件 I/O)→ J1900 侧触盘进程阻塞 → 网络 softirq、内存回收压力波及 RT 核 | ★★★★ 主因(静默期 max 仅 41.8µs) |
|
||||
| 2 | **SMI 系统管理中断** | J1900(Bay Trail Atom)BIOS 的 USB legacy / 嵌入式控制器 / 热管理 SMI,100–500µs 不可屏蔽、OS 不可见 | ★★★ 次嫌疑(偶发形态吻合,需 hwlatdetect 证实) |
|
||||
| 3 | **深 C 状态退出** | Bay Trail C6 退出延迟 ~100–200µs;周期睡眠偶入深态 | ★★(均值仅 5–7µs,多数时间为浅态) |
|
||||
|
||||
## 4. 验证方法
|
||||
|
||||
```bash
|
||||
# 区分硬件(SMI) vs 软件(NFS/OS)延迟 — 内核 6.6 自带 rtla:
|
||||
rtla hwlatdetect --cpus 2 --duration 60
|
||||
# 判定: hwlatdetect 报数百微秒 => SMI/硬件; 干净 => NFS/OS 软件因素
|
||||
|
||||
# 辅助: cyclictest 对照(无 EtherCAT 负载时测量裸调度抖动)
|
||||
cyclictest -m -p 80 -i 1000 -l 60000 -a 2
|
||||
```
|
||||
|
||||
## 5. 缓解建议(按收益排序)
|
||||
|
||||
| # | 措施 | 预期效果 |
|
||||
|---|---|---|
|
||||
| 1 | gateway 目录与日志移出 NFS(tmpfs 或本地存储) | 消除主因 |
|
||||
| 2 | BIOS 关闭 USB Legacy、不需要的 EC 功能 | 消 SMI 尖峰 |
|
||||
| 3 | 内核启动参数 `isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3` | 完全隔离 RT 核 |
|
||||
| 4 | `intel_idle.max_cstate=1` 限制最深 C 状态 | 消 C6 退出尖峰(功耗换延迟) |
|
||||
| 5 | IRQ 亲和性复核(保持设备 IRQ 远离核 2/3) | 已满足,固化 |
|
||||
|
||||
## 6. 结论
|
||||
|
||||
J1900 基础实时性良好(均值 5–7µs,p99 < 10µs,1800 万周期零丢帧)。偶发数百微秒尖峰的主因是 **NFS 根文件系统在 Windows 服务器繁忙时的停顿**;SMI 为次要嫌疑,可用 `rtla hwlatdetect` 一测定论。对当前 EL6695 数据通道无实质影响(尖峰只占 ~0.0001%,且 1kHz 预算 1ms 内 exec 最大 400µs 仍有富余)。
|
||||
301
monitor_5h.csv
Normal file
301
monitor_5h.csv
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
timestamp,nCycles,bSync,nReturnedSeq,nMismatch,nProcMismatch
|
||||
2026-07-28 02:13:04,1825622,False,0,648246528,844072
|
||||
2026-07-28 02:14:04,1885662,False,0,694359552,904116
|
||||
2026-07-28 02:15:04,1945680,False,0,740451072,964130
|
||||
2026-07-28 02:16:04,2005694,False,0,786541824,1024144
|
||||
2026-07-28 02:17:04,2065708,True,2065707,789764352,1028339
|
||||
2026-07-28 02:18:04,2125730,True,2125727,789764352,1028339
|
||||
2026-07-28 02:19:04,2185753,True,2185751,789764352,1028339
|
||||
2026-07-28 02:20:04,2245766,True,2245766,789764352,1028339
|
||||
2026-07-28 02:21:04,2305794,True,2305794,789764352,1028339
|
||||
2026-07-28 02:22:04,2365820,True,2365819,789764352,1028339
|
||||
2026-07-28 02:23:04,2425842,True,2425840,789764352,1028339
|
||||
2026-07-28 02:24:04,2485861,True,2485861,789764352,1028339
|
||||
2026-07-28 02:25:04,2545882,True,2545880,789764352,1028339
|
||||
2026-07-28 02:26:04,2605900,True,2605898,789764352,1028339
|
||||
2026-07-28 02:27:04,2665917,True,2665914,789764352,1028339
|
||||
2026-07-28 02:28:04,2725936,True,2725934,789764352,1028339
|
||||
2026-07-28 02:29:04,2785961,True,2785960,789764352,1028339
|
||||
2026-07-28 02:30:04,2845983,True,2845981,789764352,1028339
|
||||
2026-07-28 02:31:04,2906006,True,2906006,789764352,1028339
|
||||
2026-07-28 02:32:05,2966030,True,2966028,789764352,1028339
|
||||
2026-07-28 02:33:05,3026050,True,3026048,789764352,1028339
|
||||
2026-07-28 02:34:05,3086068,True,3086066,789764352,1028339
|
||||
2026-07-28 02:35:05,3146087,True,3146087,789764352,1028339
|
||||
2026-07-28 02:36:05,3206113,True,3206111,789764352,1028339
|
||||
2026-07-28 02:37:05,3266139,True,3266139,789764352,1028339
|
||||
2026-07-28 02:38:05,3326161,True,3326159,789764352,1028339
|
||||
2026-07-28 02:39:05,3386183,True,3386181,789764352,1028339
|
||||
2026-07-28 02:40:05,3446206,True,3446206,789764352,1028339
|
||||
2026-07-28 02:41:05,3506232,True,3506232,789764352,1028339
|
||||
2026-07-28 02:42:05,3566251,True,3566249,789764352,1028339
|
||||
2026-07-28 02:43:05,3626266,True,3626264,789764352,1028339
|
||||
2026-07-28 02:44:05,3686283,True,3686281,789764352,1028339
|
||||
2026-07-28 02:45:05,3746311,True,3746310,789764352,1028339
|
||||
2026-07-28 02:46:05,3806331,True,3806329,789764352,1028339
|
||||
2026-07-28 02:47:05,3866346,True,3866344,789764352,1028339
|
||||
2026-07-28 02:48:05,3926364,True,3926364,789764352,1028339
|
||||
2026-07-28 02:49:05,3986384,True,3986382,789764352,1028339
|
||||
2026-07-28 02:50:05,4046400,True,4046400,789764352,1028339
|
||||
2026-07-28 02:51:05,4106421,True,4106419,789764352,1028339
|
||||
2026-07-28 02:52:05,4166439,True,4166439,789764352,1028339
|
||||
2026-07-28 02:53:05,4226466,True,4226466,789764352,1028339
|
||||
2026-07-28 02:54:05,4286494,True,4286493,789764352,1028339
|
||||
2026-07-28 02:55:05,4346518,True,4346518,789764352,1028339
|
||||
2026-07-28 02:56:05,4406539,True,4406537,789764352,1028339
|
||||
2026-07-28 02:57:05,4466565,True,4466565,789764352,1028339
|
||||
2026-07-28 02:58:05,4526588,True,4526586,789764352,1028339
|
||||
2026-07-28 02:59:05,4586605,True,4586603,789764352,1028339
|
||||
2026-07-28 03:00:05,4646620,True,4646618,789764352,1028339
|
||||
2026-07-28 03:01:05,4706637,True,4706636,789764352,1028339
|
||||
2026-07-28 03:02:05,4766661,True,4766661,789764352,1028339
|
||||
2026-07-28 03:03:05,4826684,True,4826681,789764352,1028339
|
||||
2026-07-28 03:04:05,4886701,True,4886699,789764352,1028339
|
||||
2026-07-28 03:05:05,4946724,True,4946724,789764352,1028339
|
||||
2026-07-28 03:06:05,5006746,True,5006744,789764352,1028339
|
||||
2026-07-28 03:07:05,5066761,True,5066759,789764352,1028339
|
||||
2026-07-28 03:08:05,5126775,True,5126773,789764352,1028339
|
||||
2026-07-28 03:09:05,5186795,True,5186795,789764352,1028339
|
||||
2026-07-28 03:10:05,5246822,True,5246822,789764352,1028339
|
||||
2026-07-28 03:11:05,5306841,True,5306839,789764352,1028339
|
||||
2026-07-28 03:12:05,5366855,True,5366852,789764352,1028339
|
||||
2026-07-28 03:13:05,5426873,True,5426870,789764352,1028339
|
||||
2026-07-28 03:14:05,5486893,True,5486891,789764352,1028339
|
||||
2026-07-28 03:15:05,5546919,True,5546919,789764352,1028339
|
||||
2026-07-28 03:16:05,5606940,True,5606938,789764352,1028339
|
||||
2026-07-28 03:17:05,5666962,True,5666962,789764352,1028339
|
||||
2026-07-28 03:18:05,5727000,True,5727000,789764352,1028339
|
||||
2026-07-28 03:19:05,5787020,True,5787018,789764352,1028339
|
||||
2026-07-28 03:20:06,5847036,True,5847034,789764352,1028339
|
||||
2026-07-28 03:21:06,5907050,True,5907047,789764352,1028339
|
||||
2026-07-28 03:22:06,5967067,True,5967067,789764352,1028339
|
||||
2026-07-28 03:23:06,6027086,True,6027084,789764352,1028339
|
||||
2026-07-28 03:24:06,6087101,True,6087099,789764352,1028339
|
||||
2026-07-28 03:25:06,6147119,True,6147117,789764352,1028339
|
||||
2026-07-28 03:26:06,6207138,True,6207136,789764352,1028339
|
||||
2026-07-28 03:27:06,6267161,True,6267161,789764352,1028339
|
||||
2026-07-28 03:28:06,6327180,True,6327178,789764352,1028339
|
||||
2026-07-28 03:29:06,6387197,True,6387195,789764352,1028339
|
||||
2026-07-28 03:30:06,6447216,True,6447215,789764352,1028339
|
||||
2026-07-28 03:31:06,6507241,True,6507241,789764352,1028339
|
||||
2026-07-28 03:32:06,6567266,True,6567266,789764352,1028339
|
||||
2026-07-28 03:33:06,6627289,True,6627287,789764352,1028339
|
||||
2026-07-28 03:34:06,6687315,True,6687315,789764352,1028339
|
||||
2026-07-28 03:35:06,6747338,True,6747336,789764352,1028339
|
||||
2026-07-28 03:36:06,6807356,True,6807354,789764352,1028339
|
||||
2026-07-28 03:37:06,6867377,True,6867375,789764352,1028339
|
||||
2026-07-28 03:38:06,6927395,True,6927393,789764352,1028339
|
||||
2026-07-28 03:39:06,6987416,True,6987416,789764352,1028339
|
||||
2026-07-28 03:40:06,7047439,True,7047436,789764352,1028339
|
||||
2026-07-28 03:41:06,7107458,True,7107456,789764352,1028339
|
||||
2026-07-28 03:42:06,7167475,True,7167473,789764352,1028339
|
||||
2026-07-28 03:43:06,7227497,True,7227497,789764352,1028339
|
||||
2026-07-28 03:44:06,7287521,True,7287519,789764352,1028339
|
||||
2026-07-28 03:45:06,7347541,True,7347539,789764352,1028339
|
||||
2026-07-28 03:46:06,7407560,True,7407558,789764352,1028339
|
||||
2026-07-28 03:47:06,7467578,True,7467577,789764352,1028339
|
||||
2026-07-28 03:48:06,7527598,True,7527596,789764352,1028339
|
||||
2026-07-28 03:49:06,7587620,True,7587619,789764352,1028339
|
||||
2026-07-28 03:50:06,7647641,True,7647639,789764352,1028339
|
||||
2026-07-28 03:51:06,7707657,True,7707655,789764352,1028339
|
||||
2026-07-28 03:52:06,7767680,True,7767678,789764352,1028339
|
||||
2026-07-28 03:53:06,7827700,True,7827700,789764352,1028339
|
||||
2026-07-28 03:54:06,7887729,True,7887729,789764352,1028339
|
||||
2026-07-28 03:55:06,7947752,True,7947750,789764352,1028339
|
||||
2026-07-28 03:56:06,8007768,True,8007766,789764352,1028339
|
||||
2026-07-28 03:57:06,8067790,True,8067788,789764352,1028339
|
||||
2026-07-28 03:58:06,8127817,True,8127816,789764352,1028339
|
||||
2026-07-28 03:59:06,8187839,True,8187838,789764352,1028339
|
||||
2026-07-28 04:00:06,8247866,True,8247866,789764352,1028339
|
||||
2026-07-28 04:01:06,8307889,True,8307887,789764352,1028339
|
||||
2026-07-28 04:02:06,8367908,True,8367906,789764352,1028339
|
||||
2026-07-28 04:03:06,8427927,True,8427927,789764352,1028339
|
||||
2026-07-28 04:04:06,8487947,True,8487945,789764352,1028339
|
||||
2026-07-28 04:05:06,8547969,True,8547969,789764352,1028339
|
||||
2026-07-28 04:06:06,8607993,True,8607992,789764352,1028339
|
||||
2026-07-28 04:07:06,8668018,True,8668017,789764352,1028339
|
||||
2026-07-28 04:08:06,8728040,True,8728040,789764352,1028339
|
||||
2026-07-28 04:09:07,8788059,True,8788057,789764352,1028339
|
||||
2026-07-28 04:10:07,8848075,True,8848073,789764352,1028339
|
||||
2026-07-28 04:11:07,8908092,True,8908090,789764352,1028339
|
||||
2026-07-28 04:12:07,8968110,True,8968108,789764352,1028339
|
||||
2026-07-28 04:13:07,9028132,True,9028132,789764352,1028339
|
||||
2026-07-28 04:14:07,9088155,True,9088153,789764352,1028339
|
||||
2026-07-28 04:15:07,9148175,True,9148174,789764352,1028339
|
||||
2026-07-28 04:16:07,9208198,True,9208195,789764352,1028339
|
||||
2026-07-28 04:17:07,9268217,True,9268215,789764352,1028339
|
||||
2026-07-28 04:18:07,9328235,True,9328233,789764352,1028339
|
||||
2026-07-28 04:19:07,9388256,True,9388256,789764352,1028339
|
||||
2026-07-28 04:20:07,9448276,True,9448274,789764352,1028339
|
||||
2026-07-28 04:21:07,9508295,True,9508293,789764352,1028339
|
||||
2026-07-28 04:22:07,9568317,True,9568316,789764352,1028339
|
||||
2026-07-28 04:23:07,9628343,True,9628343,789764352,1028339
|
||||
2026-07-28 04:24:07,9688364,True,9688362,789764352,1028339
|
||||
2026-07-28 04:25:07,9748382,True,9748379,789764352,1028339
|
||||
2026-07-28 04:26:07,9808397,True,9808395,789764352,1028339
|
||||
2026-07-28 04:27:07,9868412,True,9868410,789764352,1028339
|
||||
2026-07-28 04:28:07,9928428,True,9928426,789764352,1028339
|
||||
2026-07-28 04:29:07,9988442,True,9988440,789764352,1028339
|
||||
2026-07-28 04:30:07,10048458,True,10048456,789764352,1028339
|
||||
2026-07-28 04:31:07,10108475,True,10108473,789764352,1028339
|
||||
2026-07-28 04:32:07,10168490,True,10168488,789764352,1028339
|
||||
2026-07-28 04:33:07,10228506,True,10228504,789764352,1028339
|
||||
2026-07-28 04:34:07,10288522,True,10288520,789764352,1028339
|
||||
2026-07-28 04:35:07,10348545,True,10348545,789764352,1028339
|
||||
2026-07-28 04:36:07,10408568,True,10408566,789764352,1028339
|
||||
2026-07-28 04:37:07,10468588,True,10468586,789764352,1028339
|
||||
2026-07-28 04:38:07,10528606,True,10528604,789764352,1028339
|
||||
2026-07-28 04:39:07,10588623,True,10588621,789764352,1028339
|
||||
2026-07-28 04:40:07,10648642,True,10648641,789764352,1028339
|
||||
2026-07-28 04:41:07,10708667,True,10708667,789764352,1028339
|
||||
2026-07-28 04:42:07,10768686,True,10768684,789764352,1028339
|
||||
2026-07-28 04:43:07,10828711,True,10828710,789764352,1028339
|
||||
2026-07-28 04:44:07,10888733,True,10888730,789764352,1028339
|
||||
2026-07-28 04:45:07,10948755,True,10948754,789764352,1028339
|
||||
2026-07-28 04:46:07,11008776,True,11008774,789764352,1028339
|
||||
2026-07-28 04:47:07,11068798,True,11068798,789764352,1028339
|
||||
2026-07-28 04:48:07,11128823,True,11128821,789764352,1028339
|
||||
2026-07-28 04:49:07,11188847,True,11188847,789764352,1028339
|
||||
2026-07-28 04:50:07,11248870,True,11248868,789764352,1028339
|
||||
2026-07-28 04:51:07,11308890,True,11308888,789764352,1028339
|
||||
2026-07-28 04:52:07,11368912,True,11368910,789764352,1028339
|
||||
2026-07-28 04:53:07,11428935,True,11428934,789764352,1028339
|
||||
2026-07-28 04:54:07,11488961,True,11488959,789764352,1028339
|
||||
2026-07-28 04:55:07,11548978,True,11548976,789764352,1028339
|
||||
2026-07-28 04:56:07,11608993,True,11608991,789764352,1028339
|
||||
2026-07-28 04:57:07,11669013,True,11669011,789764352,1028339
|
||||
2026-07-28 04:58:07,11729031,True,11729030,789764352,1028339
|
||||
2026-07-28 04:59:07,11789060,True,11789060,789764352,1028339
|
||||
2026-07-28 05:00:08,11849083,True,11849081,789764352,1028339
|
||||
2026-07-28 05:01:08,11909100,True,11909098,789764352,1028339
|
||||
2026-07-28 05:02:08,11969117,True,11969114,789764352,1028339
|
||||
2026-07-28 05:03:08,12029135,True,12029133,789764352,1028339
|
||||
2026-07-28 05:04:08,12089154,True,12089152,789764352,1028339
|
||||
2026-07-28 05:05:08,12149172,True,12149170,789764352,1028339
|
||||
2026-07-28 05:06:08,12209191,True,12209189,789764352,1028339
|
||||
2026-07-28 05:07:08,12269215,True,12269215,789764352,1028339
|
||||
2026-07-28 05:08:08,12329245,True,12329245,789764352,1028339
|
||||
2026-07-28 05:09:08,12389273,True,12389273,789764352,1028339
|
||||
2026-07-28 05:10:08,12449292,True,12449290,789764352,1028339
|
||||
2026-07-28 05:11:08,12509311,True,12509309,789764352,1028339
|
||||
2026-07-28 05:12:08,12569337,True,12569337,789764352,1028339
|
||||
2026-07-28 05:13:08,12629364,True,12629364,789764352,1028339
|
||||
2026-07-28 05:14:08,12689386,True,12689384,789764352,1028339
|
||||
2026-07-28 05:15:08,12749405,True,12749403,789764352,1028339
|
||||
2026-07-28 05:16:08,12809427,True,12809427,789764352,1028339
|
||||
2026-07-28 05:17:08,12869455,True,12869455,789764352,1028339
|
||||
2026-07-28 05:18:08,12929478,True,12929476,789764352,1028339
|
||||
2026-07-28 05:19:08,12989502,True,12989502,789764352,1028339
|
||||
2026-07-28 05:20:08,13049528,True,13049526,789764352,1028339
|
||||
2026-07-28 05:21:08,13109545,True,13109542,789764352,1028339
|
||||
2026-07-28 05:22:08,13169562,True,13169560,789764352,1028339
|
||||
2026-07-28 05:23:08,13229578,True,13229576,789764352,1028339
|
||||
2026-07-28 05:24:08,13289595,True,13289593,789764352,1028339
|
||||
2026-07-28 05:25:08,13349611,True,13349609,789764352,1028339
|
||||
2026-07-28 05:26:08,13409629,True,13409629,789764352,1028339
|
||||
2026-07-28 05:27:08,13469651,True,13469649,789764352,1028339
|
||||
2026-07-28 05:28:08,13529673,True,13529673,789764352,1028339
|
||||
2026-07-28 05:29:08,13589702,True,13589701,789764352,1028339
|
||||
2026-07-28 05:30:08,13649725,True,13649723,789764352,1028339
|
||||
2026-07-28 05:31:08,13709741,True,13709740,789764352,1028339
|
||||
2026-07-28 05:32:08,13769765,True,13769763,789764352,1028339
|
||||
2026-07-28 05:33:08,13829783,True,13829781,789764352,1028339
|
||||
2026-07-28 05:34:08,13889802,True,13889800,789764352,1028339
|
||||
2026-07-28 05:35:08,13949825,True,13949825,789764352,1028339
|
||||
2026-07-28 05:36:08,14009845,True,14009843,789764352,1028339
|
||||
2026-07-28 05:37:08,14069859,True,14069857,789764352,1028339
|
||||
2026-07-28 05:38:08,14129878,True,14129876,789764352,1028339
|
||||
2026-07-28 05:39:08,14189894,True,14189891,789764352,1028339
|
||||
2026-07-28 05:40:08,14249915,True,14249913,789764352,1028339
|
||||
2026-07-28 05:41:08,14309933,True,14309931,789764352,1028339
|
||||
2026-07-28 05:42:08,14369958,True,14369958,789764352,1028339
|
||||
2026-07-28 05:43:08,14429982,True,14429982,789764352,1028339
|
||||
2026-07-28 05:44:08,14490000,True,14489998,789764352,1028339
|
||||
2026-07-28 05:45:08,14550017,True,14550015,789764352,1028339
|
||||
2026-07-28 05:46:08,14610035,True,14610033,789764352,1028339
|
||||
2026-07-28 05:47:08,14670056,True,14670056,789764352,1028339
|
||||
2026-07-28 05:48:09,14730086,True,14730085,789764352,1028339
|
||||
2026-07-28 05:49:09,14790110,True,14790109,789764352,1028339
|
||||
2026-07-28 05:50:09,14850133,True,14850133,789764352,1028339
|
||||
2026-07-28 05:51:09,14910155,True,14910153,789764352,1028339
|
||||
2026-07-28 05:52:09,14970174,True,14970172,789764352,1028339
|
||||
2026-07-28 05:53:09,15030193,True,15030191,789764352,1028339
|
||||
2026-07-28 05:54:09,15090216,True,15090216,789764352,1028339
|
||||
2026-07-28 05:55:09,15150245,True,15150245,789764352,1028339
|
||||
2026-07-28 05:56:09,15210267,True,15210265,789764352,1028339
|
||||
2026-07-28 05:57:09,15270285,True,15270282,789764352,1028339
|
||||
2026-07-28 05:58:09,15330308,True,15330308,789764352,1028339
|
||||
2026-07-28 05:59:09,15390329,True,15390327,789764352,1028339
|
||||
2026-07-28 06:00:09,15450348,True,15450348,789764352,1028339
|
||||
2026-07-28 06:01:09,15510376,True,15510376,789764352,1028339
|
||||
2026-07-28 06:02:09,15570397,True,15570395,789764352,1028339
|
||||
2026-07-28 06:03:09,15630422,True,15630421,789764352,1028339
|
||||
2026-07-28 06:04:09,15690443,True,15690441,789764352,1028339
|
||||
2026-07-28 06:05:09,15750461,True,15750459,789764352,1028339
|
||||
2026-07-28 06:06:09,15810489,True,15810488,789764352,1028339
|
||||
2026-07-28 06:07:09,15870512,True,15870510,789764352,1028339
|
||||
2026-07-28 06:08:09,15930533,True,15930533,789764352,1028339
|
||||
2026-07-28 06:09:09,15990556,True,15990554,789764352,1028339
|
||||
2026-07-28 06:10:09,16050574,True,16050572,789764352,1028339
|
||||
2026-07-28 06:11:09,16110587,True,16110585,789764352,1028339
|
||||
2026-07-28 06:12:09,16170604,True,16170604,789764352,1028339
|
||||
2026-07-28 06:13:09,16230627,True,16230627,789764352,1028339
|
||||
2026-07-28 06:14:09,16290650,True,16290648,789764352,1028339
|
||||
2026-07-28 06:15:09,16350673,True,16350672,789764352,1028339
|
||||
2026-07-28 06:16:09,16410698,True,16410696,789764352,1028339
|
||||
2026-07-28 06:17:09,16470717,True,16470715,789764352,1028339
|
||||
2026-07-28 06:18:09,16530735,True,16530733,789764352,1028339
|
||||
2026-07-28 06:19:09,16590757,True,16590757,789764352,1028339
|
||||
2026-07-28 06:20:09,16650780,True,16650778,789764352,1028339
|
||||
2026-07-28 06:21:09,16710798,True,16710798,789764352,1028339
|
||||
2026-07-28 06:22:09,16770825,True,16770824,789764352,1028339
|
||||
2026-07-28 06:23:09,16830844,True,16830842,789764352,1028339
|
||||
2026-07-28 06:24:09,16890861,True,16890859,789764352,1028339
|
||||
2026-07-28 06:25:09,16950878,True,16950875,789764352,1028339
|
||||
2026-07-28 06:26:09,17010896,True,17010894,789764352,1028339
|
||||
2026-07-28 06:27:09,17070912,True,17070910,789764352,1028339
|
||||
2026-07-28 06:28:09,17130929,True,17130927,789764352,1028339
|
||||
2026-07-28 06:29:09,17190947,True,17190945,789764352,1028339
|
||||
2026-07-28 06:30:09,17250966,True,17250964,789764352,1028339
|
||||
2026-07-28 06:31:09,17310985,True,17310983,789764352,1028339
|
||||
2026-07-28 06:32:09,17371003,True,17371001,789764352,1028339
|
||||
2026-07-28 06:33:09,17431023,True,17431021,789764352,1028339
|
||||
2026-07-28 06:34:09,17491047,True,17491046,789764352,1028339
|
||||
2026-07-28 06:35:09,17551074,True,17551074,789764352,1028339
|
||||
2026-07-28 06:36:10,17611098,True,17611096,789764352,1028339
|
||||
2026-07-28 06:37:10,17671122,True,17671122,789764352,1028339
|
||||
2026-07-28 06:38:10,17731145,True,17731143,789764352,1028339
|
||||
2026-07-28 06:39:10,17791173,True,17791172,789764352,1028339
|
||||
2026-07-28 06:40:10,17851193,True,17851192,789764352,1028339
|
||||
2026-07-28 06:41:10,17911221,True,17911221,789764352,1028339
|
||||
2026-07-28 06:42:10,17971243,True,17971241,789764352,1028339
|
||||
2026-07-28 06:43:10,18031261,True,18031258,789764352,1028339
|
||||
2026-07-28 06:44:10,18091285,True,18091285,789764352,1028339
|
||||
2026-07-28 06:45:10,18151306,True,18151304,789764352,1028339
|
||||
2026-07-28 06:46:10,18211322,True,18211320,789764352,1028339
|
||||
2026-07-28 06:47:10,18271342,True,18271340,789764352,1028339
|
||||
2026-07-28 06:48:10,18331360,True,18331358,789764352,1028339
|
||||
2026-07-28 06:49:10,18391383,True,18391383,789764352,1028339
|
||||
2026-07-28 06:50:10,18451405,True,18451403,789764352,1028339
|
||||
2026-07-28 06:51:10,18511423,True,18511421,789764352,1028339
|
||||
2026-07-28 06:52:10,18571443,True,18571442,789764352,1028339
|
||||
2026-07-28 06:53:10,18631472,True,18631472,789764352,1028339
|
||||
2026-07-28 06:54:10,18691494,True,18691492,789764352,1028339
|
||||
2026-07-28 06:55:10,18751520,True,18751520,789764352,1028339
|
||||
2026-07-28 06:56:10,18811545,True,18811545,789764352,1028339
|
||||
2026-07-28 06:57:10,18871568,True,18871566,789764352,1028339
|
||||
2026-07-28 06:58:10,18931586,True,18931584,789764352,1028339
|
||||
2026-07-28 06:59:10,18991609,True,18991608,789764352,1028339
|
||||
2026-07-28 07:00:10,19051633,True,19051632,789764352,1028339
|
||||
2026-07-28 07:01:10,19111652,True,19111649,789764352,1028339
|
||||
2026-07-28 07:02:10,19171669,True,19171667,789764352,1028339
|
||||
2026-07-28 07:03:10,19231688,True,19231686,789764352,1028339
|
||||
2026-07-28 07:04:10,19291705,True,19291703,789764352,1028339
|
||||
2026-07-28 07:05:10,19351730,True,19351730,789764352,1028339
|
||||
2026-07-28 07:06:10,19411758,True,19411758,789764352,1028339
|
||||
2026-07-28 07:07:10,19471781,True,19471779,789764352,1028339
|
||||
2026-07-28 07:08:10,19531799,True,19531797,789764352,1028339
|
||||
2026-07-28 07:09:10,19591815,True,19591815,789764352,1028339
|
||||
2026-07-28 07:10:10,19651838,True,19651837,789764352,1028339
|
||||
2026-07-28 07:11:10,19711862,True,19711862,789764352,1028339
|
||||
2026-07-28 07:12:10,19771883,True,19771881,789764352,1028339
|
||||
|
15
scripts/tc-ads-mismatch-delta.ps1
Normal file
15
scripts/tc-ads-mismatch-delta.ps1
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#Requires -RunAsAdministrator
|
||||
Add-Type -Path 'C:\Program Files (x86)\Beckhoff\TwinCAT\3.1\Components\Base\v170\TwinCAT.Ads.dll'
|
||||
$c = New-Object TwinCAT.Ads.TcAdsClient
|
||||
$c.Connect('169.254.176.217.1.1', 851)
|
||||
$h = $c.CreateVariableHandle('GVL_Sync.nMismatch')
|
||||
$h2 = $c.CreateVariableHandle('GVL_Sync.bSync')
|
||||
$m1 = $c.ReadAny($h, [int]); $b1 = $c.ReadAny($h2, [bool])
|
||||
Write-Host ("t+15s : bSync=$b1 nMismatch=$m1")
|
||||
Start-Sleep 30
|
||||
$m2 = $c.ReadAny($h, [int]); $b2 = $c.ReadAny($h2, [bool])
|
||||
Write-Host ("t+45s : bSync=$b2 nMismatch=$m2 delta=$($m2-$m1)")
|
||||
Start-Sleep 30
|
||||
$m3 = $c.ReadAny($h, [int]); $b3 = $c.ReadAny($h2, [bool])
|
||||
Write-Host ("t+75s : bSync=$b3 nMismatch=$m3 delta=$($m3-$m2)")
|
||||
$c.Dispose()
|
||||
48
scripts/tc-ads-verify-800b.ps1
Normal file
48
scripts/tc-ads-verify-800b.ps1
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#Requires -RunAsAdministrator
|
||||
#Requires -Version 5.1
|
||||
$ErrorActionPreference = 'Continue'
|
||||
$adsDll = 'C:\Program Files (x86)\Beckhoff\TwinCAT\3.1\Components\Base\v170\TwinCAT.Ads.dll'
|
||||
Add-Type -Path $adsDll -ErrorAction Stop
|
||||
$c = New-Object TwinCAT.Ads.TcAdsClient
|
||||
$c.Connect('169.254.176.217.1.1', 851)
|
||||
function ReadSym($name, $type) {
|
||||
$h = $c.CreateVariableHandle($name)
|
||||
$v = $c.ReadAny($h, $type)
|
||||
$c.DeleteVariableHandle($h)
|
||||
return $v
|
||||
}
|
||||
function ReadBytes($name, $len) {
|
||||
$h = $c.CreateVariableHandle($name)
|
||||
$arr = $c.ReadAny($h, [byte[]], @($len))
|
||||
$c.DeleteVariableHandle($h)
|
||||
return $arr
|
||||
}
|
||||
$nc = ReadSym 'GVL_Sync.nCycles' ([uint64])
|
||||
$bs = ReadSym 'GVL_Sync.bSync' ([bool])
|
||||
$nrs = ReadSym 'GVL_Sync.nReturnedSeq' ([uint64])
|
||||
$nm = ReadSym 'GVL_Sync.nMismatch' ([int])
|
||||
$in = ReadBytes 'GVL_Sync.aIn1' 800
|
||||
$out = ReadBytes 'GVL_Sync.aOut1' 800
|
||||
|
||||
$nzIn = ($in | Where-Object { $_ -ne 0 }).Count
|
||||
$nzOut = ($out | Where-Object { $_ -ne 0 }).Count
|
||||
Write-Host ("nCycles={0} bSync={1} nReturnedSeq={2} lag={3} nMismatch={4}" -f $nc, $bs, $nrs, ($nc - $nrs), $nm)
|
||||
Write-Host ("aIn1 nonzero = {0}/800" -f $nzIn)
|
||||
Write-Host ("aOut1 nonzero = {0}/800" -f $nzOut)
|
||||
|
||||
# per-byte pattern check against nReturnedSeq: expected[i] = (nReturnedSeq + i) mod 256, pattern region
|
||||
$bad = 0
|
||||
$badIdx = @()
|
||||
for ($i = 16; $i -lt 800; $i++) {
|
||||
if ($i -ge 264 -and $i -le 279) { continue }
|
||||
$exp = [byte](($nrs + $i) % 256)
|
||||
if ($in[$i] -ne $exp) { $bad++; if ($badIdx.Count -lt 8) { $badIdx += $i } }
|
||||
}
|
||||
Write-Host ("pattern[16..799 excl 264..279] mismatches = {0} {1}" -f $bad, $(if ($badIdx.Count) { 'at ' + ($badIdx -join ',') } else { '' }))
|
||||
|
||||
# show window samples at several offsets
|
||||
foreach ($off in @(0, 16, 128, 256, 288, 512, 768)) {
|
||||
$seg = [BitConverter]::ToString($in[$off..($off + 7)])
|
||||
Write-Host ("aIn1[{0,3}..{1,3}] = {2}" -f $off, ($off + 7), $seg)
|
||||
}
|
||||
$c.Dispose()
|
||||
61
scripts/tc-deploy-retry-800b.ps1
Normal file
61
scripts/tc-deploy-retry-800b.ps1
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#Requires -RunAsAdministrator
|
||||
#Requires -Version 5.1
|
||||
$ErrorActionPreference = 'Continue'
|
||||
|
||||
function Invoke-Com {
|
||||
param([scriptblock]$Fn, [int]$Retries = 30, [int]$DelayMs = 2000)
|
||||
for ($i = 0; $i -lt $Retries; $i++) {
|
||||
try { return & $Fn } catch {
|
||||
$hr = $_.Exception.HResult
|
||||
if ($hr -eq -2147418111) { Start-Sleep -Milliseconds $DelayMs; continue }
|
||||
throw
|
||||
}
|
||||
}
|
||||
throw "COM call rejected $Retries times (RPC_E_CALL_REJECTED)"
|
||||
}
|
||||
|
||||
Write-Host "=== Deploy 8B with RPC retry ==="
|
||||
$dte = Invoke-Com { New-Object -ComObject TcXaeShell.DTE.17.0 }
|
||||
Invoke-Com { $dte.MainWindow.Visible = $true } | Out-Null
|
||||
try { Invoke-Com { $dte.SuppressUI = $false } | Out-Null } catch {}
|
||||
Invoke-Com { $dte.Solution.Open('C:\Users\tonycao\work\twincat3-auto-cli\TwinCAT_EL6695_Primary_800B\TwinCATProject1.sln') } | Out-Null
|
||||
Write-Host "solution opened"
|
||||
|
||||
$sm = $null
|
||||
for ($i = 0; $i -lt 40; $i++) {
|
||||
try { $sm = Invoke-Com { $dte.Solution.Projects.Item(1).Object } -Retries 3 -DelayMs 3000; if ($sm) { break } } catch { Write-Host " waiting sysmgr..." }
|
||||
}
|
||||
if (-not $sm) { Write-Host "FATAL: no sysmgr"; exit 1 }
|
||||
Write-Host "sysmgr OK"
|
||||
Invoke-Com { $sm.SetTargetNetId('169.254.176.217.1.1') } | Out-Null
|
||||
|
||||
Write-Host "building..."
|
||||
try { Invoke-Com { $dte.ExecuteCommand('Build.BuildSolution') } -Retries 10 | Out-Null } catch { Write-Host "build cmd: $_" }
|
||||
# wait for build done (BuildState 3 = done)
|
||||
$done = $false
|
||||
for ($i = 0; $i -lt 90; $i++) {
|
||||
try {
|
||||
$bs = Invoke-Com { $dte.Solution.SolutionBuild.BuildState } -Retries 5 -DelayMs 3000
|
||||
$bi = Invoke-Com { $dte.Solution.SolutionBuild.LastBuildInfo } -Retries 5 -DelayMs 1000
|
||||
if ($bs -eq 3) { Write-Host "build done (LastBuildInfo=$bi) after $($i*2)s"; $done = $true; break }
|
||||
} catch { Write-Host " build poll err: $_" }
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
if (-not $done) { Write-Host "WARN: build state never reached done" }
|
||||
|
||||
# dump build errors if any
|
||||
try {
|
||||
$ew = $dte.ToolWindows.ErrorList
|
||||
Write-Host "error list check skipped"
|
||||
} catch {}
|
||||
|
||||
Write-Host "activating..."
|
||||
Invoke-Com { $sm.ActivateConfiguration() } -Retries 30 -DelayMs 3000 | Out-Null
|
||||
Write-Host "activated"
|
||||
Start-Sleep 10
|
||||
Write-Host "restarting runtime..."
|
||||
Invoke-Com { $sm.StartRestartTwinCAT() } -Retries 30 -DelayMs 3000 | Out-Null
|
||||
Write-Host "restart issued"
|
||||
Start-Sleep 12
|
||||
try { Write-Host "IsTwinCATStarted=$($sm.IsTwinCATStarted)" } catch {}
|
||||
Write-Host "=== done ==="
|
||||
30
scripts/tc-monitor-5h.ps1
Normal file
30
scripts/tc-monitor-5h.ps1
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#Requires -RunAsAdministrator
|
||||
# 5-hour stability monitor: logs PLC sync metrics to CSV every 60s.
|
||||
$ErrorActionPreference = 'Continue'
|
||||
Add-Type -Path 'C:\Program Files (x86)\Beckhoff\TwinCAT\3.1\Components\Base\v170\TwinCAT.Ads.dll'
|
||||
$logFile = 'C:\Users\tonycao\work\ethercat-linux\monitor_5h.csv'
|
||||
'timestamp,nCycles,bSync,nReturnedSeq,nMismatch,nProcMismatch' | Out-File $logFile -Encoding utf8
|
||||
$start = Get-Date
|
||||
for ($i = 0; $i -lt 300; $i++) {
|
||||
try {
|
||||
$c = New-Object TwinCAT.Ads.TcAdsClient
|
||||
$c.Connect('169.254.176.217.1.1', 851)
|
||||
$h1 = $c.CreateVariableHandle('GVL_Sync.nCycles')
|
||||
$h2 = $c.CreateVariableHandle('GVL_Sync.bSync')
|
||||
$h3 = $c.CreateVariableHandle('GVL_Sync.nReturnedSeq')
|
||||
$h4 = $c.CreateVariableHandle('GVL_Sync.nMismatch')
|
||||
$h5 = $c.CreateVariableHandle('GVL_Sync.nProcMismatch')
|
||||
$nc = $c.ReadAny($h1, [uint64])
|
||||
$bs = $c.ReadAny($h2, [bool])
|
||||
$nrs = $c.ReadAny($h3, [uint64])
|
||||
$nm = $c.ReadAny($h4, [int])
|
||||
$npm = $c.ReadAny($h5, [uint32])
|
||||
$c.Dispose()
|
||||
$ts = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
|
||||
"$ts,$nc,$bs,$nrs,$nm,$npm" | Out-File $logFile -Append -Encoding utf8
|
||||
} catch {
|
||||
$ts = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
|
||||
"$ts,ERROR,,,," | Out-File $logFile -Append -Encoding utf8
|
||||
}
|
||||
Start-Sleep -Seconds 60
|
||||
}
|
||||
62
scripts/tc-relink-800b.ps1
Normal file
62
scripts/tc-relink-800b.ps1
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#Requires -RunAsAdministrator
|
||||
$ErrorActionPreference = "Continue"
|
||||
$dte = New-Object -ComObject TcXaeShell.DTE.17.0
|
||||
$dte.MainWindow.Visible = $true
|
||||
try { $dte.SuppressUI = $false } catch {}
|
||||
$dte.Solution.Open("C:\Users\tonycao\work\twincat3-auto-cli\TwinCAT_EL6695_Primary_800B\TwinCATProject1.sln")
|
||||
Start-Sleep 20
|
||||
$sm = $null
|
||||
for ($i = 0; $i -lt 20; $i++) {
|
||||
try { $sm = $dte.Solution.Projects.Item(1).Object; if ($sm) { break } } catch {}
|
||||
Start-Sleep 3
|
||||
}
|
||||
if (-not $sm) { Write-Host "no sysmgr"; exit 1 }
|
||||
try { $sm.SetTargetNetId("169.254.176.217.1.1") } catch {}
|
||||
Start-Sleep 2
|
||||
|
||||
$box = "TIID^设备 1 (EtherCAT)^模块 3 (EK1100)^模块 10 (EL6695)"
|
||||
$cands = @(
|
||||
"$box^IO Outputs^IO Outputs",
|
||||
"$box^IO Outputs^IO Outputs[0]",
|
||||
"$box^IO Inputs^IO Inputs",
|
||||
"$box^IO Inputs^IO Inputs[0]"
|
||||
)
|
||||
foreach ($c in $cands) {
|
||||
$it = $null
|
||||
try { $it = $sm.TryLookupTreeItem($c) } catch { Write-Host "err $c : $_" }
|
||||
if ($it) {
|
||||
$sz = ""
|
||||
try { $sz = $it.BitSize } catch {}
|
||||
Write-Host "OK: $c name=$($it.Name) type=$($it.ItemType) bitsize=$sz"
|
||||
} else {
|
||||
Write-Host "MISS: $c"
|
||||
}
|
||||
}
|
||||
|
||||
$varAin = "TIPC^PlcSync^PlcSync Instance^PlcTask Inputs^GVL_Sync.aIn1"
|
||||
$varAout = "TIPC^PlcSync^PlcSync Instance^PlcTask Outputs^GVL_Sync.aOut1"
|
||||
foreach ($v in @($varAin, $varAout)) {
|
||||
$it = $null
|
||||
try { $it = $sm.TryLookupTreeItem($v) } catch {}
|
||||
if ($it) { Write-Host "PLC OK: $v" } else { Write-Host "PLC MISS: $v" }
|
||||
}
|
||||
|
||||
Write-Host "--- unlink existing ---"
|
||||
try { $sm.UnlinkVariables($varAin, "$box^IO Inputs^IO Inputs") ; Write-Host "unlinked aIn1" } catch { Write-Host "unlink aIn1: $_" }
|
||||
try { $sm.UnlinkVariables($varAout, "$box^IO Outputs^IO Outputs"); Write-Host "unlinked aOut1" } catch { Write-Host "unlink aOut1: $_" }
|
||||
|
||||
Write-Host "--- link whole arrays ---"
|
||||
try { $sm.LinkVariables($varAin, "$box^IO Inputs^IO Inputs"); Write-Host "linked aIn1" } catch { Write-Host "link aIn1: $_" }
|
||||
try { $sm.LinkVariables($varAout, "$box^IO Outputs^IO Outputs"); Write-Host "linked aOut1" } catch { Write-Host "link aOut1: $_" }
|
||||
|
||||
$xml = $sm.ProduceMappingInfo()
|
||||
[System.IO.File]::WriteAllText("C:\Users\tonycao\work\ethercat-linux\tmp_mapping2.xml", $xml, [System.Text.Encoding]::UTF8)
|
||||
Write-Host "mapping saved"
|
||||
|
||||
Write-Host "--- save + activate + restart ---"
|
||||
try { $dte.Solution.SaveAll(); Write-Host "saved" } catch { Write-Host "save: $_" }
|
||||
try { $sm.ActivateConfiguration(); Write-Host "activated" } catch { Write-Host "activate: $_" }
|
||||
Start-Sleep 10
|
||||
try { $sm.StartRestartTwinCAT(); Write-Host "restart issued" } catch { Write-Host "restart: $_" }
|
||||
Start-Sleep 10
|
||||
Write-Host "done"
|
||||
|
|
@ -38,18 +38,35 @@ pub fn twin_layout_blob(obj: u16) -> Vec<u8> {
|
|||
/// Size-parameterised TwinCAT line-format blob.
|
||||
///
|
||||
/// For payloads of 1024 bytes this is byte-identical to `twin_layout_blob`.
|
||||
/// For small payloads (<= 30 bytes, fitting one 240-bit entry) a single
|
||||
/// entry references the real object at the exact bit length.
|
||||
/// For payloads up to 240 bits a single entry references the real object at
|
||||
/// the exact bit length. Larger payloads use the TwinCAT line format:
|
||||
/// 1 real entry @240bit + continuation entries @240bit + 1 continuation
|
||||
/// entry at the remainder bit length.
|
||||
pub fn twin_layout_blob_sized(obj: u16, payload_bytes: usize) -> Vec<u8> {
|
||||
if payload_bytes == 1024 {
|
||||
return twin_layout_blob(obj);
|
||||
}
|
||||
let bits = (payload_bytes * 8).min(240) as u8;
|
||||
let total_bits = payload_bytes * 8;
|
||||
let idx_lo = (obj & 0xFF) as u8;
|
||||
let idx_hi = (obj >> 8) as u8;
|
||||
if total_bits <= 240 {
|
||||
let mut blob = Vec::with_capacity(6);
|
||||
blob.extend_from_slice(&1u16.to_le_bytes());
|
||||
blob.extend_from_slice(&[bits, 1, idx_lo, idx_hi]);
|
||||
blob.extend_from_slice(&[total_bits as u8, 1, idx_lo, idx_hi]);
|
||||
return blob;
|
||||
}
|
||||
let full = total_bits / 240;
|
||||
let rem = (total_bits % 240) as u8;
|
||||
let n = if rem > 0 { full + 1 } else { full };
|
||||
let mut blob = Vec::with_capacity(2 + n * 4);
|
||||
blob.extend_from_slice(&(n as u16).to_le_bytes());
|
||||
blob.extend_from_slice(&[240, 1, idx_lo, idx_hi]);
|
||||
for _ in 1..full {
|
||||
blob.extend_from_slice(&[240, 0, 0, 0]);
|
||||
}
|
||||
if rem > 0 {
|
||||
blob.extend_from_slice(&[rem, 0, 0, 0]);
|
||||
}
|
||||
blob
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,15 +31,15 @@ const PDI_LEN: usize = 3072;
|
|||
|
||||
// Secondary side SM layout (ESI-defined process data SMs)
|
||||
const SM_TX_ADDR: u16 = 0x1C00; // SM2: outputs (J1900 writes data to TwinCAT)
|
||||
const SM_TX_LEN: usize = 8;
|
||||
const SM_TX_LEN: usize = 800;
|
||||
const SM_RX_ADDR: u16 = 0x8E00; // SM3: inputs (J1900 reads data from TwinCAT)
|
||||
// Full PDO: 2B diagnostic word + 8B payload (single-entry twin_layout blob
|
||||
// expands 0x6000:01 to 8 bytes).
|
||||
const SM_RX_LEN: usize = 8; // SM3 buffer (no diag word, pure 8B payload)
|
||||
const SM_RX_PLD_LEN: usize = 8; // actual payload after stripping diagnostic word
|
||||
const SM_RX_LEN: usize = 800; // SM3 buffer (no diag word, pure 8B payload)
|
||||
const SM_RX_PLD_LEN: usize = 800; // actual payload after stripping diagnostic word
|
||||
const RX_PREFIX: usize = 0; // no diag word prefix (0x1C13=[0x1A08] only)
|
||||
|
||||
const PAYLOAD_LEN: usize = 8;
|
||||
const PAYLOAD_LEN: usize = 800;
|
||||
|
||||
/// Abort after this many consecutive cycles with a TX or RX error.
|
||||
const MAX_ERR_STREAK: u64 = 1000;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user