agentskills.codes
BF

bfd-data-acquisition

Use when acquiring STM32 runtime data from global symbols, memory regions, stack-published local slots, or RTT channels and converting captures into structured artifacts for analysis.

Install

mkdir -p .claude/skills/bfd-data-acquisition && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16270" && unzip -o skill.zip -d .claude/skills/bfd-data-acquisition && rm skill.zip

Installs to .claude/skills/bfd-data-acquisition

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Use when acquiring STM32 runtime data from global symbols, memory regions, stack-published local slots, or RTT channels and converting captures into structured artifacts for analysis.
183 chars✓ has a “when” trigger

About this skill

BFD Data Acquisition

Self-Improvement Loop (Required)

  • When this skill encounters a build, flash, debug, script-usage, or other workflow problem, do not stop at the local workaround after the issue is solved.
  • Record the resolved issue and lesson in BFD-Kit/.learnings/ERRORS.md and/or BFD-Kit/.learnings/LEARNINGS.md; unresolved capability gaps go to BFD-Kit/.learnings/FEATURE_REQUESTS.md.
  • Promote reusable fixes into the affected BFD-Kit asset in the same task when feasible: update the relevant SKILL.md, script, wrapper, or resource so the next run benefits by default.
  • When a learning is promoted into a skill or script, append a short entry to BFD-Kit/.learnings/CHANGELOG.md and mention the improvement in the task close-out.

Purpose

Use this skill when the task is "show the contents of this global/static object" and the object can be resolved from an ELF.

This skill is the default path for:

  • global/static object inspection
  • pointer-hub decoding
  • enum-bearing state objects
  • stack-published local-slot capture through pointer symbols
  • raw RAM capture only when no stable symbol exists

This skill is not tied to any motor model or business object. The primary workflow is generic ELF + symbol + DWARF.

Required Precheck

Run bootstrap before any acquisition command:

python3 ./.codex/skills/bfd-project-init/scripts/bootstrap.py --project-root . --mode check

Fail fast if ${STM32_ELF} or the active bootstrap profile is missing.

Before the first symbol-auto run, also verify that the exact interpreter behind python3 can import elftools:

python3 -c "import elftools, sys; print(sys.executable)"

If this fails:

  • on Ubuntu system Python, install python3-pyelftools
  • if an activated conda environment shadows system python3, either install pyelftools into that environment or invoke /usr/bin/python3 explicitly for the acquisition command

Primary Command Contract

Primary script:

python3 BFD-Kit/skills/codex/bfd-data-acquisition/scripts/data_acq.py ...

Primary mode:

python3 BFD-Kit/skills/codex/bfd-data-acquisition/scripts/data_acq.py \
  --elf "${STM32_ELF}" \
  --mode symbol-auto \
  --symbol <global_symbol> \
  --follow-depth 1 \
  --format summary \
  --output logs/data_acq/<symbol>.summary

Meaning of the primary arguments:

  • --mode symbol-auto: resolve the symbol from ELF, reflect its DWARF type, reuse or rebuild schema cache, sample RAM, and decode named fields.
  • --symbol <global_symbol>: required global or static object symbol.
  • --follow-depth <N>: pointer follow depth.
  • --format summary|json|csv: output renderer.

symbol-auto rules:

  • requires --symbol
  • supports only --capture-mode snapshot
  • rejects manual decode options such as --decode-profile, --layout, --pointer-array, and --follow-pointer
  • writes or reuses cache under .codex/bfd/dwarf_cache/
  • when the script is invoked from a central BFD-Kit checkout, it also searches the current working directory upward for .codex/bfd/active_profile.env and .codex/bfd/dwarf_cache, so run it from the target project directory when you want project-local profile/cache resolution
  • root object size and typedef-backed array element sizes come from the reflected DWARF schema; if a snapshot is shorter than expected, the script now reports an explicit capture-size mismatch or truncated nested field metadata instead of a raw Python struct.error

Follow-Depth Rules

  • --follow-depth 0: decode the root object only; pointers remain address metadata.
  • --follow-depth 1: follow one pointer layer. Use this first for pointer hubs and object tables.
  • --follow-depth >1: recursively follow nested pointers. Increase only when the object layout requires it.

If --follow-depth >1 on a pointer array or pointer-rich object crashes with errors such as struct.error: unpack requires a buffer of 1 bytes, stop deep recursion on that object. Fall back to --follow-depth 1 to recover the first-layer structs plus child pointer addresses, then inspect the nested child objects separately with another acquisition or raw J-Link mem32 reads.

Standard Workflow Order

  1. Use --mode symbol-auto first when the target object has DWARF-supported type information.
  2. Fall back to --mode symbol only when:
    • the target type contains unsupported DWARF features
    • a manual decode profile is intentionally narrower than the full object
    • a typed scalar layout is sufficient
  3. Use --pointer-symbol only for stack-published local data.
  4. Use raw --address capture only when no stable symbol exists.

Native HSS Escalation

When the requirement is high-rate, non-halting sampling of a fixed-address scalar global/static variable on a J-Link target, prefer the native HSS CLI path instead of GUI J-Scope automation or halt/read/go loops:

bash BFD-Kit/scripts/bfd_jlink_hss.sh --json hss sample \
  --symbol chassis_parameter.IMU.yaw \
  --symbol chassis_parameter.IMU.pitch \
  --duration 0.3 \
  --period-us 1000 \
  --output logs/data_acq/imu_yaw_pitch_hss.csv

Use this path only for fixed-address scalar globals/statics. Repeat --symbol for multi-symbol sampling. On J-Link PLUS, SEGGER's model limits and local HSS verification both indicate a 10-symbol ceiling; do not treat hss inspect raw capability word 2 as the symbol-count limit. The wrapper uses BFD-Kit/.runtime/venv automatically after bash BFD-Kit/init_project.sh --project-root .. If the target is a pointer-driven object graph or needs DWARF field decoding, stay on symbol-auto. The command writes a wide CSV to --output and a metadata sidecar JSON to --output.meta.json.

Do not assume requested --period-us equals the achieved sample period on every probe model. Local RSCF_h7 validation with J-Link CE showed a practical single-float floor near 1000 us, even when --period-us was reduced from 1000 down to 1 and SWD was raised from 4000 to 8000 kHz. When a new J-Link model, target, or board wiring is introduced, run an explicit sweep first and report the effective period from captured sample counts instead of trusting the requested value or a capability word name.

ST-Link does not provide an HSS-equivalent path in this revision. If STM32_PROBE=stlink, treat high-rate capture as a separate polling/snapshot design problem rather than a drop-in replacement for native J-Link HSS.

If the requirement is textual RTT evidence over ST-Link, switch to the independent bfd-strtt-rtt skill instead of forcing that flow through J-Link RTT guidance.

For FanX/Tek DAPLink High or another CMSIS-DAP probe, use the PyOCD HSS-compatible sampler when native J-Link HSS is unavailable but a fixed-address scalar CSV is still needed:

RSCF_h7/.tools/pyocd-venv/bin/python BFD-Kit/scripts/bfd_pyocd_hss.py --json sample \
  --elf RSCF_h7/builds/gcc/debug/RSCF_H7_BOARD_ONE.elf \
  --target stm32h723xx \
  --uid 6d1395736d13957301 \
  --frequency 10000000 \
  --symbol g_system_status.status_byte \
  --duration 0.5 \
  --period-us 1000 \
  --output RSCF_h7/logs/data_acq/g_system_status_pyocd_hss.csv

This backend intentionally writes the same wide CSV + .meta.json shape as native HSS, but it is host-polled and uses host monotonic timestamps. Do not label it as SEGGER probe-side HSS. For deterministic high-rate system identification, prefer firmware telemetry mirror/ring or a custom DAPLink vendor-command backend once the probe firmware source is available.

When the question is specifically "how many float values can DAPLink / PyOCD hold at a stable 1000 Hz update?", use the built-in benchmark instead of guessing from one-off captures:

RSCF_h7/.tools/pyocd-venv/bin/python BFD-Kit/scripts/bfd_pyocd_hss.py --json benchmark-float \
  --address 0x200096E8 \
  --min-floats 1 \
  --max-floats 64 \
  --target stm32h723xx \
  --uid 6d1395736d13957301 \
  --frequency 10000000 \
  --duration 0.2 \
  --period-us 1000 \
  --output RSCF_h7/logs/data_acq/pyocd_float_benchmark.json

This report tells you:

  • the largest repeated float_count that still meets the configured 1 kHz stability rule
  • the effective bytes per second at each float count
  • where the host-polled path starts to fall behind

If the needed float count is above the stable 1 kHz boundary, stop trying to stretch host polling and move the fast path into the bundled MCU telemetry ring:

python3 BFD-Kit/scripts/bfd_telemetry_ring.py --json layout \
  --field pos_rad:f32 \
  --field vel_rads:f32 \
  --field torque_nm:f32 \
  --field state:u32 \
  --capacity 128

Then capture the ring through PyOCD once the firmware has published the ring image symbol/address:

RSCF_h7/.tools/pyocd-venv/bin/python BFD-Kit/scripts/bfd_telemetry_ring.py --json capture-pyocd \
  --address 0x24020000 \
  --field pos_rad:f32 \
  --field vel_rads:f32 \
  --field torque_nm:f32 \
  --field state:u32 \
  --target stm32h723xx \
  --uid 6d1395736d13957301 \
  --frequency 10000000 \
  --duration 1.0 \
  --poll-period-us 1000 \
  --output RSCF_h7/logs/data_acq/app_ring_capture.csv

The current bfd_pyocd_hss.py also supports two generic paths that align better with UNI_DataVisualizer style direct-read workflows:

  • raw SRAM/MMIO scalar capture via repeated --address-spec name@0xADDR:type
  • importing enabled variables from a Windows HSSDVProj file via --project-file

The script now coalesces contiguous addresses into one region read and automatically selects block32 when the merged region is 4-byte aligned and 4-byte sized. On RSCF_h7 with FanX/Tek DAPLink High at 10 MHz SWD, local validation reached about 51.25 kB/s for a packed 41B struct field group and about 128 kB/s for a merged 64B block32 raw-memory capture. This clears the practical 50 kB/s threshold for MCU runtime data collection, but it is still not probe-side HSS and should not be positioned as a 1 MB/s equivalent.


Content truncated.

Search skills

Search the agent skills registry