ethercat-linux/scripts/tc-check-state.ps1
Tony Cao 309aaba342 EL6695 8-byte bidirectional exchange with per-byte verification
- 8B PDO config: ULINT-sized payload, no 0x1A01 diag PDO on SM3
  (device rejected SM3=8 with diag assigned: 'size not allowed, min/max 0xa')
- twin_layout_blob_sized(): single 64-bit mapping entry for 8B payloads
- Ticker: per-byte XOR 0x5A transform in 8B mode so TwinCAT can verify
  every byte individually (1KB path unchanged, const-guarded)
- TwinCAT automation scripts: deploy with RPC retry, LinkVariables-based
  whole-array relink (element links only carry 1 byte), ADS watch, diag
- Docs: 8B design, verification methodology, test report
2026-07-27 19:01:05 +08:00

187 lines
6.7 KiB
PowerShell

#Requires -RunAsAdministrator
#Requires -Version 5.1
[CmdletBinding()]
param(
[string]$Solution = $null
)
$ErrorActionPreference = 'Continue'
. "$PSScriptRoot\tc-common.ps1"
if (-not $Solution) { $Solution = $script:DefaultSolution }
New-Log $script:DefaultLogDir
$LogFile = Join-Path $script:DefaultLogDir "check-state.log"
function Write-Log($Message) {
$line = "[{0}] {1}" -f (Get-Date -Format 'HH:mm:ss'), $Message
Write-Host $line
Add-Content -Path $LogFile -Value $line -Encoding UTF8
}
# Load TwinCAT.Ads
$adsDll = 'C:\Program Files (x86)\Beckhoff\TwinCAT\3.1\Components\Base\v170\TwinCAT.Ads.dll'
try {
Add-Type -Path $adsDll -ErrorAction Stop
Write-Log "TwinCAT.Ads loaded from $adsDll"
} catch {
Write-Log "FATAL: Cannot load TwinCAT.Ads: $_"
exit 1
}
# Helper to bind to running XAE DTE via ROT
function Get-XaeDte {
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
public class XaeRot {
[DllImport("ole32.dll")] static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable pprot);
[DllImport("ole32.dll")] static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);
public static object GetDte(string match) {
IRunningObjectTable rot; IBindCtx bc;
GetRunningObjectTable(0, out rot);
CreateBindCtx(0, out bc);
IEnumMoniker em; rot.EnumRunning(out em);
IMoniker[] mons = new IMoniker[1];
IntPtr fetched = IntPtr.Zero;
while (em.Next(1, mons, fetched) == 0) {
string name; mons[0].GetDisplayName(bc, null, out name);
if (name.IndexOf(match, StringComparison.OrdinalIgnoreCase) >= 0) {
object o; rot.GetObject(mons[0], out o);
return o;
}
}
return null;
}
}
'@ -ReferencedAssemblies System.Runtime.InteropServices
return [XaeRot]::GetDte('TcXaeShell.DTE')
}
function Read-Ads($NetId, $Port, $IGrp, $IOff, $Len) {
$c = New-Object TwinCAT.Ads.TcAdsClient
try {
$c.Connect($NetId, $Port)
$buf = New-Object byte[] $Len
$n = $c.Read([uint32]$IGrp, [uint32]$IOff, $buf, 0, $Len)
$hex = [BitConverter]::ToString($buf, 0, $n)
return "OK n=$n : $hex"
} catch {
return "ERR: $($_.Exception.Message)"
} finally {
$c.Dispose()
}
}
Write-Log "=== TwinCAT State Check ==="
# Try to bind to running XAE DTE
$dte = Get-XaeDte
if (-not $dte) {
Write-Log "No running XAE DTE found. Creating a new one..."
try {
$dte = New-Object -ComObject TcXaeShell.DTE.17.0 -ErrorAction Stop
$dte.MainWindow.Visible = $true
} catch {
Write-Log "FATAL: Cannot create DTE: $_"
exit 1
}
}
if (-not $dte.Solution.IsOpen) {
Write-Log "Opening solution $Solution"
try {
$dte.Solution.Open($Solution)
for ($i = 1; $i -le 120; $i++) {
Start-Sleep -Seconds 1
if ($dte.Solution.IsOpen) { break }
}
} catch {
Write-Log "Solution.Open error: $_"
}
}
Write-Log "Solution open: $($dte.Solution.IsOpen)"
Write-Log "Solution path: $($dte.Solution.FullName)"
$sysMgr = $null
for ($i = 1; $i -le 40; $i++) {
try {
$sysMgr = $dte.Solution.Projects.Item(1).Object
if ($sysMgr) { break }
} catch {}
Start-Sleep -Seconds 2
}
if (-not $sysMgr) {
Write-Log "FATAL: Cannot get SysManager"
exit 1
}
Write-Log "SysManager obtained"
$targetNetId = '169.254.176.217.1.1'
$platform = 'TwinCAT RT (x64)'
try { $sysMgr.SetTargetNetId($targetNetId); Write-Log "SetTargetNetId $targetNetId OK" } catch { Write-Log "SetTargetNetId error: $_" }
try { $sysMgr.ConfigurationManager.ActiveTargetPlatform = $platform; Write-Log "ActiveTargetPlatform set to $platform" } catch { Write-Log "Set platform error: $_" }
Start-Sleep -Seconds 3
# Read state before activation
Write-Log "--- State BEFORE activation ---"
try { Write-Log "IsTwinCATStarted = $($sysMgr.IsTwinCATStarted)" } catch { Write-Log "IsTwinCATStarted error: $_" }
try { Write-Log "CurrentMode = $($sysMgr.CurrentMode)" } catch { Write-Log "CurrentMode error: $_" }
try { Write-Log "TargetNetId = $($sysMgr.ConfigurationManager.ActiveConfiguration.TargetNetId)" } catch { Write-Log "TargetNetId error: $_" }
try { Write-Log "ActivePlatform = $($sysMgr.ConfigurationManager.ActiveTargetPlatform)" } catch { Write-Log "ActivePlatform error: $_" }
# Activate
Write-Log "Activating configuration..."
try { $sysMgr.ActivateConfiguration(); Write-Log "ActivateConfiguration OK" } catch { Write-Log "ActivateConfiguration error: $_" }
Start-Sleep -Seconds 5
# Restart runtime to Run mode
Write-Log "Restarting TwinCAT runtime..."
try { $sysMgr.StartRestartTwinCAT(); Write-Log "StartRestartTwinCAT OK" } catch { Write-Log "StartRestartTwinCAT error: $_" }
Start-Sleep -Seconds 10
# Read state after restart
Write-Log "--- State AFTER activation/restart ---"
try { Write-Log "IsTwinCATStarted = $($sysMgr.IsTwinCATStarted)" } catch { Write-Log "IsTwinCATStarted error: $_" }
try { Write-Log "CurrentMode = $($sysMgr.CurrentMode)" } catch { Write-Log "CurrentMode error: $_" }
try { $msgs = $sysMgr.GetLastErrorMessages(); Write-Log "LastErrorMessages = $msgs" } catch { Write-Log "GetLastErrorMessages error: $_" }
# ADS diagnostics
Write-Log "--- ADS diagnostics ---"
Write-Log "System ADS state (169.254.176.217.1.1, port 65535, iGrp 0x0, iOff 0, 4 bytes): $(Read-Ads '169.254.176.217.1.1' 65535 0 0 4)"
Write-Log "EtherCAT master 1 state (169.254.176.217.2.1, port 65535, iGrp 0x9, iOff 0, 32 bytes): $(Read-Ads '169.254.176.217.2.1' 65535 0x9 0 32)"
# Try to export EtherCAT master online XML
try {
$io = $sysMgr.LookupTreeItem('TIID')
$ecat = $null
for ($j = 1; $j -le [int]$io.ChildCount; $j++) {
try {
$ch = $io.Child($j)
if ([int]$ch.ItemSubType -eq 111) { $ecat = $ch; break }
} catch {}
}
if ($ecat) {
Write-Log "EtherCAT master found: $($ecat.Name)"
$xml = $ecat.ProduceXml($true)
$xmlFile = Join-Path $script:DefaultLogDir 'check-state_master.xml'
[System.IO.File]::WriteAllText($xmlFile, $xml, [System.Text.Encoding]::UTF8)
Write-Log "Master Online XML saved: $xmlFile ($($xml.Length) bytes)"
Write-Log "Enumerating configured boxes under master:"
for ($j = 1; $j -le [int]$ecat.ChildCount; $j++) {
try {
$b = $ecat.Child($j)
Write-Log " Box[$j]: name='$($b.Name)' subtype=$($b.ItemSubType)"
} catch {}
}
} else {
Write-Log "No EtherCAT master found under TIID"
}
} catch {
Write-Log "EtherCAT XML error: $_"
}
Write-Log "=== Check complete ==="