Files
chuan 2fdcf7a6d0 feat!: 添加快速串口仿真并精简运行代码
- 增加可选快速串口模式,缩短虚拟串口和 UART 接收耗时并保留 DMA、组帧与固件回执
- 增加 just stop 和虚拟串口归属记录,支持正常退出及残留端口清理
- 修正 PowerShell 脚本编码,保留升级大帧传输所需的驱动节流
- 补充 Flash 编程并行度寄存器读写,避免固件升级产生未处理位警告
- 修正 Monitor 运行错误处理及 UART 接收队列访问的锁保护
- 删除测试目录、专用客户端与测试运行分支,清理 Web 未引用资源和依赖
- 更新快速串口配置及启动、退出说明
- BREAKING CHANGE: 移除 just test 及其测试选项,项目仅保留运行和环境管理命令
2026-10-20 10:58:07 +08:00

94 lines
4.2 KiB
PowerShell

param(
[Parameter(Mandatory = $true)][string]$ComPort,
[int]$TcpPort,
[string]$StateDirectory,
[Parameter(Mandatory = $true)][string]$OwnershipFile,
[switch]$Cleanup,
[switch]$Fast
)
# Run in 32-bit Windows PowerShell: the installed virtual-port ActiveX is x86.
$ErrorActionPreference = 'Stop'
[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
function Remove-OwnedPort {
param($Port)
if (-not (Test-Path -LiteralPath $OwnershipFile)) { return }
$owner = Get-Content -LiteralPath $OwnershipFile -Raw -Encoding UTF8 | ConvertFrom-Json
if ($owner.com_port -ne $ComPort) { throw 'Virtual COM ownership record does not match the requested port' }
if ($owner.pid -ne $PID) {
$process = Get-CimInstance Win32_Process -Filter "ProcessId=$([int]$owner.pid)"
if ($process -and $process.CommandLine -like "*$OwnershipFile*") {
throw "$ComPort bridge is still running (PID $($owner.pid)); stop its Renode instance first"
}
}
if ([IO.Ports.SerialPort]::GetPortNames() -contains $ComPort) {
if (-not $Port.IsCreated -and -not $Port.Attach($ComPort)) { throw "Cannot attach owned port $ComPort" }
if ($Port.IsOpened) { throw "$ComPort is still open in another application; close that application and run just stop again" }
if (-not $Port.Delete()) { throw "Cannot remove owned port $ComPort" }
$deadline = [DateTime]::UtcNow.AddSeconds(3)
while ([IO.Ports.SerialPort]::GetPortNames() -contains $ComPort) {
if ([DateTime]::UtcNow -ge $deadline) { throw "$ComPort device removal has not completed; run just stop again" }
Start-Sleep -Milliseconds 100
}
}
Remove-Item -LiteralPath $OwnershipFile
}
$vsp = New-Object -ComObject VSPort.VSPortAx
$vsp.DeleteOnExit = $false
$client = New-Object Net.Sockets.TcpClient
$created = $false
try {
if ($Cleanup) {
Remove-OwnedPort $vsp
return
}
if ([IO.Ports.SerialPort]::GetPortNames() -contains $ComPort) {
throw "$ComPort already exists; choose an unused virtual port"
}
$created = $vsp.CreatePort($ComPort)
if (-not $created) { throw "Cannot create $ComPort" }
# 归属记录独立于 run.json,终端中断导致驱动设备残留时仍可恢复清理
@{ com_port = $ComPort; pid = $PID } | ConvertTo-Json -Compress |
Set-Content -LiteralPath $OwnershipFile -Encoding UTF8
$vsp.DeleteOnExit = $true
# 驱动关闭限速时会截断超过 8192 字节的写入,升级帧最大为 8206 字节,必须保留节流
if (-not $vsp.SetStrictBaudrate($true)) { throw 'Cannot enable baud-rate emulation' }
$client.NoDelay = $true
$client.Connect('127.0.0.1', $TcpPort)
$stream = $client.GetStream()
$vsp.SetCTS($true) | Out-Null
$vsp.SetDSR($true) | Out-Null
$vsp.SetDCD($true) | Out-Null
$buffer = New-Object byte[] 65536
[IO.File]::WriteAllText((Join-Path $StateDirectory 'ready'), $ComPort)
while (-not (Test-Path -LiteralPath (Join-Path $StateDirectory 'stop'))) {
# Drain all available driver bytes; no fixed 8000-byte application buffer.
# 快速模式只提高虚拟驱动的模拟速率,仍保留节流以完整传输超过 8192 字节的帧
if ($Fast -and $vsp.IsOpened -and $vsp.Baudrate -ne 3000000) { $vsp.Baudrate = 3000000 }
$count = $vsp.InCount
if ($count -gt 0) {
[byte[]]$incoming = $vsp.ReadArray($count)
$stream.Write($incoming, 0, $incoming.Length)
}
if ($client.Available -gt 0) {
$count = $stream.Read($buffer, 0, [Math]::Min($client.Available, $buffer.Length))
[byte[]]$outgoing = New-Object byte[] $count
[Array]::Copy($buffer, $outgoing, $count)
$written = $vsp.WriteArray($outgoing)
if ($written -ne $count) { throw "Incomplete virtual-port response: $written/$count bytes" }
} elseif ($client.Client.Poll(0, [Net.Sockets.SelectMode]::SelectRead)) {
break
}
Start-Sleep -Milliseconds 1
}
} finally {
try {
$client.Close()
if ($created) { Remove-OwnedPort $vsp }
} finally {
[Runtime.InteropServices.Marshal]::FinalReleaseComObject($vsp) | Out-Null
}
}