Operation Flows
This page describes the order in which wlink issues commands. Implementations
live in src/operations.rs
and src/probe.rs.
Command byte layouts are in Command Reference.
Attach (start of a session)
ProbeSession::attach:
- Check that the probe variant supports the requested chip. Without
--chip,CH32V103(0x01) is used as the provisional family. - Loop (up to 3 retries, 100 ms apart):
0x0c SetSpeedwith the provisionalriscvchipand the selected speed;0x0d / 0x02 AttachChip— break on success.
- If
--chipwas given, verify the detected family matches; otherwise issue0x0c SetSpeedagain using the detected family. - Run the family-specific post-init hook (
RiscvChip::do_post_init).
81 0c 02 01 01 SetSpeed(riscvchip=0x01, High)
81 0d 01 02 AttachChip
82 0d 05 05 20 36 05 10 → CH32V20X, ChipID 0x20360510
81 0c 02 05 01 SetSpeed again with the detected family
The CH32V205 family requires firmware v3.6 (version_code >= 42); older
firmware misdetects it as CH32V20X and wlink warns.
Status / chip info
ProbeSession::dump_info:
0x11 / 0x06 GetChipInfo::V2whenversion_code >= 29, else0x11 / 0x09 GetChipInfo::V1— see Chip Info.0x06 / 0x01 CheckReadProtect→ report whether flash is read-protected.- If the family supports it,
0x0d / 0x04 GetChipRomRamSplit→ SRAM/CODE split mode.
Querying info halts the MCU. wlink re-enables execution on detach.
Erase (default method)
ProbeSession::erase_flash:
- If the family supports flash protection:
0x06 / 0x01 CheckReadProtect; protected →unprotect_flash();- if unprotected,
0x06 / 0x04 CheckReadProtectEx; write-protected →unprotect_flash().
0x02 / 0x01 Program::EraseFlash.0x0d / 0x02 AttachChipagain to re-establish the session.
Unprotect
ProbeSession::unprotect_flash starts with a fresh attach
(0x0d / 0xff OptEnd then 0x0d / 0x02), then:
0x06 / 0x01 CheckReadProtect; if0x01,0x06 / 0x02 Unprotect, reattach, re-check.0x06 / 0x04 CheckReadProtectEx; if0x11,0x06 02 ff ff ff ff ff ff ff(UnprotectEx(0xff)), reattach, re-check.
wlink deliberately skips Unprotect when flash is already unprotected: the
probe firmware mass-erases the option-byte page, destroying USER/Data/WRPR.
Flash programming
ProbeSession::write_flash(data, address):
1 (optional) unprotect_flash()
2 0x01 SetWriteMemoryRegion(address, len)
3 0x02 / 0x05 Program::WriteFlashOP
4 data EP 0x02: write the family's flash algorithm blob
(padded to data_packet_size, see src/flash_op.rs)
5 0x02 / 0x07 Program::Unknown07AfterFlashOPWritten
→ response must be 0x07
6 0x02 / 0x02 Program::WriteFlash
7 for each write_pack_size chunk:
data EP 0x02: write chunk (0xff-padded to data_packet_size)
data EP 0x82: read 4-byte ack, last byte must be 0x04
(observed 41 01 01 04)
8 0x02 / 0x08 Program::End
data_packet_size and write_pack_size are per-family; see
RiscvChip::data_packet_size / write_pack_size in src/lib.rs.
Memory read
ProbeSession::read_memory(address, length):
- Round
lengthup to a multiple of 4. 0x03 SetReadMemoryRegion(address, len).0x02 / 0x0c Program::ReadMemory.0x82data endpoint: readlenbytes in 64-byte bulk chunks.- Reverse each 4-byte word to fix the probe’s word order.
A leading A9 BD F9 F3 sequence indicates a read from an invalid location or
a chip that has just entered debug mode; wlink logs a warning.
Special erase (power-off / RST pin)
erase --method power-off|pin-rst --chip <FAMILY> bypasses attach entirely:
0x0c SetSpeed(riscvchip=<--chip>, High)
0x0d / 0x0f EraseCodeFlash::ByPowerOff → 81 0d 02 0f <riscvchip>
or 0x0d / 0x08 EraseCodeFlash::ByPinRST → 81 0d 02 08 <riscvchip>
Both require a probe with power functions and a chip family whose
support_special_erase() is true. Because there is no auto-detection, --chip
is mandatory. The RST-pin variant additionally needs the nRST line wired to
the target.
Reset and detach
| CLI | Commands |
|---|---|
wlink reset (quit) | 0x0b / 0x01 Reset::Soft, then ~300 ms delay |
wlink reset run / halt | DMI halt/resume via 0x08 — see DMI |
| end of most commands | 0x0d / 0xff OptEnd (skipped with --no-detach, or when the MCU must stay halted) |
wlink sdi-print enable | 0x0d / 0xee 00 |
wlink set-power | 0x0d / 0x09…0x0c |