Add Week 4 Binary Ninja notebook and OpenOCD/flash host tooling

- WEEK04-BN.md/.pdf: full Binary Ninja dynamic + static lab for 0x0005 and 0x0008
- README: link the Week 4-BN notebook after Week 4a
- debug-server.sh/.ps1: OpenOCD launcher (USE_CORE=0, -rtos none, BP_ADDR)
- flash.sh/.ps1: UF2 flash helpers
- pyproject.toml: ruff config for root host-side scripts
This commit is contained in:
Kevin Thomas committed 2026-10-03 11:33:10 -04:00
1 parent 34f21bcd52
commit 3e52dd0412
11 files changed
+2264 -1095

No files matched your search

+128
View File
@@ -0,0 +1,128 @@
<#
.SYNOPSIS
Program a raw .bin into RP2350 XIP flash via the Pico Debug Probe and OpenOCD.
.DESCRIPTION
Writes a headerless raw binary to the RP2350's external XIP flash starting at
physical address 0x10000000, verifies the written bytes by reading them back,
then releases the core so the freshly programmed firmware runs.
A raw .bin carries no address information, no entry point and no section
table, so the load address MUST be supplied out of band. On the RP2350 the
only correct value is 0x10000000: that is where the boot ROM jumps after
pulling the reset vector out of the on-chip XIP window. Flashing anywhere
else produces a board that enumerates over USB and then does nothing.
The target must already be running the stock RP2350 bootrom (the default
state after power-up, or after any BOOTSEL + UF2 reflash). OpenOCD attaches
to the bootrom over SWD, halts it, programs flash, verifies, and resets.
This is the macOS / Linux equivalent of flash.sh. The two must stay in
lockstep: same base address, same verify, same conservative SWD clock.
.PARAMETER Bin
Mandatory. Path to the raw .bin image to program.
.ENVIRONMENT
PICO_OPENOCD Directory containing openocd.exe AND its scripts\ directory.
Default: $env:USERPROFILE\.pico-sdk\openocd\0.12.0+dev
The path is used for BOTH the executable and the -s scripts
argument.
ADAPTER_SPEED SWD clock in kHz. Default: 5000.
5000 kHz is deliberately conservative. This is a write path,
not a read-only debug session, and a marginal USB cable or
long dupont run produces spurious verify failures at higher
clocks. Raise it (24000) for read-only work; if
"Error: target not halted" or verify mismatches appear,
lower it to 1000.
.EXAMPLE
.\flash.ps1 -Bin 0x0005_intro-to-variables\build\0x0005_intro-to-variables.bin
.EXAMPLE
$env:ADAPTER_SPEED=1000; .\flash.ps1 -Bin build\hacked.bin
.EXAMPLE
$env:PICO_OPENOCD="C:\openocd\bin"; .\flash.ps1 -Bin build\hacked.bin
.NOTES
Requirements:
* Pico Debug Probe (or any CMSIS-DAP / SWD adapter) connected to the target.
* OpenOCD with the rp2350 target script installed.
* The Debug Probe must use the WinUSB driver. If OpenOCD reports
"unable to open CMSIS-DAP device", install it with Zadig
(https://zadig.akeo.ie/), selecting "Debug Probe (CMSIS-DAP)" -> WinUSB.
* Exactly one process may own the debug probe. Close any other OpenOCD,
GDB, or IDE debug session first.
Exit status:
0 flash written, verified, and core released
1 input file missing or OpenOCD not found
* any other status is propagated from OpenOCD, so a failed verify or a
write error is visible to the caller rather than being swallowed.
Related scripts:
debug-server.ps1 long-running GDB server for live debugging with
Binary Ninja. Use that instead of this script when you
need to single-step.
See also:
WEEK04\WEEK04-BN.md the full walkthrough this script belongs to
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$Bin
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
# --- argument validation ---------------------------------------------------
if (-not (Test-Path -PathType Leaf $Bin)) {
Write-Error "file not found: $Bin"
Write-Host "build it first: cmake -B build -G Ninja -DPICO_BOARD=pico2 -DPICO_PLATFORM=rp2350 ; cmake --build build"
exit 1
}
# --- toolchain resolution --------------------------------------------------
$OCD = if ($env:PICO_OPENOCD) { $env:PICO_OPENOCD } else { "$env:USERPROFILE\.pico-sdk\openocd\0.12.0+dev" }
if (-not (Test-Path "$OCD\openocd.exe")) {
Write-Error "OpenOCD not found at $OCD\openocd.exe (set PICO_OPENOCD to the directory containing openocd.exe)"
exit 1
}
$SPEED = if ($env:ADAPTER_SPEED) { $env:ADAPTER_SPEED } else { "5000" }
# --- program ---------------------------------------------------------------
# OpenOCD flag notes:
# -f interface/cmsis-dap.cfg the Pico Debug Probe is a CMSIS-DAP v1 device
# -f target/rp2350.cfg RP2350 dual Cortex-M33 + RP2350B0-style DAP;
# sets USE_CORE=SMP by default, which is fine here
# because we never hand uninitialised core1
# registers to a debugger. For live debugging use
# debug-server.ps1, which forces USE_CORE=0.
# -c "program BIN 0x10000000 verify reset exit"
# program the write
# 0x10000000 base address (see .DESCRIPTION)
# verify read back and compare every byte; a mismatch aborts
# reset reset the core so the new image starts at its vectors
# exit release the probe and return to the shell
#
# The adapter speed is deliberately lower here than in debug-server.ps1; see
# ADAPTER_SPEED in .ENVIRONMENT.
Write-Host "Flashing $Bin -> 0x10000000 using $OCD\openocd.exe (SWD $SPEED kHz)"
& "$OCD\openocd.exe" `
-s "$OCD\scripts" `
-f interface/cmsis-dap.cfg `
-f target/rp2350.cfg `
-c "adapter speed $SPEED" `
-c "program $Bin 0x10000000 verify reset exit"
exit $LASTEXITCODE