DebugProbe C API

The C-compatible interface to the Binho Atira, shadowing the blocking C++ surface one call at a time — what Ground Control binds. Every string and byte buffer is written into caller-provided storage with an explicit capacity; nothing is allocated on the caller’s behalf. Every public method of debugprobe::DebugProbe has an entry point here, enforced by scripts/check_atira_bindings.py.

group DebugProbe C API

C-compatible interface to the Binho Atira, shadowing the blocking C++ surface one call at a time — what Ground Control binds.

Every string and byte buffer is written into caller-provided storage with an explicit capacity; nothing is allocated on the caller’s behalf.

Defines

DEBUGPROBE_PATH_MAX

Buffer sizes a caller must provide. Generous on purpose: a hidapi path is a device node on Linux but an IOService path on macOS.

DEBUGPROBE_SERIAL_MAX
DEBUGPROBE_SPI_CS_ASSERT

SPI_TRANSFER / list-entry flag: assert chip select before clocking.

DEBUGPROBE_SPI_CS_RELEASE

SPI_TRANSFER / list-entry flag: release chip select after clocking.

DEBUGPROBE_SPI_LIST_POLL

List-entry flag: poll this entry’s reply against the poll fields.

DEBUGPROBE_SPI_LIST_DISCARD_RX

List-entry flag: keep this entry’s reply out of the response.

DEBUGPROBE_SPI_XFER_MAX_PAYLOAD

Per-report bound of SPI_TRANSFER: tx bytes one command report carries.

DEBUGPROBE_SPI_XFER_MAX_TRANSFER

Per-report bound of SPI_TRANSFER: clocked bytes one response report returns.

DEBUGPROBE_SPI_MAX_TRANSFER_LENGTH

The hostadapter per-call limit, preserved by the SDK layer (P2).

DEBUGPROBE_FLASH_MAX_ERASE_TYPES

Capacity of DebugProbe_FlashParams::eraseTypes (JESD216 names at most four).

DEBUGPROBE_FLASH_NAME_MAX

Capacity of DebugProbe_FlashParams::name, NUL included.

DEBUGPROBE_NOTIFICATION_MAX

Largest payload a notification can carry: one HID report minus its header, rounded up. Sized from HID_CTRL_REPORT_SIZE (64) rather than guessed.

DEBUGPROBE_RESET_SYSTEM

Reset flavours for DebugProbe_DebugReset. AIRCR.SYSRESETREQ

DEBUGPROBE_RESET_CORE

AIRCR.VECTRESET — ARMv7-M only, UNSUPPORTED on v8-M

DEBUGPROBE_RESET_HARDWARE

nRESET through DAP_SWJ_Pins

DEBUGPROBE_TFLASH_NAME_MAX

Bytes DebugProbe_TargetFlashInfo::deviceName holds, NUL included (FlashDevice.DevName is char[128]).

DEBUGPROBE_TFLASH_ROUTINE_NONE

Routines DebugProbe_TargetFlashReport::failedRoutine names.

DEBUGPROBE_TFLASH_ROUTINE_INIT
DEBUGPROBE_TFLASH_ROUTINE_UNINIT
DEBUGPROBE_TFLASH_ROUTINE_ERASE_SECTOR
DEBUGPROBE_TFLASH_ROUTINE_PROGRAM_PAGE
DEBUGPROBE_TFLASH_ROUTINE_LOAD
DEBUGPROBE_TFLASH_ROUTINE_ERASE_CHIP
DEBUGPROBE_TFLASH_PACK_TEXT_MAX

Bytes each name field of the pack structs holds, NUL included; longer text is truncated.

DEBUGPROBE_TFLASH_PACK_REASON_MAX

Bytes DebugProbe_TargetFlashPackDevice::reason holds, NUL included.

DEBUGPROBE_TFLASH_PACK_FLASHABLE

DebugProbe_TargetFlashPackDevice::support values.

DEBUGPROBE_TFLASH_PACK_NEEDS_CONNECT_STEPS

loads only with its connectSteps confirmed

DEBUGPROBE_TFLASH_PACK_NOT_SUPPORTED

refused; reason says why

Typedefs

typedef void (*DebugProbe_ProgressFn)(uint32_t done, uint32_t total, void *user)

Progress in BYTES (never commands), on the calling thread.

typedef struct DebugProbe_Handle DebugProbe_Handle

Opaque handle for an Atira SDK instance.

typedef bool (*DebugProbe_TargetFlashProgressFn)(uint32_t done, uint32_t total, void *user)

Progress in BYTES on the calling thread; return false to cancel.

Functions

DebugProbe_Handle *DebugProbe_Create(int timeout_ms)

Creates an instance. Does not touch a device.

Parameters:
  • timeout_ms – Per-call response deadline; -1 waits forever.

Returns:

Handle, or NULL on allocation failure.

void DebugProbe_Destroy(DebugProbe_Handle *handle)

Destroys an instance, disconnecting first if needed. NULL is a no-op.

size_t DebugProbe_ListDevices(DebugProbe_DeviceEntry *out, size_t capacity, size_t *count)

Every connected Atira. Needs no handle and no connection.

Parameters:
  • out – Caller-allocated array, may be NULL when capacity is 0.

  • capacity – Entries out can hold.

  • count – Receives the number of devices FOUND, which can exceed capacity — call with capacity 0 to size the array, then again to fill it.

Returns:

Entries written into out.

bool DebugProbe_Connect(DebugProbe_Handle *handle, const char *devicePath, const char *serialNumber)

Opens a device. Empty or NULL selects the first Atira found.

Parameters:
  • devicePath – hidapi path, or NULL/”” for any.

  • serialNumber – iSerial, or NULL/”” for any. ⚠ On a multi-board bench always pass this: enumeration order is not stable and hidapi opens the first match.

Returns:

true when the device is open.

uint16_t DebugProbe_ConnectCode(DebugProbe_Handle *handle, const char *devicePath, const char *serialNumber)

DebugProbe_Connect with the reason it failed (1.7.1, #378).

Returns:

SUCCESS when open; SDK_ERROR_DISCONNECT when nothing could be opened (absent, busy, no permission) or handle is NULL; SDK_ERROR_UNEXPECTED_RESPONSE when DEV_INFO is unreadable or short; DEBUGPROBE_FIRMWARE_TOO_OLD when the firmware predates fw-atira v1.0.

void DebugProbe_Disconnect(DebugProbe_Handle *handle)

Closes the device. Safe to call when not connected.

bool DebugProbe_LastResponseMismatch(DebugProbe_Handle *handle, DebugProbe_ResponseMismatch *out)

Detail for the most recent SDK_ERROR_WRONG_RESPONSE on this handle.

Returns:

false when none has been recorded, so a caller can ask unconditionally after any failure. Overwritten by the next mismatch and never cleared by a success — read it while handling the error it belongs to.

uint16_t DebugProbe_LastFirmwareStatus(DebugProbe_Handle *handle)

The firmware’s raw 16-bit status from the most recent response. Since fw-atira v1.0 it is already a CosmicSDK code, so it differs from what the call returned only when the firmware sent a value it does not declare (the call then returns SDK_ERROR_UNEXPECTED_RESPONSE). For support. 0 (success) before the first response or when handle is NULL.

void DebugProbe_SetTimeout(DebugProbe_Handle *handle, int timeout_ms)

Changes the per-call deadline for subsequent calls.

size_t DebugProbe_SerialNumber(DebugProbe_Handle *handle, char *out, size_t capacity)

iSerial of the connected board, written NUL-terminated into out.

Returns:

Characters written, excluding the terminator; 0 when not connected.

size_t DebugProbe_UartBridgePort(DebugProbe_Handle *handle, char *out, size_t capacity)

OS name of this board’s UART-bridge port, NUL-terminated.

Correlated to the connected board rather than guessed from enumeration order, which is what makes it safe on a multi-board bench.

Returns:

Characters written, excluding the terminator; 0 when unknown.

void DebugProbe_OnNotification(DebugProbe_Handle *handle, void (*callback)(const DebugProbe_Notification*))

Registers a callback for unsolicited reports, or NULL to clear it.

⚠ The callback runs on the SDK’s polling thread, not the caller’s. Do no blocking work in it and issue no SDK call from it — the same rule the C++ surface carries, and the reason it is stated here too: a C consumer has no type system hint that this is another thread.

uint16_t DebugProbe_Echo(DebugProbe_Handle *handle, const uint8_t *data, size_t len, uint8_t *out, size_t outCapacity, size_t *outLen)

ECHO — proves the control plane is alive and returns evidence.

Parameters:
  • data – Bytes to send, may be NULL when len is 0.

  • out – Caller-allocated buffer for the echoed bytes, may be NULL.

  • outLen – Receives bytes written into out. Optional.

uint16_t DebugProbe_GetDeviceInfo(DebugProbe_Handle *handle, DebugProbe_DeviceInfo *out)

GET_DEVICE_INFO.

uint16_t DebugProbe_GetSettings(DebugProbe_Handle *handle, DebugProbe_DeviceSettings *out)

GET_SETTINGS — persisted configuration.

uint16_t DebugProbe_GetMode(DebugProbe_Handle *handle, ProgMode *mode)

GET_MODE — the persisted target protocol.

uint16_t DebugProbe_SetMode(DebugProbe_Handle *handle, ProgMode mode)

SET_MODE.

uint16_t DebugProbe_UartGetConfig(DebugProbe_Handle *handle, DebugProbe_UartConfig *out)

GET_UART_CFG.

uint16_t DebugProbe_UartSetConfig(DebugProbe_Handle *handle, const DebugProbe_UartConfig *cfg)

SET_UART_CFG. Rejected locally when the config is not legal — the firmware validates nothing beyond the payload length before persisting.

uint16_t DebugProbe_GetCdc1Config(DebugProbe_Handle *handle, DebugProbe_Cdc1Config *out)

GET_CDC1_CFG.

uint16_t DebugProbe_SetCdc1Config(DebugProbe_Handle *handle, const DebugProbe_Cdc1Config *cfg)

SET_CDC1_CFG. ⚠ An effective change resets the board — see the struct’s note.

uint16_t DebugProbe_GetSwdCoexistStatus(DebugProbe_Handle *handle, DebugProbe_SwdCoexistStatus *out)

GET_SWD_STATUS. Answers UNKNOWN_CMD on builds without SWD-coexist support, like every optional command.

uint16_t DebugProbe_GetPinStatus(DebugProbe_Handle *handle, DebugProbe_PinStatus *out)

GET_PIN_STATUS.

uint16_t DebugProbe_EnterBootMode(DebugProbe_Handle *handle)

ENTER_BOOTLOADER. The device re-enumerates as a DFU volume, so the connection dies on success — that is not an error.

uint16_t DebugProbe_PowerGetReading(DebugProbe_Handle *handle, DebugProbe_PowerReading *out)

POWER_GET_READING.

uint16_t DebugProbe_PowerGetMonitorActive(DebugProbe_Handle *handle, bool *active)

Whether the power monitor answered a reading at all.

uint16_t DebugProbe_PowerSetOutput(DebugProbe_Handle *handle, bool on)

POWER_SET_OUTPUT (fw-atira 1.0.x). ⚠ The firmware does not raise the target rail at boot, by design — a probe never pushes voltage into someone else’s board. Turning it on is a deliberate act with a target attached.

uint16_t DebugProbe_PowerGetOutput(DebugProbe_Handle *handle, bool *on)

POWER_GET_OUTPUT (fw-atira 1.0.x).

uint16_t DebugProbe_SetSignalVoltageLevel(DebugProbe_Handle *handle, uint16_t millivolts)

SET_SIGNAL_VOLTAGE_LEVEL (fw-atira >= 1.1), in mV. The firmware owns the range (FW_INVALID_PARAMETER outside it). Set a self-powered target’s I/O level before switching the signal voltage on.

uint16_t DebugProbe_GetSignalVoltageLevel(DebugProbe_Handle *handle, uint16_t *millivolts)

GET_SIGNAL_VOLTAGE_LEVEL (fw-atira >= 1.1): the set-point in mV.

uint16_t DebugProbe_SetSignalVoltageEnabled(DebugProbe_Handle *handle, bool on)

SET_SIGNAL_VOLTAGE_EN (fw-atira >= 1.1). Off also drops target power.

uint16_t DebugProbe_GetSignalVoltageEnabled(DebugProbe_Handle *handle, bool *on)

GET_SIGNAL_VOLTAGE_EN (fw-atira >= 1.1).

uint16_t DebugProbe_SetTargetPowerEnabled(DebugProbe_Handle *handle, bool on)

SET_POWER_TARGET_EN (fw-atira >= 1.1). On: FW_INTERFACE_NOT_INITIALIZED while the signal voltage is off, FW_RESOURCE_BUSY while a supply is on pin 1 (self-powered target; do not retry, the firmware already waits up to 0.5 s for leftover charge), FW_PIN1_OVERVOLTAGE above 5500 mV.

uint16_t DebugProbe_GetTargetPowerEnabled(DebugProbe_Handle *handle, bool *on)

GET_POWER_TARGET_EN (fw-atira >= 1.1).

uint16_t DebugProbe_GetSignalVoltageCheck(DebugProbe_Handle *handle, DebugProbe_SignalVoltageCheck *out)

GET_SIGNAL_VOLTAGE_CHECK (fw-atira >= 1.1): the signal set-point against a fresh read of pin 1. With target power off, pin 1 is a self-powered target’s own supply: read this before switching the signal voltage on.

uint16_t DebugProbe_SignalVoltageUseExternal(DebugProbe_Handle *handle, uint16_t *millivolts)

SIGNAL_VOLTAGE_USE_EXTERNAL (fw-atira >= 1.1): set the signal level to the self-powered target’s supply on pin 1 and switch the signal voltage on. millivolts receives the level set. FW_VOLTAGE_OUT_OF_RANGE: no usable supply; FW_RESOURCE_BUSY: target power is on; FW_PIN1_OVERVOLTAGE: above 5500 mV. Nothing is persisted.

uint16_t DebugProbe_DebugAttach(DebugProbe_Handle *handle, bool under_reset, DebugProbe_CoreState *out)

Bring up the debug port and enable core debug. Non-intrusive (the core keeps running) unless under_reset, which holds nRESET through the handshake and halts at the reset vector.

uint16_t DebugProbe_DebugDetach(DebugProbe_Handle *handle)

Release the core (debug off, breakpoints cleared) and the probe. Idempotent.

uint16_t DebugProbe_DebugHalt(DebugProbe_Handle *handle, DebugProbe_CoreState *out)

Halt the core (DHCSR.C_HALT) and wait for S_HALT.

uint16_t DebugProbe_DebugRun(DebugProbe_Handle *handle, DebugProbe_CoreState *out)

Resume the core.

uint16_t DebugProbe_DebugStep(DebugProbe_Handle *handle, DebugProbe_CoreState *out)

Execute one instruction with interrupts masked. Needs a halted core (DEBUGPROBE_DEBUG_NOT_HALTED otherwise).

uint16_t DebugProbe_DebugReset(DebugProbe_Handle *handle, uint8_t kind, DebugProbe_CoreState *out)

Reset and halt at the vector. kind is DEBUGPROBE_RESET_*.

uint16_t DebugProbe_DebugGetState(DebugProbe_Handle *handle, DebugProbe_CoreState *out)

Read the core state without changing it.

uint16_t DebugProbe_DebugRegRead(DebugProbe_Handle *handle, uint8_t reg, uint32_t *value)

Read one core register by DCRSR selector (0-15, 16 xPSR, 17 MSP, 18 PSP, 20 CONTROL group). Halted core required.

uint16_t DebugProbe_DebugRegWrite(DebugProbe_Handle *handle, uint8_t reg, uint32_t value)

Write one core register. Halted core required.

uint16_t DebugProbe_DebugMemRead(DebugProbe_Handle *handle, uint32_t addr, uint32_t len, uint8_t *out, size_t outCapacity, size_t *outLen)

Read len bytes of target memory through the MEM-AP (works while running; any alignment). len above 1 MiB is SDK_ERROR_WRONG_REQUEST.

Parameters:
  • out – Caller-allocated; outLen receives bytes written.

uint16_t DebugProbe_DebugMemWrite(DebugProbe_Handle *handle, uint32_t addr, const uint8_t *data, size_t len)

Write len bytes of target memory.

uint16_t DebugProbe_DebugCallFunction(DebugProbe_Handle *handle, uint32_t entry, uint32_t returnAddr, uint32_t stackPointer, uint32_t staticBase, const uint32_t args[4], uint32_t pollRounds, uint32_t *out_r0)

One call into code already resident in target memory.

The mechanism a CMSIS flash algorithm is driven with: args land in r0-r3, staticBase in r9 (0 leaves it alone), execution starts at entry with stackPointer, and returnAddr is where it comes back to — it must already hold a breakpoint instruction, which a CMSIS algorithm blob provides as its first word, so no FPB comparator is spent and the user’s breakpoints survive.

pollRounds bounds the wait for that return; 0 uses the session default. A sector erase is orders of magnitude slower than any other debug verb, which is why the ceiling is per call.

Requires a halted core, restores every register it clobbers, and reports DEBUGPROBE_DEBUG_CALL_FAULTED if the core halted somewhere other than the return address — a routine that hard-faults halts too, and its r0 reads exactly like success. A routine that never halts within pollRounds is halted by the SDK: DEBUGPROBE_DEBUG_CALL_FAULTED if it is then found in an exception handler (IPSR != 0), DEBUGPROBE_DEBUG_TIMEOUT otherwise.

Parameters:
  • out_r0 – receives the routine’s return value.

uint16_t DebugProbe_DebugBreakpointSet(DebugProbe_Handle *handle, uint32_t addr, uint8_t *id)

Set a hardware breakpoint; id receives the comparator to clear it by. Same address twice returns the same id.

uint16_t DebugProbe_DebugBreakpointClear(DebugProbe_Handle *handle, uint8_t id)

Clear one hardware breakpoint.

uint16_t DebugProbe_DebugBreakpointList(DebugProbe_Handle *handle, DebugProbe_Breakpoint *out, size_t capacity, size_t *count)

Every breakpoint the FPB holds.

Parameters:
  • out – Caller-allocated array of capacity; count receives how many exist (not how many fit), so a short array is detectable.

uint16_t DebugProbe_TargetFlashLoadAlgorithm(DebugProbe_Handle *handle, const uint8_t *flm, size_t flmLen, uint32_t ramStart, uint32_t ramSize, DebugProbe_TargetFlashInfo *out)

Parse and validate a .FLM against the RAM window [ramStart, ramStart+ramSize), host-side; touches nothing on the target. out receives the FlashDevice description.

uint16_t DebugProbe_TargetFlashGetInfo(DebugProbe_Handle *handle, DebugProbe_TargetFlashInfo *out)

The loaded algorithm’s description.

uint16_t DebugProbe_TargetFlashUnloadAlgorithm(DebugProbe_Handle *handle)

Drop the loaded algorithm. Idempotent.

uint16_t DebugProbe_TargetFlashEraseRange(DebugProbe_Handle *handle, uint32_t addr, uint32_t n, DebugProbe_TargetFlashProgressFn progress, void *user)

Erase every sector overlapping [addr, addr+n); bytes of those sectors outside the range are lost.

uint16_t DebugProbe_TargetFlashEraseChip(DebugProbe_Handle *handle, DebugProbe_TargetFlashProgressFn progress, void *user)

Erase the whole flash region: the FLM’s EraseChip when it has one (TargetFlashInfo::hasEraseChip), else every sector.

uint16_t DebugProbe_TargetFlashProgram(DebugProbe_Handle *handle, uint32_t addr, const uint8_t *data, size_t len, DebugProbe_TargetFlashProgressFn progress, void *user)

Program len bytes at addr. Erase is NOT implied.

uint16_t DebugProbe_TargetFlashVerify(DebugProbe_Handle *handle, uint32_t addr, const uint8_t *data, size_t len, bool *matches, uint32_t *mismatchAddr, DebugProbe_TargetFlashProgressFn progress, void *user)

Read back with the core halted and compare. matches receives the verdict; mismatchAddr the first differing address when it does not match (optional).

uint16_t DebugProbe_TargetFlashWrite(DebugProbe_Handle *handle, uint32_t addr, const uint8_t *data, size_t len, bool verify, DebugProbe_TargetFlashProgressFn progress, void *user)

Erase the touched sectors, program, and verify when verify, in one algorithm session.

uint16_t DebugProbe_TargetFlashGetLastReport(DebugProbe_Handle *handle, DebugProbe_TargetFlashReport *out)

What the last operation did, success or not.

uint16_t DebugProbe_TargetFlashGetLastErasedRange(DebugProbe_Handle *handle, uint32_t *addr, uint32_t *bytes)

The last operation’s erased range, [*addr, *addr + *bytes): whole sectors, so it can reach past the requested range. It counts only erases that finished: when failedRoutine is DEBUGPROBE_TFLASH_ROUTINE_ERASE_CHIP the algorithm’s whole region is in an unknown state, and when it is _ERASE_SECTOR so is the sector at *addr + *bytes (the first sector of the range when *bytes is 0). Not in DebugProbe_TargetFlashReport, which stays 28 bytes for callers that mirror it.

uint16_t DebugProbe_TargetFlashGetLastSkippedSteps(DebugProbe_Handle *handle, DebugProbe_TargetFlashConnectStep *out, size_t capacity, size_t *count)

The vendor connect steps the last operation skipped (C++ TargetFlashReport::connectStepsSkipped): those confirmed to DebugProbe_TargetFlashLoadPackDevice for the loaded part, when the operation touched the target. None on a refusal, after a .FLM load or for a FLASHABLE part. Not in DebugProbe_TargetFlashReport, which keeps its layout for callers that mirror it.

Parameters:
  • out – Caller-allocated array, may be NULL when capacity is 0.

  • capacity – Entries out can hold.

  • count – Receives the number of steps, which can exceed capacity.

Returns:

SUCCESS; SDK_ERROR_DISCONNECT for a NULL handle.

uint16_t DebugProbe_TargetFlashListPackDevices(const uint8_t *pack, size_t packLen, DebugProbe_TargetFlashPackDevice *out, size_t entrySize, size_t capacity, size_t *count)

Every device a .pack lists. Needs no handle and no connection.

Parameters:
  • pack – The .pack bytes.

  • packLen – Bytes at pack.

  • out – Caller-allocated array, may be NULL when capacity is 0.

  • entrySize – sizeof(DebugProbe_TargetFlashPackDevice) as the caller compiled it. Entries are entrySize apart and each gets that many bytes at most, so a caller built against an older header keeps working when a later SDK appends fields.

  • capacity – Entries out can hold.

  • count – Receives the number of devices in the pack, which can exceed capacity: call with capacity 0 to size the array, then again to fill it. 0 on failure.

Returns:

SUCCESS, or DEBUGPROBE_TFLASH_BAD_PACK; SDK_ERROR_WRONG_REQUEST when out is set and entrySize is 0.

uint16_t DebugProbe_TargetFlashListPackVariants(const uint8_t *pack, size_t packLen, DebugProbe_TargetFlashPackVariant *out, size_t entrySize, size_t capacity, size_t *count)

Every variant a .pack lists, device by device in listing order. Sized and filled like DebugProbe_TargetFlashListPackDevices, with entrySize = sizeof(DebugProbe_TargetFlashPackVariant).

Returns:

SUCCESS, or DEBUGPROBE_TFLASH_BAD_PACK; SDK_ERROR_WRONG_REQUEST when out is set and entrySize is 0.

uint16_t DebugProbe_TargetFlashGetPackDeviceConnectStep(const uint8_t *pack, size_t packLen, const char *device, size_t index, DebugProbe_TargetFlashConnectStep *out)

Connect step index (in order, from 0) the SDK skips for device: the C half of TargetFlashPackDevice::connectSteps, with no limit on how many a device lists. Needs no handle and no connection.

Parameters:
Returns:

SUCCESS, DEBUGPROBE_TFLASH_BAD_PACK or _PACK_NO_DEVICE; SDK_ERROR_WRONG_REQUEST for a NULL device or out, or an index at or past connectStepCount.

uint16_t DebugProbe_TargetFlashLoadPackDevice(DebugProbe_Handle *handle, const uint8_t *pack, size_t packLen, const char *device, const char *const *confirmedSteps, size_t confirmedCount, DebugProbe_TargetFlashInfo *out)

Load the .FLM a .pack names for device, with the PDSC’s RAM window, as DebugProbe_TargetFlashLoadAlgorithm does. Host-side.

Parameters:
  • device – A NUL-terminated DebugProbe_TargetFlashPackDevice::name.

  • confirmedSteps – The connect steps the user was shown and accepted, on every call. Must equal the device’s connect steps (same names, same order), so a confirmation for another part or pack does not carry over. May be NULL when confirmedCount is 0.

  • confirmedCount – Entries at confirmedSteps; 0 for a FLASHABLE part (a non-zero count there is refused with _PACK_NEEDS_CONFIRM).

  • out – Receives the algorithm’s FlashDevice description.

Returns:

SUCCESS, DEBUGPROBE_TFLASH_BAD_PACK, _PACK_NO_DEVICE, _PACK_UNSUPPORTED, _PACK_NEEDS_CONFIRM, _BAD_ALGORITHM or _RAM_WINDOW; SDK_ERROR_DISCONNECT for a NULL handle, device, out, or step pointer. On any refusal nothing is loaded.

uint16_t DebugProbe_SpiDeinit(DebugProbe_Handle *handle)

SPI_DEINIT — close the session, releasing a held CS. Idempotent.

uint16_t DebugProbe_SpiGetParameters(DebugProbe_Handle *handle, DebugProbe_SpiParams *out)

SPI_GET_PARAMS — the open session’s parameters.

uint16_t DebugProbe_SpiTransferChunk(DebugProbe_Handle *handle, uint8_t flags, const uint8_t *tx, size_t txLen, uint16_t transferLen, uint8_t *rx, size_t rxCapacity, size_t *rxLen)

SPI_TRANSFER — one report: clock transferLen bytes, the first txLen from tx and the rest as dummy zeros.

Parameters:
  • handle – The device.

  • tx – Bytes to clock out first; may be NULL when txLen is 0.

  • txLen – 0..56.

  • transferLen – 1..59 clocked bytes, at least txLen.

  • rxCapacity – Capacity of rx in bytes.

  • rxLen – Receives the number of bytes written to rx. Optional.

  • flags – DEBUGPROBE_SPI_CS_ASSERT / _RELEASE: both = a self-contained transaction; ASSERT alone opens a held envelope, neither continues it, RELEASE alone closes it.

  • rx – Caller-allocated; receives every clocked byte (transferLen of them), truncated to rxCapacity; rxLen receives bytes written.

uint16_t DebugProbe_SpiCsRelease(DebugProbe_Handle *handle)

SPI_CS release — end a held envelope without clocking.

uint16_t DebugProbe_SpiGetStatus(DebugProbe_Handle *handle, DebugProbe_SpiStatus *out)

SPI_GET_STATUS — answers without a session.

uint16_t DebugProbe_SpiHashStart(DebugProbe_Handle *handle, uint8_t algorithm)

SPI_HASH_START — reset the running on-probe hash (0 = CRC-32, i.e. zlib).

uint16_t DebugProbe_SpiHashUpdate(DebugProbe_Handle *handle, uint16_t n)

SPI_HASH_UPDATE — clock n dummy bytes as a middle chunk of the held envelope, folding them into the hash. Returns no data.

Parameters:
uint16_t DebugProbe_SpiHashFinish(DebugProbe_Handle *handle, uint8_t *algorithm, uint8_t *digest, size_t digestCapacity, size_t *digestLen)

SPI_HASH_FINISH — collect the digest and clear the running state.

Parameters:
  • handle – The device.

  • algorithm – Receives the algorithm byte. Optional.

  • digest – Caller-allocated, LE; 4 bytes for CRC-32. digestLen receives bytes written.

  • digestCapacity – Capacity of digest in bytes.

  • digestLen – Receives the number of bytes written; 0 on failure. Optional.

uint16_t DebugProbe_SpiTransferList(DebugProbe_Handle *handle, const DebugProbe_SpiListEntry *entries, size_t count, DebugProbe_SpiListResult *out)

SPI_XFER_LIST — run count entries as one transaction list.

Parameters:
  • handle – The device.

  • entries – The list, in execution order; read during the call only.

  • count – 1..DebugProbe_SpiStatus.listMaxEntries (8 on this contract).

  • out – Filled whenever the 4-byte header arrived, on error too. Outcome 1 is SUCCESS with the flag set, not an error.

uint16_t DebugProbe_SpiControllerInit(DebugProbe_Handle *handle, SpiBitOrder bitOrder, SpiMode mode, SpiDataWidth dataWidth, SpiChipSelect chipSelect, SpiChipSelectPolarity chipSelectPol, uint32_t frequency)

SPI_INIT with CosmicSDK’s argument list (definitions.h enums).

uint16_t DebugProbe_SpiSetParameters(DebugProbe_Handle *handle, SpiBitOrder bitOrder, SpiMode mode, SpiDataWidth dataWidth, SpiChipSelect chipSelect, SpiChipSelectPolarity chipSelectPol, uint32_t frequency)

SPI_SET_PARAMS with CosmicSDK’s argument list.

uint16_t DebugProbe_SpiTransfer(DebugProbe_Handle *handle, const uint8_t *inData, uint16_t inDataLength, uint8_t *outData, size_t outCapacity, uint16_t transferLength, size_t *outLen)

One logical transfer of transferLength bytes (1..1024) under one CS envelope: inData first, dummy zeros for the rest, every clocked byte returned. Chunked over HID reports by the SDK, invisibly. A chunk that fails on the wire releases the chip select before the status is returned, so a failed transfer never leaves the session mid-envelope.

Note

At 16-bit width both lengths must be even and bytes are passed as the wire carries them (each pair one little-endian frame).

Parameters:
  • handle – The device.

  • inData – Bytes to clock out first; may be NULL when inDataLength is 0.

  • inDataLength – 0..transferLength.

  • transferLength – Total clocked bytes, 1..1024.

  • outCapacity – Capacity of outData in bytes.

  • outLen – Receives the number of bytes written. Optional.

  • outData – Caller-allocated, at least transferLength bytes; truncated to outCapacity, outLen receives bytes written.

uint16_t DebugProbe_SpiFlashDetect(DebugProbe_Handle *handle, const DebugProbe_FlashParams *override, DebugProbe_FlashParams *out)

JEDEC names the part, SFDP supplies the numbers, override (NULL for none) wins outright after the JEDEC liveness check. out receives the parameters in use.

uint16_t DebugProbe_SpiFlashGetParams(DebugProbe_Handle *handle, DebugProbe_FlashParams *out)

The parameters of the detected part.

uint16_t DebugProbe_SpiFlashRelease(DebugProbe_Handle *handle)

Forget the detected part (confirms a deferred page program first). Does NOT close the SPI session.

uint16_t DebugProbe_SpiFlashRead(DebugProbe_Handle *handle, uint32_t addr, uint32_t n, uint8_t *out, size_t outCapacity, size_t *outLen, DebugProbe_ProgressFn progress, void *user)

Read n bytes from addr into caller storage.

uint16_t DebugProbe_SpiFlashSectorErase(DebugProbe_Handle *handle, uint32_t addr)

One sector erase at a sector-aligned addr.

uint16_t DebugProbe_SpiFlashEraseRange(DebugProbe_Handle *handle, uint32_t addr, uint32_t n, DebugProbe_ProgressFn progress, void *user)

Erase every sector overlapping [addr, addr+n) with the largest aligned granularity; the footprint equals sector-at-a-time. Chip erase is never selected here.

uint16_t DebugProbe_SpiFlashChipErase(DebugProbe_Handle *handle)

Erase the whole part. Explicit by design.

uint16_t DebugProbe_SpiFlashProgram(DebugProbe_Handle *handle, uint32_t addr, const uint8_t *data, size_t len, DebugProbe_ProgressFn progress, void *user)

Program len bytes at addr, split on page boundaries. Erase is NOT implied.

uint16_t DebugProbe_SpiFlashHash(DebugProbe_Handle *handle, uint32_t addr, uint32_t n, uint32_t *crc32, DebugProbe_ProgressFn progress, void *user)

CRC-32 (zlib) of a span computed ON THE PROBE. DEBUGPROBE_FLASH_NO_HASH when the image does not advertise it.

uint16_t DebugProbe_SpiFlashVerifyFast(DebugProbe_Handle *handle, uint32_t addr, const uint8_t *data, size_t len, bool *matches, DebugProbe_ProgressFn progress, void *user)

Pass/fail verify via the probe hash — cannot name a byte.

uint16_t DebugProbe_SpiFlashVerify(DebugProbe_Handle *handle, uint32_t addr, const uint8_t *data, size_t len, bool *matches, uint32_t *mismatchAddr, DebugProbe_ProgressFn progress, void *user)

Verify a span: the hash for pass/fail when available, read-back to name the first differing byte otherwise. matches receives the verdict; mismatchAddr the absolute address of the first difference when it does not match (optional).

uint16_t DebugProbe_SpiFlashBlankCheck(DebugProbe_Handle *handle, uint32_t addr, uint32_t n, bool *blank, uint32_t *firstDirty)

Whether [addr, addr+n) is all 0xFF; firstDirty receives the first non-blank address when not (optional).

uint16_t DebugProbe_SpiBulkAvailable(DebugProbe_Handle *handle, bool *available)

Whether this board’s SPI vendor bulk interface can be opened from here. False on images without it, and on Windows until the firmware ships the MSOSv2 subset that binds WinUSB to it — the flash library then runs the HID path (~21.9 KB/s program vs ~184.8 KB/s over bulk).

uint16_t DebugProbe_SpiFlashProgramFast(DebugProbe_Handle *handle, uint32_t addr, const uint8_t *data, size_t len, bool *usedBulk, DebugProbe_ProgressFn progress, void *user)

SpiFlashProgram with the transport policy: over the bulk interface when it opens (the HID session is handed over and taken back; usedBulk true), the HID list path otherwise. Same bytes either way; verify afterwards as usual.

uint16_t DebugProbe_SpiFlashGetLastBulkStats(DebugProbe_Handle *handle, DebugProbe_SpiFlashBulkStats *out)

Counters of the last bulk program (zeros after an HID one).

struct DebugProbe_DeviceEntry
#include <DebugProbe_API_c.h>

One connected Atira, as reported by enumeration.

Fixed arrays rather than pointers: enumeration must not allocate on the caller’s behalf (see property 2 in the file comment).

Public Members

char path[DEBUGPROBE_PATH_MAX]

hidapi path, stable for the session.

char serial[DEBUGPROBE_SERIAL_MAX]

iSerial.

struct DebugProbe_DeviceInfo
#include <DebugProbe_API_c.h>

GET_DEVICE_INFO. hw_variant is 2 on the Rev A/B product board and 1 on an FRDM build — the cheap way to tell which pinmux an image needs, which the capability bitmask cannot answer.

Public Members

uint16_t capabilities

HID_CTRL_CAP_* bitmask.

uint8_t active_mode

LIVE mode; the persisted one is in settings.

struct DebugProbe_DeviceSettings
#include <DebugProbe_API_c.h>

GET_SETTINGS — the PERSISTED configuration, which can disagree with what the hardware is currently doing. targetProtocol is the persisted mode; DebugProbe_DeviceInfo::active_mode is the live one.

struct DebugProbe_UartConfig
#include <DebugProbe_API_c.h>

GET/SET_UART_CFG. ⚠ The firmware applies only flow control to the bridge; baud/dataBits/parity/stopBits are written to NVS and nothing reads them back, so a GET reports the persisted values rather than the live line coding. dataBits must be a legal value even when unused: the firmware range-checks nothing before persisting it.

struct DebugProbe_Cdc1Config
#include <DebugProbe_API_c.h>

GET/SET_CDC1_CFG. ⚠ A SET that changes something answers SUCCESS, persists, then RESETS the board ~100 ms later — the connection dies and the device re-enumerates. A SET that changes nothing does not reset.

struct DebugProbe_PinStatus
#include <DebugProbe_API_c.h>

GET_PIN_STATUS — live occupancy of the shared target-pin group.

Public Members

uint8_t holders

bitmask: bit0 RTT, 1 SWO, 2 UPDI, 3 ICSP, 4 DAP.

uint32_t generation

increments on every free->held edge.

bool captureUartValid

Whether the board reported the capture-UART byte at all. False means firmware older than fw-atira #118, which has no arbiter to report — that is NOT the same as reporting the arbiter free, and a consumer that conflates the two will claim nothing holds a resource it cannot see.

uint8_t captureUart

Holder of the capture-UART arbiter when captureUartValid: 0 free, 1 SWO, 2 UPDI, 0xFF no arbiter in this image.

⚠ It reports ONE arbiter row, the LPUART instance UPDI drives. On a revab board (fw-atira #82) SWO capture moves to LPUART1, so a live capture holds a row this byte does not report and 0 means only “UPDI is

not holding it”.

struct DebugProbe_SwdCoexistStatus
#include <DebugProbe_API_c.h>

GET_SWD_STATUS — the SWD bus shared between a host CMSIS-DAP session and the probe’s internal engine. Read-only diagnostics, and on RAM-constrained profiles the only observability there is.

Public Members

uint16_t msSinceHostTransfer

0xFFFF = no host transfer since boot.

struct DebugProbe_PowerReading
#include <DebugProbe_API_c.h>

POWER_GET_READING from the INA232 on the VDD_DUT rail. Voltage in mV and power in mW, like the host adapters; current in µA, because the monitor resolves 62.5 µA and a sleeping target draws under 1 mA.

struct DebugProbe_SignalVoltageCheck
#include <DebugProbe_API_c.h>

GET_SIGNAL_VOLTAGE_CHECK (fw-atira >= 1.1). state: 0 no supply on pin 1 (under 0.5 V), 1 match, 2 signal above the target’s supply (refused), 3 signal below it (VIH risk), 4 Atira powers the target, 5 signal on with no target supply for 2 s (back-powered through its I/O), 6 pin 1 over 5500 mV (reading it switches the rails off).

struct DebugProbe_SpiParams
#include <DebugProbe_API_c.h>

SPI controller parameters — the 9-byte blob of SPI_INIT/SET_PARAMS/ GET_PARAMS, in CosmicSDK’s enums (definitions.h): SpiBitOrder, SpiMode, SpiDataWidth (0 = 8-bit, 1 = 16-bit — the SDK translates to the literal width the wire carries), SpiChipSelect, SpiChipSelectPolarity.

Public Members

uint32_t frequency

SCK in Hz; firmware bounds 1 kHz .. 12 MHz today.

uint8_t bitOrder

SpiBitOrder

uint8_t mode

SpiMode 0..3

uint8_t dataWidth

SpiDataWidth

uint8_t chipSelect

SpiChipSelect; CS1..3 answer NOT_SUPPORTED unless routed

uint8_t chipSelectPol

SpiChipSelectPolarity

struct DebugProbe_SpiStatus
#include <DebugProbe_API_c.h>

SPI_GET_STATUS. Answers without a session (params zeroed then). The limits are LIVE values — a host uses them rather than compile-time defaults: hashMaxChunk depends on SCK, listMaxEntries on the image. Zero in any limit means the firmware predates that field.

Public Members

DebugProbe_SpiParams params

meaningful only when active

uint16_t hashMaxChunk

max SPI_HASH_UPDATE bytes for this session

uint16_t pollMaxUs

max poll budget of one list entry

uint8_t features

HID_CTRL_SPI_FEAT_* bitmap

uint8_t listMaxEntries

max entries of one SPI_XFER_LIST

uint8_t pollMaxIterations

max poll iterations of one list entry

bool active

a session is open

bool csHeld

an envelope is open

bool hashRunning

a hash was started and not finished

struct DebugProbe_SpiListEntry
#include <DebugProbe_API_c.h>

One entry of an SPI_XFER_LIST — behaves exactly like one SPI_TRANSFER (same flags, same transfer_len > payload dummy-tail rule). The poll fields are read only with DEBUGPROBE_SPI_LIST_POLL set, and a poll entry must carry both CS flags. payload is caller storage, read during the call only.

Public Members

const uint8_t *payload

tx bytes, caller storage, read during the call

uint16_t pollMaxUs

poll budget in microseconds

uint8_t flags

DEBUGPROBE_SPI_CS_* and DEBUGPROBE_SPI_LIST_* bits

uint8_t payloadLen

bytes at payload, <= 64

uint8_t transferLen

1..64; >= payloadLen

uint8_t pollOffset

byte of THIS entry’s reply to test

uint8_t pollMask

mask applied to that byte

uint8_t pollValue

done when (reply[offset] & mask) == value

uint8_t pollMaxIterations

poll iterations before giving up, 1..64

struct DebugProbe_SpiListResult
#include <DebugProbe_API_c.h>

SPI_XFER_LIST response. rx is the concatenated reply of every entry without DISCARD_RX, in entry order; the caller splits it with its own transfer lengths (the wire carries none). Outcome 1 = a poll hit its bound at entry index entriesExecuted; the entries after it did not run and no envelope is open. Filled on error responses too, since the firmware always sends the header.

Public Members

uint8_t entriesExecuted

entries that ran

uint8_t outcome

0 done, 1 poll bounded out

uint8_t pollIterations

of the last poll entry executed

uint8_t rxLen

bytes valid in rx

uint8_t rx[60]

concatenated replies of non-DISCARD entries

struct DebugProbe_FlashEraseType
#include <DebugProbe_API_c.h>

One erase granularity a NOR part advertises.

Public Members

uint32_t size

bytes erased by one command

uint8_t opcode

the erase opcode for that size

uint8_t reserved[3]

zero

struct DebugProbe_FlashParams
#include <DebugProbe_API_c.h>

Everything the flash library needs to drive one NOR part — filled by SFDP, seeded/named by the JEDEC table, or supplied by hand (every field is an override point). sectorSize/sectorEraseOp is the SMALLEST granularity; eraseTypes carries every advertised one, largest first, and may be empty for a manual override. source: 0 override, 1 table, 2 SFDP.

Public Members

uint32_t capacity

bytes

uint32_t pageSize

program page, bytes

uint32_t sectorSize

the SMALLEST erase granularity, bytes

DebugProbe_FlashEraseType eraseTypes[DEBUGPROBE_FLASH_MAX_ERASE_TYPES]

every advertised granularity, largest first

char name[DEBUGPROBE_FLASH_NAME_MAX]

NUL-terminated

uint8_t sectorEraseOp

erase opcode for sectorSize

uint8_t chipEraseOp

chip erase opcode (never issued automatically)

uint8_t readOp

read opcode

uint8_t programOp

page program opcode

uint8_t addressBytes

3 or 4

uint8_t source

0 override, 1 JEDEC table, 2 SFDP

uint8_t eraseTypeCount

entries used in eraseTypes

uint8_t reserved

zero

struct DebugProbe_SpiFlashBulkStats
#include <DebugProbe_API_c.h>

What the last bulk program did: page envelopes sent, previous-page polls that hit their bound, and the lists those cost in re-sends.

Public Members

uint32_t pages

page envelopes sent

uint32_t boundedPolls

previous-page polls that hit their bound

uint32_t extraLists

lists those cost in waits and re-sends

struct DebugProbe_Notification
#include <DebugProbe_API_c.h>

An unsolicited report from the device (resp_type 0x80).

data points into storage owned by the SDK and is valid only for the duration of the callback — copy it if you need it afterwards. That is the price of not allocating on the caller’s behalf, and it is the same deal CosmicSDK’s notification callback makes.

Public Members

uint16_t status

u16 since fw-atira v1.0 (#267).

struct DebugProbe_ResponseMismatch
#include <DebugProbe_API_c.h>

Why the last SDK_ERROR_WRONG_RESPONSE happened.

The status code says a response was malformed; it cannot say how. On the bench that gap cost a hand-rolled HID probe: RTT_GET_STATUS answered 13 bytes where the contract builds 14, and a bare 0xA000 reads like a host regression rather than an older firmware.

expected points at a string literal owned by the library — valid for the process lifetime, so unlike every other buffer in this header it needs no caller storage and must not be freed.

Public Members

uint8_t cmdId

HID_CTRL_CMD_* , or a feature-report id.

uint16_t actualLen

What the device actually sent.

const char *expected

What the SDK required, in prose.

struct DebugProbe_CoreState
#include <DebugProbe_API_c.h>

Core state as the debug verbs report it. pc is only meaningful while halted. stop_reason: 0 running, 1 request, 2 breakpoint, 3 watchpoint, 4 step, 5 reset.

struct DebugProbe_Breakpoint
#include <DebugProbe_API_c.h>

One FPB comparator in use: the id to clear it by, and its address.

struct DebugProbe_TargetFlashInfo
#include <DebugProbe_API_c.h>

The loaded algorithm’s FlashDevice (DevDscr) description.

Public Members

char deviceName[DEBUGPROBE_TFLASH_NAME_MAX]

DevDscr.DevName, NUL-terminated, informational only

uint8_t erasedValue

DevDscr.valEmpty

struct DebugProbe_TargetFlashReport
#include <DebugProbe_API_c.h>

What the last operation did, filled on success and on failure.

Public Members

bool targetTouched

false: refused before any write to the target

bool finalResetOk

false: target state unknown — detach and power-cycle

uint8_t failedRoutine

DEBUGPROBE_TFLASH_ROUTINE_*

uint32_t failedR0

the routine’s r0 when failedRoutine is not NONE

bool verifyMismatch

a readback differed (Verify, or Write with verify)

uint32_t firstMismatch

its first differing address, when verifyMismatch

struct DebugProbe_TargetFlashConnectStep
#include <DebugProbe_API_c.h>

One vendor connect step, by name.

struct DebugProbe_TargetFlashPackDevice
#include <DebugProbe_API_c.h>

One <device> of a .pack (C++ TargetFlashPackDevice).

Public Members

char name[DEBUGPROBE_TFLASH_PACK_TEXT_MAX]

Dname, what DebugProbe_TargetFlashLoadPackDevice takes

char vendor[DEBUGPROBE_TFLASH_PACK_TEXT_MAX]

Dvendor, else the pack’s publisher

char family[DEBUGPROBE_TFLASH_PACK_TEXT_MAX]

Dfamily

char reason[DEBUGPROBE_TFLASH_PACK_REASON_MAX]

empty when FLASHABLE

uint32_t connectStepCount

How many connect steps the SDK skips for this device; 0 unless NEEDS_CONNECT_STEPS. Read each with DebugProbe_TargetFlashGetPackDeviceConnectStep and pass them back to DebugProbe_TargetFlashLoadPackDevice.

uint32_t flashBase

the PDSC’s flash block (0/0 when none)

uint8_t support

DEBUGPROBE_TFLASH_PACK_*

bool multiCore

more than one <processor>

struct DebugProbe_TargetFlashPackVariant
#include <DebugProbe_API_c.h>

One <variant> of a .pack and the device it belongs to (C++ TargetFlashPackDevice::variants). Load by device.

Public Members

char variant[DEBUGPROBE_TFLASH_PACK_TEXT_MAX]

Dvariant: often the name printed on the chip

char device[DEBUGPROBE_TFLASH_PACK_TEXT_MAX]

its device’s name