Three small native Windows CLI tools to flash, reset, and read the Unique Device ID (UDID) of a Microchip dsPIC33AK (Curiosity-class) board through its on-board PKOB4 debugger, selecting the target by PKOB4 serial number.
Tip
Want the quickest ready-to-use setup? See the dspic33ak-hal-starter
buildtools/
directory. It includes the PowerShell wrapper, vendors these executables, and
provides a practical build → flash → reset workflow.
If you found this repository and simply want a ready-to-use firmware project
workflow, start from the dspic33ak-hal-starter example instead of wiring these
executables by hand:
dspic33ak-hal-starter/buildtools/flashauto.ps1is a higher-level wrapper that auto-detects the built HEX, chooses the PKOB4 by serial, runs flash, then runs reset.dspic33ak-hal-starter/buildtools/_flash_reset_tools/vendors published copies of these executables, so a fresh clone can flash/reset without a separate tool install.
Example:
git clone https://github.com/sulaolab/dspic33ak-hal-starter.git
cd dspic33ak-hal-starter
.\buildtools\build.ps1
.\buildtools\flashauto.ps1See the starter project's buildtools/ directory:
Use this repository directly when you want the standalone low-level tools, custom integration, or to rebuild/update the vendored executables.
Iterating on firmware from an editor/terminal — not the MPLAB X IDE — runs into three friction points that these tools remove:
- Opening MPLAB X just to flash or reset is slow. You want a single, scriptable command in your build/edit loop, not an IDE round-trip.
- Picking the right board when several are plugged in. PKOB4 tools index boards by connection order, which changes; these tools select strictly by PKOB4 serial number, so the board you mean is the board you get.
- Resetting a board whose console runs over the PKOB4 USB-CDC is awkward.
mdb Resetresets the MCU but tends to drop/re-enumerate the CDC console.ipecmd -OLhold/release keeps the console but does not reset a running MCU.- MPLAB X IPECMDBoost "release from reset" does reset and is the practically usable method — but its Java server occasionally hangs and wedges the workflow.
reset_pkob4 wraps that working IPECMDBoost path and adds warm/cold timeout
selection, early failure detection, and failure-only targeted cleanup. A healthy
Boost server is kept alive for fast subsequent resets; a transient hang no longer
blocks you. flash_pkob4 does the same hardening for the mdb programming step.
Both keep board selection by serial and run without opening the IDE.
Neither tool talks to the PKOB4 USB protocol directly, and reset_pkob4 never
blindly kills unrelated java.exe — it only clears the targeted IPECMDBoost state
when recovery is needed. flash_pkob4 --reset-after-flash is just a safe
composition of flash success followed by reset_pkob4.
Bottom line — built for automation, including AI agents. Because each tool is a single deterministic command (explicit serial, clear exit codes, timeout/retry, targeted recovery, machine-readable output that reports any cleanup it performed), an AI coding agent or CI script can drive the build → flash → reset → observe loop on real hardware with no IDE interaction and no human babysitting. That makes the hardware iteration loop dramatically faster and more reliable — the real payoff of these wrappers.
| Tool | Role |
|---|---|
flash_pkob4 |
Flash — program a HEX via MPLAB X mdb; optional reset-after-flash. |
reset_pkob4 |
Reset only — release-from-reset via MPLAB X IPECMDBoost. Does not flash. |
read_udid_pkob4 |
Read UDID only — read the target's 128-bit Unique Device ID via MPLAB X mdb. Does not flash or reset (but connecting briefly drops the CDC console). |
flash_pkob4 and reset_pkob4 are designed to be used as a pair: flash_pkob4
programs the HEX, and can optionally call reset_pkob4 after success. read_udid_pkob4 is a
standalone query — it reports the per-die UDID (board-individual identity), which
is distinct from the PKOB4 serial (a debugger ID) and from DEVID (a part-type ID).
- Windows x64.
- MPLAB X installed (v6.x). The tools auto-detect the newest install under
C:\Program Files\Microchip\MPLABX\vX.YYand reuse its bundledmdb/ipecmdboost.jarand Java runtime. (No separate Java/.NET install is needed to run a published single-file exe.) - A board attached via PKOB4.
- To build from source: .NET SDK 8+.
Each tool is an independent .NET project that publishes to a self-contained
single-file .exe (no .NET install required on the target machine):
cd flash_pkob4 # or: cd reset_pkob4
dotnet publish -c Release
# -> bin/Release/net8.0/win-x64/publish/<tool>.exeBuild outputs (bin/, obj/, the published .exe) are intentionally not
committed — see .gitignore. Copy the published .exe wherever you keep your
bench tools.
# Flash a HEX to one board (by PKOB4 serial), then reset it:
flash_pkob4 --serial 020085204RYN000318 --hex path/to/firmware.production.hex --reset-after-flash
# Read that board's Unique Device ID (UDID):
read_udid_pkob4 --serial 020085204RYN000318
# UDID1=00D7794B
# UDID2=56080004
# UDID3=00EA010F
# UDID4=FFFFFFFF
# UDID128=FFFFFFFF00EA010F5608000400D7794B
# Serial: 020085204RYN000318How
read_udid_pkob4reads the UDID. MPLAB Xmdbprints the fourUDIDn = 0x...words automatically when it connects to the target, and the tool parses those. The documentedx /U4xw 0x7F2BE0memory-read form does not work on the dsPIC33AK MP_DFP tested (it returns0xFFFFFFFF/0x00000000garbage — theUmemory is not mapped forxin that pack), so the connect-time print is the reliable path. The values match the on-chip read (firmware reading0x007F2BE0..EC) exactly.
Common options (see each subfolder README for the full list and exit codes):
--serial <sn>— PKOB4 serial (required); selects the board.--device <token>— device token (flash_pkob4defaultdsPIC33AK512MPS512,reset_pkob4default33AK512MPS512).--timeout <sec>,--retry <n>,--verbose,--dry-run.flash_pkob4 --reset-after-flashdelegates toreset_pkob4only after a successful program operation; the reset token is derived from--deviceunless--reset-deviceis specified.reset_pkob4uses separate Boost warm/cold defaults: warm port-2012 Java present means a 5 second timeout, while a cold Boost start uses 60 seconds because the first output may not appear for 20+ seconds. Pass--warm-timeout,--cold-timeout, or legacy--timeoutto override.
Both tools take --list to enumerate the connected PKOB4 serials — instant and
side-effect free (a USB scan):
reset_pkob4 --list # or: flash_pkob4 --list
# Connected PKOB4 serial(s): 1
# 020085204RYN000057reset_pkob4 additionally takes --list --probe to report each board's device
token + Device Id by briefly connecting to it:
reset_pkob4 --list --probe # uses --device (default 33AK512MPS512)
# Connected PKOB4: 1 (probing with device token '33AK512MPS512' -- this resets each board)
# 020085204RYN000057 dsPIC33AK512MPS512 Device Id 0xa77c--probe resets each probed board and briefly drops its USB-CDC console (it
has to connect to the target to read the device id), so it is opt-in. It confirms
the expected --device token rather than discovering an arbitrary unknown part. A
plain --list does neither — it only reads the USB serial. (You can also get the
serial from the MPLAB X tool list, flashing logs, or
Get-PnpDevice -PresentOnly | ? { $_.InstanceId -match 'RYN' }.) A PKOB4 serial
is not a secret — it is printed on the debugger.
flash_pkob4 and reset_pkob4 emit short, newline-terminated progress lines
prefixed with a stable tag ([flash] / [reset]), including a heartbeat every
5 seconds while a long operation is in flight:
[reset] attempt 1: boost=cold (port free); expected ~60s, timeout=60s serial=020085...057
[reset] 5s/~60s still working
[reset] 10s/~60s still working
[reset] done: reset succeeded in 30s serial=020085204RYN000057 exit=0
This is deliberately not a \r-redrawn progress bar: a bar is optimised for a
live TTY and gets mangled or flooded when captured/redirected, which is exactly how
an automated caller reads the output. The heartbeat is proof-of-life — a caller
(AI agent or CI) can tell "still working" from "hung" and will not kill a healthy
cold start early (early kills are what wedge the boost Java server). The lines are
flushed immediately, stay low-volume, and the final done: line carries the exit
code and elapsed time. Exit codes and --list output are unchanged. --verbose
still streams the raw underlying mdb/boost output (heartbeats are suppressed then,
since raw lines are already flowing).
In the default mode, flash_pkob4 also passes through the human-facing MPLAB X
report block verbatim — the ***** separator, Connecting to MPLAB PKoB4, the
loaded-versions list, Target device … found., the Device Id / UDID lines, the
program "…" echo, Programming target…, Erasing…, the memory-range lines, and
Programming/Verify complete / Program succeeded. — interleaved with the
heartbeat, so an MPLAB X user sees exactly the blocks they recognize. The
surrounding java.util.logging / SLF4J framework chatter is filtered out, the
trailing quit script echo is dropped, and runs of blank lines collapse to one.
Use --verbose for the full raw dump (everything, plus the wrapper's own
diagnostics). A failed program still surfaces its … Program failed. line.
[flash] attempt 1: programming hex=perseus_512.X.production.hex device=dsPIC33AK512MPS512 timeout=120s serial=020085...057
[flash] 10s/~120s still working
*****************************************************
Connecting to MPLAB PKoB4
Currently loaded versions:
...
Target device dsPIC33AK512MPS512 found.
Device Id = 0xa77c
UDID1 = 0x00d76a9d
program "….production.hex"
Programming target...
[flash] 35s/~120s still working
Erasing...
Programming/Verify complete
Program succeeded.
[flash] done: flash succeeded in 40s serial=020085204RYN000057 hex=… exit=0
- A reset re-enumerates the PKOB4 USB, so a serial/CDC console (e.g. Tera Term) briefly drops and must reconnect after each reset — expected, not a fault.
reset_pkob4keeps a healthyIPECMDBoostserver alive for fast warm resets. It removes stale2012.lock|inibefore cold starts when port 2012 is free, and performs targeted recovery after timeout or a decisive early failure using official/OQ, port-owner Java kill and2012.lock|iniremoval if needed.- State escape hatches (no target contact):
reset_pkob4 --check-javagives a fast verdict (warm/cold/stale),reset_pkob4 --shutdown-boostasks Boost to quit, andreset_pkob4 --clean-javaperforms emergency targeted cleanup. - If the PKOB4 firmware itself gets wedged (boost reports "unloaded while still
busy / unplug and reconnect"),
reset_pkob4detects this, stops retrying into a hang, and tells you to unplug/replug the USB cable (exit code 6). Only a USB re-enumeration clears that device-side state.
MIT-0 (MIT No Attribution).
dsPIC33AK(Curiosity 系)ボードを、基板上の PKOB4 デバッガ経由で 書き込み(flash) / リセット(reset) / UDID(固有デバイス ID)読み出し する ための Windows 用 CLI ツール 3 本です。 PKOB4 のシリアル番号でボードを選択するため、複数枚を挿したまま狙った 1 枚だけを操作できます。 MPLAB X を開かずにコマンド一発で動きます。
最大の狙いは自動化・AI エージェントでの利用です。各ツールは「明示シリアル指定・明確な終了コード・ timeout/retry・ターゲットを絞った復旧・掃除内容を出力する機械可読な出力」を備えた決定的な単一コマンドなので、 AI コーディングエージェントや CI が build → flash → reset → 観測 のループを実機上で IDE 操作も人手の見張りもなしに回せます。これにより実機イテレーションが劇的に速く・確実になります (このラッパーの本当の価値)。
flash_pkob4… 書き込み(MPLAB Xmdb経由)。必要なら成功後にreset_pkob4を呼べる。reset_pkob4… リセット専用(MPLAB XIPECMDBoostの release-from-reset)。書き込みはしない。read_udid_pkob4… UDID 読み出し専用(MPLAB Xmdb経由)。ダイ固有の 128bit UDID を表示 (接続時に CDC コンソールは一瞬切れる)。mdbが接続時に出力するUDIDn = 0x...をパースする方式で、x /U4xwメモリ読みは対象 DFP では機能しない(FF/00 を返す)ため接続時出力を使う。値はファームの オンチップ読み出し(0x007F2BE0..EC)と完全一致。UDID は PKOB4 シリアル(デバッガ ID)や DEVID(型番 ID)とは別物で、基板の個体識別に使える。
要件:Windows x64、MPLAB X v6.x インストール済み(同梱の mdb/ipecmdboost.jar/Java を自動検出して利用)、
ソースからのビルドには .NET SDK 8+。
ビルド:各フォルダで dotnet publish -c Release → 自己完結の単一 exe が
bin/Release/net8.0/win-x64/publish/ に生成されます。ビルド生成物(bin/obj/exe)は
リポジトリに含めていません(.gitignore で除外)。
使い方:--serial <PKOB4 SN> でボードを選択。flash_pkob4 --serial <sn> --hex <hex> で書き込み、
--reset-after-flash を付けると成功後にリセットまで実行します。各サブフォルダの README に全オプションと終了コードがあります。
補足:リセットは PKOB4 の USB 再列挙を伴うため、シリアルコンソール(Tera Term 等)は
一瞬切れて再接続が必要です(正常動作)。reset_pkob4 は正常な Boost 常駐を温存し、
失敗時だけ official shutdown、port-owner Java kill、2012.lock|ini 削除を行います。
warm 既定 timeout は 5 秒、cold 既定 timeout は 60 秒です。