Skip to content

Latest commit

 

History

History
341 lines (244 loc) · 10.2 KB

File metadata and controls

341 lines (244 loc) · 10.2 KB

C FFI API Reference

This page documents every function, struct, and typedef exported by the ferrite-ffi crate. The C header file is ferrite_sdk.h.

Error codes

typedef enum {
    FERRITE_OK              =  0,   // Success
    FERRITE_NOT_INITIALIZED = -1,   // ferrite_sdk_init() was not called
    FERRITE_ALREADY_INIT    = -2,   // ferrite_sdk_init() called more than once
    FERRITE_BUFFER_FULL     = -3,   // Metric buffer overflow (oldest evicted)
    FERRITE_KEY_TOO_LONG    = -4,   // Metric key exceeds 32 characters
    FERRITE_NULL_PTR        = -5,   // A required pointer argument was NULL
    FERRITE_ENCODING        = -6,   // Chunk encoding failed
    FERRITE_TRANSPORT       = -7,   // Transport callback returned an error
} ferrite_error_t;

All functions return ferrite_error_t. Check the return value after every call.


Initialization

ferrite_sdk_init

ferrite_error_t ferrite_sdk_init(
    const char                *device_id,
    const char                *firmware_version,
    uint64_t                   build_id,
    uint64_t                 (*ticks_fn)(void),
    const ferrite_ram_region_t  *ram_regions,
    uint32_t                   ram_region_count
);

Initialize the SDK. Call exactly once at firmware startup, before calling any other ferrite_* function.

Parameters:

Parameter Type Description
device_id const char* NUL-terminated device identifier. Must point to memory that lives for the entire program (typically a string literal).
firmware_version const char* NUL-terminated firmware version string. Same lifetime requirement.
build_id uint64_t First 8 bytes of the ELF .build_id section. Pass 0 if not available.
ticks_fn uint64_t (*)(void) Function returning the current monotonic tick count. Must not be NULL.
ram_regions const ferrite_ram_region_t* Array of valid RAM address ranges. May be NULL if ram_region_count is 0.
ram_region_count uint32_t Number of elements in the ram_regions array. Maximum 4.

Returns: FERRITE_OK on success, FERRITE_NULL_PTR if a required pointer is NULL, FERRITE_ALREADY_INIT if called more than once.

Example:

static uint64_t get_ticks(void) {
    return (uint64_t)k_uptime_ticks();
}

ferrite_ram_region_t regions[] = {
    { .start = 0x20000000, .end = 0x20040000 },
};

ferrite_error_t err = ferrite_sdk_init(
    "my-device-01",
    "1.2.3",
    0,
    get_ticks,
    regions,
    1
);

Reboot reason

ferrite_record_reboot_reason

ferrite_error_t ferrite_record_reboot_reason(uint8_t reason);

Record the reboot reason for the current boot cycle. Call after reading the MCU's reset-cause register.

Parameters:

Parameter Type Description
reason uint8_t Reason code (see table below)

Reason codes:

Code Name Description
0 Unknown Default / unrecognized
1 PowerOnReset Initial power-on
2 SoftwareReset AIRCR.SYSRESETREQ
3 WatchdogTimeout Watchdog timer expired
4 HardFault Cortex-M HardFault (set automatically by fault handler)
5 MemoryFault MPU violation
6 BusFault Bus error
7 UsageFault Undefined instruction, etc.
8 AssertFailed Application assert
9 PinReset External reset pin
10 BrownoutReset Supply voltage dropped
11 FirmwareUpdate Pre-update reset
12 UserRequested Application-initiated reset

Returns: FERRITE_OK or FERRITE_NOT_INITIALIZED.

ferrite_last_reboot_reason

ferrite_error_t ferrite_last_reboot_reason(uint8_t *out_reason);

Retrieve the reboot reason recorded by the previous boot. If no valid record exists, writes 0 (Unknown) to *out_reason.

Parameters:

Parameter Type Description
out_reason uint8_t* Output pointer for the reason code. Must not be NULL.

Returns: FERRITE_OK or FERRITE_NULL_PTR.


Metrics

ferrite_metric_increment

ferrite_error_t ferrite_metric_increment(const char *key, uint32_t delta);

Increment a counter metric. If the key does not exist, a new entry is created with value delta. If it exists, delta is added to the current value (wrapping at UINT32_MAX).

Parameters:

Parameter Type Description
key const char* NUL-terminated metric key, max 32 characters. Must not be NULL.
delta uint32_t Value to add to the counter.

Returns: FERRITE_OK, FERRITE_NOT_INITIALIZED, FERRITE_NULL_PTR, or FERRITE_KEY_TOO_LONG.

ferrite_metric_gauge

ferrite_error_t ferrite_metric_gauge(const char *key, float value);

Set a gauge metric. Overwrites any previous value for this key.

Parameters:

Parameter Type Description
key const char* NUL-terminated metric key, max 32 characters.
value float New gauge value.

Returns: FERRITE_OK, FERRITE_NOT_INITIALIZED, FERRITE_NULL_PTR, or FERRITE_KEY_TOO_LONG.

ferrite_metric_observe

ferrite_error_t ferrite_metric_observe(const char *key, float value);

Record a histogram observation. Updates min, max, sum, and count for the given key.

Parameters:

Parameter Type Description
key const char* NUL-terminated metric key, max 32 characters.
value float Observed value.

Returns: FERRITE_OK, FERRITE_NOT_INITIALIZED, FERRITE_NULL_PTR, or FERRITE_KEY_TOO_LONG.


Fault record

ferrite_last_fault

ferrite_error_t ferrite_last_fault(ferrite_fault_record_t *out);

Retrieve the fault record from the previous boot. If no valid fault is present, out->valid is set to false.

Parameters:

Parameter Type Description
out ferrite_fault_record_t* Output pointer for the fault record. Must not be NULL.

Returns: FERRITE_OK or FERRITE_NULL_PTR.

ferrite_fault_record_t

typedef struct {
    bool     valid;           // true if a fault was captured
    uint8_t  fault_type;      // 0=HardFault, 1=MemFault, 2=BusFault, 3=UsageFault
    uint8_t  _pad[2];

    // Hardware exception frame (pushed by CPU on fault entry)
    uint32_t r0, r1, r2, r3;
    uint32_t r12, lr, pc, xpsr;

    // Software-captured registers
    uint32_t r4, r5, r6, r7, r8, r9, r10, r11;
    uint32_t sp;

    // Stack snapshot: first 16 words above SP at fault time
    uint32_t stack_snapshot[16];

    // Cortex-M fault status registers
    uint32_t cfsr;    // Configurable Fault Status Register
    uint32_t hfsr;    // HardFault Status Register
    uint32_t mmfar;   // MemManage Fault Address Register
    uint32_t bfar;    // BusFault Address Register
} ferrite_fault_record_t;

Usage:

ferrite_fault_record_t fault;
ferrite_last_fault(&fault);

if (fault.valid) {
    printf("Fault type=%u at PC=0x%08X, LR=0x%08X\n",
           fault.fault_type, fault.pc, fault.lr);
    printf("CFSR=0x%08X HFSR=0x%08X\n", fault.cfsr, fault.hfsr);

    // Print stack snapshot
    for (int i = 0; i < 16; i++) {
        printf("  SP+%02d: 0x%08X\n", i * 4, fault.stack_snapshot[i]);
    }
}

Upload

ferrite_upload

ferrite_error_t ferrite_upload(
    const ferrite_transport_t  *transport,
    ferrite_upload_stats_t     *out_stats
);

Run a full blocking upload session. Sends all pending data (DeviceInfo, RebootReason, FaultRecord, Metrics, Trace, Heartbeat) through the transport callbacks.

On success, clears all uploaded data from the SDK buffers. On transport error, data is retained for the next attempt.

Parameters:

Parameter Type Description
transport const ferrite_transport_t* Transport descriptor. Must not be NULL. send_chunk must not be NULL.
out_stats ferrite_upload_stats_t* Optional output for upload statistics. May be NULL.

Returns: FERRITE_OK, FERRITE_NOT_INITIALIZED, FERRITE_NULL_PTR, FERRITE_TRANSPORT, or FERRITE_ENCODING.

ferrite_transport_t

typedef int32_t (*ferrite_send_chunk_fn)(
    const uint8_t *data,
    uint32_t       len,
    void          *ctx
);

typedef bool (*ferrite_is_available_fn)(void *ctx);

typedef struct {
    ferrite_send_chunk_fn   send_chunk;    // Required
    ferrite_is_available_fn is_available;  // Optional (NULL = always available)
    void                 *ctx;           // Opaque context forwarded to callbacks
} ferrite_transport_t;

The send_chunk callback must return 0 on success, non-zero on error. If it returns non-zero, the upload session is aborted and ferrite_upload() returns FERRITE_TRANSPORT.

The ctx pointer is forwarded to every callback invocation. Use it to pass peripheral handles, socket descriptors, or other transport state without global variables.

ferrite_upload_stats_t

typedef struct {
    uint32_t chunks_sent;
    uint32_t bytes_sent;
    bool     fault_uploaded;
    uint32_t metrics_uploaded;
    uint32_t trace_bytes_uploaded;
} ferrite_upload_stats_t;

Structs

ferrite_ram_region_t

typedef struct {
    uint32_t start;  // Inclusive start address
    uint32_t end;    // Exclusive end address
} ferrite_ram_region_t;

Defines a valid RAM address range for the fault handler's stack snapshot. The fault handler will only read addresses that fall within a registered region, preventing secondary faults from accessing invalid memory.


Thread safety summary

Function ISR-safe Thread-safe Reentrant
ferrite_sdk_init No No No
ferrite_record_reboot_reason Yes Yes Yes
ferrite_last_reboot_reason Yes Yes Yes
ferrite_metric_increment Yes Yes Yes
ferrite_metric_gauge Yes Yes Yes
ferrite_metric_observe Yes Yes Yes
ferrite_last_fault Yes Yes Yes
ferrite_upload No Yes (single caller) No

"ISR-safe" means the function can be called from an interrupt service routine. All metric functions use Cortex-M critical sections (interrupt disable/enable) and are safe from any context.

ferrite_upload must not be called from an ISR because the transport callback may block. It should be called from exactly one thread/task at a time.