开启了192k 所有RAM
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
<#
|
||||
run_boot_test.ps1 - Full automated boot-log capture + verify in one call.
|
||||
|
||||
Orchestrates:
|
||||
1. serial_capture.ps1 (with -FlashCmd): stable-start capture -> flash -> collect
|
||||
2. Extract the captured text from the JSON
|
||||
3. verify_log.ps1 on the extracted boot log
|
||||
|
||||
Usage:
|
||||
powershell -ExecutionPolicy Bypass -File run_boot_test.ps1 `
|
||||
[-Port COM6] [-BaudRate 115200] `
|
||||
[-DurationMs 30000] [-InitialTimeoutMs 90000] [-IdleTimeoutMs 8000] `
|
||||
[-FlashCmd "D:\...\download.bat"] `
|
||||
[-Required "App init OK;Network Init;net init: OK;PHY: 100M FULL"] `
|
||||
[-Forbidden "FAIL;ERROR;HardFault"] `
|
||||
[-OutDir C:\temp] [-ShowTailLines 15]
|
||||
|
||||
Exit codes:
|
||||
0 = PASS (captured + all required markers + no forbidden)
|
||||
1 = FAIL (marker miss / forbidden hit)
|
||||
2 = capture or flash error
|
||||
3 = verify file error
|
||||
|
||||
NOTE: ASCII-only on purpose - project source files contain Chinese and must
|
||||
never be rewritten by encoding-sensitive PowerShell. Keep this script ASCII.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$Port = "COM6",
|
||||
[int]$BaudRate = 115200,
|
||||
[int]$DurationMs = 30000,
|
||||
[int]$InitialTimeoutMs = 90000,
|
||||
[int]$IdleTimeoutMs = 8000,
|
||||
[int]$MaxBytes = 65536,
|
||||
[string]$FlashCmd = "D:\Code\DTU 程序\STM32F4-Base\MDK-ARM\download.bat",
|
||||
[string]$Required = "App init OK;Network Init;net init: OK",
|
||||
[string]$Forbidden = "FAIL;ERROR;HardFault",
|
||||
[string]$OutDir = "$env:TEMP\opencode",
|
||||
[int]$ShowTailLines = 15
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$captureScript = Join-Path $scriptDir "serial_capture.ps1"
|
||||
$verifyScript = Join-Path $scriptDir "verify_log.ps1"
|
||||
|
||||
if (-not (Test-Path -LiteralPath $captureScript)) {
|
||||
Write-Output "RUN_TEST_ERROR: serial_capture.ps1 not found"
|
||||
exit 2
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $verifyScript)) {
|
||||
Write-Output "RUN_TEST_ERROR: verify_log.ps1 not found"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $OutDir)) {
|
||||
New-Item -ItemType Directory -Path $OutDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$stamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||
$capJson = Join-Path $OutDir "boot_capture_$stamp.json"
|
||||
$bootTxt = Join-Path $OutDir "boot_log_$stamp.txt"
|
||||
|
||||
Write-Output "=== Boot test $stamp ==="
|
||||
Write-Output "Capture: $capJson"
|
||||
|
||||
& $captureScript -OutFile $capJson -Port $Port -BaudRate $BaudRate `
|
||||
-DurationMs $DurationMs -InitialTimeoutMs $InitialTimeoutMs `
|
||||
-IdleTimeoutMs $IdleTimeoutMs -MaxBytes $MaxBytes `
|
||||
-FlashCmd $FlashCmd -MaxRetries 3 -RetryDelayMs 1500
|
||||
$capRc = $LASTEXITCODE
|
||||
if ($capRc -ne 0) {
|
||||
Write-Output "RUN_TEST_ERROR: capture failed (rc=$capRc)"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $capJson)) {
|
||||
Write-Output "RUN_TEST_ERROR: no capture JSON at $capJson"
|
||||
exit 2
|
||||
}
|
||||
|
||||
try {
|
||||
$json = Get-Content -LiteralPath $capJson -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
} catch {
|
||||
Write-Output "RUN_TEST_ERROR: cannot parse capture JSON: $_"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if (-not $json.read) {
|
||||
Write-Output "RUN_TEST_ERROR: capture JSON has no 'read' object"
|
||||
exit 2
|
||||
}
|
||||
|
||||
Write-Output ("Capture: bytes_read={0} completion_reason={1} waited_ms={2} elapsed_ms={3}" -f `
|
||||
$json.read.bytes_read, $json.read.completion_reason, $json.read.waited_ms, $json.read.elapsed_ms)
|
||||
|
||||
$data = [string]$json.read.data
|
||||
if ([string]::IsNullOrEmpty($data)) {
|
||||
Write-Output "RUN_TEST_ERROR: capture returned no data (device silent?)"
|
||||
Write-Output "Hint: raise -InitialTimeoutMs if flashing is slow, or check the device boots."
|
||||
exit 2
|
||||
}
|
||||
|
||||
[System.IO.File]::WriteAllText($bootTxt, $data, [System.Text.Encoding]::UTF8)
|
||||
Write-Output "Boot log: $bootTxt"
|
||||
|
||||
& $verifyScript -LogPath $bootTxt -Required $Required -Forbidden $Forbidden `
|
||||
-ShowTailLines $ShowTailLines
|
||||
$verifyRc = $LASTEXITCODE
|
||||
Write-Output "RUN_TEST_RC=$verifyRc"
|
||||
exit $verifyRc
|
||||
@@ -0,0 +1,159 @@
|
||||
<#
|
||||
serial_capture.ps1 - Capture a serial boot log with serial-mcp-server CLI.
|
||||
|
||||
Workflow (deterministic boot-log capture after flashing):
|
||||
1. Open COM via serial-mcp-server `read` CAPTURE mode and WAIT for the first
|
||||
byte (up to -InitialTimeoutMs). This starts BEFORE flashing.
|
||||
2. Flash the target (download.bat) -> MCU resets and prints the boot log.
|
||||
3. The running capture picks up the first byte, then collects for -DurationMs.
|
||||
4. The process exits and writes a single structured JSON file at -OutFile.
|
||||
|
||||
Known trap (Adancurusul/serial-mcp-server, fixed here by retry):
|
||||
When COM is released by a previous process and reopened immediately,
|
||||
tokio-serial read returns 0 bytes and the project's capture.rs turns that
|
||||
into a fatal `UnexpectedEof` error (serial stream returned zero bytes).
|
||||
This is transient: a short backoff then reopening succeeds. This script
|
||||
detects that error, backs off, and restarts the capture.
|
||||
|
||||
Usage:
|
||||
powershell -ExecutionPolicy Bypass -File serial_capture.ps1 `
|
||||
-OutFile C:\temp\boot.json `
|
||||
[-Port COM6] [-BaudRate 115200] `
|
||||
[-DurationMs 20000] [-InitialTimeoutMs 60000] `
|
||||
[-IdleTimeoutMs 1500] [-MaxBytes 65536] `
|
||||
[-FlashCmd "D:\...\download.bat"] `
|
||||
[-MaxRetries 3] [-RetryDelayMs 1500]
|
||||
|
||||
Modes:
|
||||
-FlashCmd: orchestrates the whole sequence in ONE call: (retry-stable)
|
||||
start capture, run the flash/download command, then wait for capture to
|
||||
finish. Use this to avoid tool-call gaps letting the capture timeout before
|
||||
flashing.
|
||||
No -FlashCmd: starts the capture, waits for it to be stable (survives
|
||||
-StabilityCheckMs), prints the PID, and returns. Caller flashes, then calls
|
||||
with -WaitOnly to reap.
|
||||
|
||||
Exit codes:
|
||||
0 = capture completed (ok or clean timeout)
|
||||
1 = capture failed to start after retries
|
||||
2 = capture error status in JSON
|
||||
|
||||
NOTE: ASCII-only on purpose - project source files contain Chinese and must
|
||||
never be rewritten by encoding-sensitive PowerShell. Keep this script ASCII.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$OutFile,
|
||||
|
||||
[string]$Port = "COM6",
|
||||
[int]$BaudRate = 115200,
|
||||
[int]$DurationMs = 20000,
|
||||
[int]$InitialTimeoutMs = 60000,
|
||||
[int]$IdleTimeoutMs = 1500,
|
||||
[int]$MaxBytes = 65536,
|
||||
[string]$FlashCmd = "",
|
||||
[int]$MaxRetries = 3,
|
||||
[int]$RetryDelayMs = 1500,
|
||||
[int]$StabilityCheckMs = 1500
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$exe = "$env:LOCALAPPDATA\serial-mcp-server\serial-mcp-server.exe"
|
||||
if (-not (Test-Path -LiteralPath $exe)) {
|
||||
Write-Output "CAPTURE_ERROR: serial-mcp-server binary not found: $exe"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$outDir = Split-Path -Parent $OutFile
|
||||
if ($outDir -and -not (Test-Path -LiteralPath $outDir)) {
|
||||
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$baseArgs = @(
|
||||
"read",
|
||||
"--port", $Port,
|
||||
"--baud", ([string]$BaudRate),
|
||||
"--duration-ms", ([string]$DurationMs),
|
||||
"--start-trigger", "first-byte",
|
||||
"--initial-timeout-ms", ([string]$InitialTimeoutMs),
|
||||
"--idle-timeout-ms", ([string]$IdleTimeoutMs),
|
||||
"--max-bytes", ([string]$MaxBytes),
|
||||
"--json"
|
||||
)
|
||||
|
||||
function Start-CaptureProcess {
|
||||
param([int]$attempt)
|
||||
$out = $OutFile
|
||||
$err = "$OutFile.err"
|
||||
if (Test-Path -LiteralPath $out) { Remove-Item -LiteralPath $out -Force }
|
||||
if (Test-Path -LiteralPath $err) { Remove-Item -LiteralPath $err -Force }
|
||||
if ($attempt -gt 0) {
|
||||
Write-Host "RETRY: capture attempt $attempt (backoff $RetryDelayMs ms)"
|
||||
Start-Sleep -Milliseconds $RetryDelayMs
|
||||
}
|
||||
$p = Start-Process -FilePath $exe -ArgumentList $baseArgs `
|
||||
-RedirectStandardOutput $out -RedirectStandardError $err `
|
||||
-WindowStyle Hidden -PassThru
|
||||
if ($p -eq $null -or $p.HasExited) {
|
||||
Write-Output "CAPTURE_ERROR: process failed to start (attempt $attempt)"
|
||||
return $null
|
||||
}
|
||||
return $p
|
||||
}
|
||||
|
||||
function Test-CaptureErrored {
|
||||
$err = "$OutFile.err"
|
||||
if (Test-Path -LiteralPath $err) {
|
||||
$e = Get-Content -LiteralPath $err -Raw -ErrorAction SilentlyContinue
|
||||
if ($e -match "UnexpectedEof|zero bytes|Error:") { return $true }
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
$proc = $null
|
||||
for ($i = 0; $i -le $MaxRetries; $i++) {
|
||||
$proc = Start-CaptureProcess -attempt $i
|
||||
if ($proc -eq $null) { continue }
|
||||
|
||||
# Wait a moment: if the process died with EOF/error immediately, retry.
|
||||
Start-Sleep -Milliseconds $StabilityCheckMs
|
||||
if (-not $proc.HasExited) { break } # stable, keep it
|
||||
if (-not (Test-CaptureErrored)) { break } # exited cleanly, no error
|
||||
Write-Host "CAPTURE_EOF: transient EOF on attempt $i, retrying..."
|
||||
$proc = $null
|
||||
}
|
||||
|
||||
if ($proc -eq $null) {
|
||||
Write-Output "CAPTURE_ERROR: could not start a stable capture after retries"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Output "CAPTURE_PID: $($proc.Id)"
|
||||
|
||||
if ($FlashCmd) {
|
||||
if (-not (Test-Path -LiteralPath $FlashCmd)) {
|
||||
Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue
|
||||
Write-Output "CAPTURE_ERROR: flash command not found: $FlashCmd"
|
||||
exit 1
|
||||
}
|
||||
Write-Output "FLASH_START: $FlashCmd"
|
||||
& $FlashCmd
|
||||
$flashRc = $LASTEXITCODE
|
||||
Write-Output "FLASH_RC: $flashRc"
|
||||
$proc.WaitForExit()
|
||||
Write-Output "CAPTURE_DONE"
|
||||
if (Test-Path -LiteralPath $OutFile) {
|
||||
$content = Get-Content -LiteralPath $OutFile -Raw -ErrorAction SilentlyContinue
|
||||
if ($content -match '"status":\s*"error"') {
|
||||
Write-Output "CAPTURE_ERROR: capture returned error status"
|
||||
Write-Output $content
|
||||
exit 2
|
||||
}
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,102 @@
|
||||
<#
|
||||
verify_log.ps1 - Check a captured MCU debug log against boot/test markers.
|
||||
|
||||
Used by the @test loop: after flashing, the fresh boot log is captured to a
|
||||
file (serial-mcp-server capture), then this script greps it and prints a
|
||||
structured verdict.
|
||||
|
||||
Usage:
|
||||
powershell -ExecutionPolicy Bypass -File verify_log.ps1 `
|
||||
-LogPath <file> `
|
||||
[-Required 'marker1;marker2'] `
|
||||
[-Forbidden 'FAIL;ERROR;HardFault'] `
|
||||
[-ShowTailLines 40]
|
||||
|
||||
Exit code:
|
||||
0 = PASS (every required marker found, no forbidden pattern matched)
|
||||
1 = FAIL (missing required marker or forbidden pattern present)
|
||||
2 = ERROR (log file not found / unreadable)
|
||||
|
||||
Default required markers match the STM32F4-Base boot sequence
|
||||
(see App/app_main.c + App/task/net_task.c). Override per test case, e.g.:
|
||||
-Required 'App init OK;net init: OK;PHY: 100M FULL'
|
||||
-Forbidden 'FAIL;ERROR;HardFault;assert'
|
||||
|
||||
NOTE: ASCII-only on purpose - project source files contain Chinese and must
|
||||
never be rewritten by encoding-sensitive PowerShell. Keep this script ASCII.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$LogPath,
|
||||
|
||||
[string]$Required = 'App init OK;Network Init;net init: OK',
|
||||
[string]$Forbidden = 'FAIL;ERROR;HardFault;assert',
|
||||
[int]$ShowTailLines = 40
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $LogPath)) {
|
||||
Write-Output "VERIFY_ERROR: log file not found: $LogPath"
|
||||
exit 2
|
||||
}
|
||||
|
||||
try {
|
||||
$content = Get-Content -LiteralPath $LogPath -Encoding UTF8 -ErrorAction Stop
|
||||
} catch {
|
||||
# Fall back to default encoding if UTF-8 read fails
|
||||
try {
|
||||
$content = Get-Content -LiteralPath $LogPath -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Output "VERIFY_ERROR: cannot read log file: $LogPath"
|
||||
exit 2
|
||||
}
|
||||
}
|
||||
|
||||
$all = $content -join "`n"
|
||||
|
||||
$requiredList = @($Required -split ';' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' })
|
||||
$forbiddenList = @($Forbidden -split ';' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' })
|
||||
|
||||
Write-Output "=== Log verdict: $LogPath ==="
|
||||
Write-Output ("Lines: {0}, bytes: {1}" -f $content.Count, (Get-Item -LiteralPath $LogPath).Length)
|
||||
|
||||
$missing = @()
|
||||
foreach ($m in $requiredList) {
|
||||
if ($all.Contains($m)) {
|
||||
Write-Output ("[OK] required marker found: {0}" -f $m)
|
||||
} else {
|
||||
Write-Output ("[MISS] required marker NOT found: {0}" -f $m)
|
||||
$missing += $m
|
||||
}
|
||||
}
|
||||
|
||||
$hits = @()
|
||||
foreach ($f in $forbiddenList) {
|
||||
$matches = @($content | Where-Object { $_ -like "*$f*" })
|
||||
if ($matches.Count -gt 0) {
|
||||
Write-Output ("[HIT] forbidden pattern: {0} ({1} line(s))" -f $f, $matches.Count)
|
||||
$hits += $f
|
||||
} else {
|
||||
Write-Output ("[OK] forbidden pattern absent: {0}" -f $f)
|
||||
}
|
||||
}
|
||||
|
||||
if ($ShowTailLines -gt 0 -and $content.Count -gt 0) {
|
||||
Write-Output ""
|
||||
Write-Output "=== Last $ShowTailLines line(s) of log ==="
|
||||
$start = [Math]::Max(0, $content.Count - $ShowTailLines)
|
||||
$content[$start..($content.Count - 1)] | ForEach-Object { Write-Output $_ }
|
||||
}
|
||||
|
||||
if ($missing.Count -gt 0 -or $hits.Count -gt 0) {
|
||||
Write-Output ""
|
||||
Write-Output "VERDICT: FAIL"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "VERDICT: PASS"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user