ethercat-linux/scripts/tc-deploy-retry-4khz.ps1
Tony Cao 8c1f519526 Async pipelined FPWR + 4kHz: exec 245us->24us, RTT 2ms->1.25-1.5ms
- FPWR fire-and-forget: two alternating leaked tx slots, or()-driven
  20us kick to reach sendable, poll_once reap after next spin-detect
  (late=0 over 350k cycles). Fixes: reap placement, poll_once kick
- exec drops to 24us mean, freeing budget for 4kHz (250us) operation
- 4kHz verified: TwinCAT PLC at 4001.8Hz, lag 5-6 cycles
  (RTT 1.25-1.5ms); J1900 effective 2.9kHz - FPRD poll cost (71us x N)
  exceeds 250us budget, occasional frame miss
- Conclusion: J1900 write wait never contributed to lag; the 4-stage
  pipeline is TwinCAT IO mapping + bridge forwarding
2026-07-28 01:18:05 +08:00

62 lines
2.4 KiB
PowerShell

#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_4kHz\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 ==="