Add hisilicon ws63 bs21#2
Open
sanchuanhehe wants to merge 12 commits into
Open
Conversation
These chips are HiSilicon RISC-V cores whose Debug Module is reached through an ARM CoreSight DAP (AHB-AP) — the same topology probe-rs already supports for RP2350 via mem_ap_dtm. So this needs a target definition + a small DM-base extension + a debug sequence + a flash algorithm, NOT a new backend (the vendor needed a dedicated OpenOCD 'riscvcs' patch for exactly this; probe-rs has it). Adds, under doc/hisilicon-ws63-bs21/: - README.md: architecture, the RP2350/mem-AP feasibility finding, reverse- engineered ground truth (DAP IDCODE 0x5ba0_0477, WS63 AP0/DM 0x80000000, custom LOCI CSRs, memory maps, debug-enable), and the open hardware-gated items. - WS63.wip.yaml / BS21.wip.yaml: target scaffolds (RISC-V via !Riscv mem_ap + dm_base, real memory maps; flash_algorithms TODO). - mem_ap_dtm.patch.txt: the one required core change — an optional dm_base on RiscvCoreAccessOptions + MemApDtm so the DM can sit off AP-offset-0 (WS63 needs 0x80000000; default 0 keeps RP2350 and all existing targets byte-identical). WIP: debug bring-up is achievable with the dm_base change; flash programming and on-silicon validation remain open (need a board). Sourced from HiSpark Studio's bundled patched OpenOCD (riscvcs/batchcs, flash/nor/ws63.c, vendorhm/WS63-*.cfg) and the fbb_ws63/fbb_bs2x SDKs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The RISC-V mem-AP DTM (used when the RISC-V Debug Module sits behind a CoreSight mem-AP, e.g. RP235x) hard-coded the DM at AP offset 0 (dmi_register*4). HiSilicon WS63 (Hi3863) has the same topology but its DM is at 0x80000000. Add an optional DM base so such parts work, then ship WS63 as a debug target. - probe-rs-target: add `dm_base: u64` (#[serde(default)] -> 0) to RiscvCoreAccessOptions. Only meaningful with `mem_ap`. - mem_ap_dtm: MemApDtm carries dm_base; new(memory, dm_base); dmi_register_to_ap_address = dm_base + dmi_register*4. - session.rs: thread dm_base through riscv_mem_ap_cores (now a 3-tuple) at all three MemApDtm::new sites, sourced from the core's CoreAccessOptions::Riscv. - registry.rs / target-gen: set dm_base: 0 at the generic-RISC-V construction sites. - targets/HiSilicon_WS63.yaml: new built-in target. RISC-V core behind CoreSight AP0, dm_base 0x80000000 (from HiSpark Studio's patched OpenOCD WS63-*.cfg). DEBUG-only (attach/halt/mem/registers); no flash algorithm yet. Default dm_base 0 keeps RP235x and every existing target byte-identical. Verified: cargo check -p probe-rs-target / -p probe-rs / -p probe-rs --no-default-features all clean; cargo fmt --check clean; the validate_builtin test (validates all built-in targets incl. WS63) passes. Refs doc/hisilicon-ws63-bs21/README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address the adversarial completeness review: the dm_base change + WS63 target wire the DTM/target LAYER, but that is not an end-to-end 'attach works' claim. Make the README precise — items 1-2 (dm_base, WS63 target) landed; items 3-4 (vendor DebugSequence for debug-port enable + CSR expose; flash algorithm) plus AP0 enumeration, the external GPIO_04-high strap, and on-silicon validation are still required before attach succeeds on a board. Add explicit 'flash_algorithms: []' to HiSilicon_WS63.yaml for clarity. No code change; validate_builtin still passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WS63 is an ArmWithRiscv target (RISC-V core via mem-AP behind a CoreSight DAP), so
the chip-specific debug bring-up must hook the ARM DAP, not RISC-V: a RISC-V
on_connect runs too late (after enter_debug_mode first touches the DM), and for
ArmWithRiscv targets the DAP path uses the Arm sequence (session.rs maps
DebugSequence::Riscv(_) -> DefaultArmSequence). So the vendor returns
DebugSequence::Arm.
- new probe-rs/src/vendor/hisilicon/{mod.rs,sequences.rs}: HiSilicon vendor +
Ws63 ArmDebugSequence; registered in vendor/mod.rs. Matches chip name 'WS63'.
- Ws63::debug_device_unlock performs the debug-port enable (0x40010260 = 1,
'enable coresight-swd mode' from the vendor OpenOCD cfg) as a best-effort write:
on failure it logs and continues, since on most boards the port is enabled by
the external GPIO_04-high-at-power-on strap (which probe-rs cannot do).
- ws63_uses_hisilicon_arm_sequence test: WS63 resolves to DebugSequence::Arm
end-to-end (YAML -> registry -> vendor).
- expose_csrs has no probe-rs equivalent (register lists are compile-time static);
prefer_sba is moot on the mem-AP path (DMI routes through the ARM AP). Documented.
Still unvalidated on silicon (needs the GPIO_04 strap + AP0 to enumerate).
Verified: cargo check / fmt / clippy clean; registry tests pass (incl. the new
test + validate_builtin). Adversarially reviewed (attach-path + honesty: both pass).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A complete probe-rs flash loader for the WS63 SFC NOR flash, ported from the fbb_ws63 hal_sfc_v150 register/command sequence (corroborated by HiSpark OpenOCD ws63.c): WREN/RDSR/4K-erase/page-program via SFC reg mode (base 0x48000000, cmd_config@0x300 / cmd_ins@0x308 / cmd_addr@0x30c / cmd_databuf@0x400), 64-byte chunks, WIP poll, CPU-XIP->flash offset via 0x200000. - doc/hisilicon-ws63-bs21/flash-algorithm/: no_std crate using flash-algorithm 0.7 (default-features off + panic-handler; erase-chip off so probe-rs erases per-sector). Built for riscv32imc (WS63 has no atomics; probe-rs doesn't preserve FP). Excluded from the workspace (root Cargo.toml) so host builds skip it. - VERIFIED: builds for riscv32imc; the ELF exports Init/UnInit/EraseSector/ ProgramPage/FlashDevice; 'target-gen elf' extracts a well-formed algorithm (pc_init/pc_uninit/pc_program_page/pc_erase_sector/data_section_offset + flash_properties range 0x200000..0xa00000, page 0x100, 4K sectors). fmt+clippy clean. Adversarially reviewed against the SDK: faithful port, no transcription bugs (3-byte addressing assumption noted in the validation checklist). - DELIBERATELY NOT embedded into HiSilicon_WS63.yaml (flash_algorithms stays []): an unvalidated erase/program algo in the default flash path could corrupt a board on 'probe-rs download'. Embed via 'target-gen ... --update' only after the hardware validation checklist in flash-algorithm/README.md. WS63 stays debug-only until then. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… DMs A postexec-only abstract command (postexec=1, transfer=0) built with aarsize=0 is rejected by some DM implementations — notably the HiSilicon WS63, which returns abstractcs.cmderr=NotSupported. This aborted attach on real WS63 silicon (the DM has no abstract CSR access and no system bus, so all CSR/memory access must go through the program buffer, whose execution relies on these postexec commands). OpenOCD always issues postexec commands with a valid aarsize and regno=x0 (e.g. command=0x241000). Match that: add `postexec_command()` (aarsize selected by XLEN, regno=x0) and use it for the four program-buffer paths: read/write_csr_progbuf and read/write_dcsr_inline. Verified on WS63 hardware over J-Link: `probe-rs read --chip WS63` now attaches, halts, and reads memory through the program buffer (0xDEADBEEF from SRAM); previously failed with AbstractCommand(NotSupported). The rejected 0x40000 command is gone, replaced by 0x241000, with zero NotSupported errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
probe-rs can now erase/program the WS63 on-chip SPI-NOR flash over J-Link. Hardware-verified: `probe-rs download --chip WS63 --verify` writes real data and reads it back correctly. Getting there required fixing several issues for the program-buffer-only WS63 debug module and the flash-algorithm crate's RISC-V support: flash algorithm (doc/hisilicon-ws63-bs21/flash-algorithm): - Init clears the flash chip's block-protect bits (WREN + WRSR 0x00). On this board (GD25Q32) they are set at power-on (RDSR=0x1e) and silently reject all erase/program until cleared. - Add an `ebreak` trampoline at PrgCode offset 0 (link.x + build.rs). probe-rs sets ra=load_address per CMSIS convention and expects a routine's `ret` to self-trap there, but the crate lays functions out at .entry with no trap, so without this Init's `ret` fell through into EraseSector and timed out. - Build with code-model=medium (RISC-V medany). The default medlow emits absolute `lui`+offset for statics (e.g. _IS_INIT), which point at the wrong place once the blob is loaded at a runtime RAM address and make the algo run off the rails (the DM even drops out). medany is PC-relative. - Bound wait_cmd_done so a routine can never spin forever. probe-rs riscv: - halt(): set ebreakm on the fast halt path too, so an ebreak (such as the flash algorithm's return trampoline) traps to debug mode instead of raising an exception. HiSilicon_WS63.yaml: embed the ws63-sfc flash algorithm. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gorithm The WS63 SFC NOR flash loader was carried in-tree under doc/hisilicon-ws63-bs21/flash-algorithm/ as a standalone (workspace-excluded) riscv32imc crate. It now lives in its own general-purpose workspace, https://github.com/hispark-rs/hisi-flash-algorithm (the ws63 crate), with room for future HiSilicon families (bs2x). The algorithm itself is unchanged and stays embedded in probe-rs/targets/HiSilicon_WS63.yaml (flash_algorithms: [ws63-sfc]); that file is not touched here. - Remove the doc/hisilicon-ws63-bs21/flash-algorithm/ crate and its workspace `exclude` entry in the root Cargo.toml. - Add doc/hisilicon-ws63-bs21/flash-algorithm.md pointing at the new repo and documenting the build -> target-gen --update re-embed workflow. - Refresh the WS63 doc README: the flash algorithm is now embedded and hardware-verified (probe-rs download erase/program on a GD25Q32), not a scaffold. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
reset_hart_and_halt relied solely on a held haltreq across ndmreset. On targets where the halt lands a few instructions late, the hart runs past the reset vector before halting — on the HiSilicon WS63 a plain-haltreq reset_and_halt ends up ~46 instructions deep in the mask ROM (PC 0x1000b8) with stale CSRs (mepc/mcause left over from a prior run), which is misleading when bringing up an app. When the DM advertises dmstatus.hasresethaltreq, arm the dedicated halt-on-reset request (resethaltreq) before the reset pulse so the hart halts at the FIRST instruction out of reset, then disarm it (clrresethaltreq) once the hart is confirmed halted. Targets without the capability keep the previous held-haltreq behavior unchanged. Validated on WS63: reset_and_halt now lands at the reset vector 0x100000 instead of 0x1000b8. Also adds examples/trapdump.rs — a WS63 bring-up HIL diagnostic (HW-bp at app entry, run-to-milestone, free-run PC/GPIO sampling) used to find and verify this. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eset The WS63 boot ROM initializes the SFC (SPI Flash Controller) during normal reset. Using the Debug Module's ndmreset or hartreset+resethaltreq resets the SoC but halts the CPU before the boot ROM can run SFC init, leaving the SFC controller in a partially-initialized state. This causes 'Flash Init Fail! ret = 0x80001341' on subsequent boots. Root fix: override RiscvDebugSequence::reset_system_and_halt for WS63 to use the system controller's software reset (sc_sys_res), mirroring HiSilicon's official OpenOCD HISPARK_TRACE_MODIFIES flow: 1. Write SC_HRST_RES debug flag 2. Unlock SC_CFG_LOCK 3. Set PERI_CRG to HOSC clock 4. Trigger SC_SYS_RES system reset 5. Wait 5ms, read SC_HRST_RES, wait 10ms (assert_reset) 6. Halt core 7. Wait 500ms for halt to take effect (deassert_reset) The vendor now returns DebugSequence::Riscv(Ws63) so the RISC-V core gets the custom reset sequence. The ARM DAP bring-up falls back to DefaultArmSequence (same pattern as RP235x_riscv). Verified on WS63 silicon: probe-rs reset no longer breaks SFC; board boots normally with no 'Flash Init Fail' and UART output is intact.
1d613fb to
434ce29
Compare
Sync with hisi-flash-algorithm f9b774e: - pc_init 0x78→0x70, pc_uninit 0x240→0x278, pc_program_page 0x10a→0x154 - data_section_offset 0x2ac→0x3b4 - erase_sector_timeout 5000→30000 New algo includes wait_ready_best_effort + SR save/restore in Drop.
…SFC init The previous reset_system_and_halt used interface.halt(), which is synchronous — it writes haltreq and immediately polls allhalted. This catches the CPU inside Boot ROM before SFC is initialized, causing 'Flash Init Fail!' on subsequent boots. OpenOCD's 'deassert_reset' does the same: target_halt + 500 ms wait, relying on the halt request being asynchronous — the CPU runs through Boot ROM → flashboot → app during that window before actually stopping. Mirror that behavior: write haltreq without polling, wait 500 ms for Boot ROM + flashboot to complete, then confirm the halt synchronously.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.