Optional common components

These declarations come from public header files. Selection, lifecycle, supported execution modes and physical authorization remain bounded by the corresponding design and support records.

Byte transport, TLS and MQTT composition

byte_stream.h defines immediate partial reads and copied writes with finite absolute deadlines. SUCCESS reports local byte acceptance, not peer delivery; BUSY with zero bytes requires explicit owner progress. No caller buffer remains borrowed after a stream operation returns. The optional Nexus::LwIPTCP client implements this face over the pinned NO_SYS IPv4 stack. Products still own the executor, peer selection, trusted time, entropy and shutdown/reconnect policy.

Consumer

Selected target and header

Boundary

Generic Ethernet adapter caller

Nexus::LwIP, nexus/network/lwip_adapter.h

Nexus types; no supplier headers or profile macros

Generic TCP byte caller

Nexus::LwIPTCP, nexus/network/lwip_tcp.h

Opaque client and the existing readonly byte face

Static netif composition

Nexus::LwIPStorage, nexus/network/lwip_storage.h

Exact pinned netif/adapter layout, composition only

Static TCP composition

Nexus::LwIPTCPStorage, nexus/network/lwip_tcp_storage.h

Exact pinned PCB/pbuf client layout, composition only

The composition initializes lwIP once and supplies a live network adapter, caller-owned storage and a positive receive-frame budget. All raw stack APIs, callbacks, network service and clients share one serialized NO_SYS executor. Call facade data/control outside raw callbacks; nested cross-facade mutation is rejected with BUSY. No socket layer, worker, scheduler, lock, name registry or maximum opaque pool is created. A successful TCP start admits CONNECTING; it does not establish the connection. Its first finite connect deadline cannot be extended. The existing byte face is a stateful handle, not a readiness proof.

TCP writes use official copied admission: a positive partial count releases the caller input immediately, while queued data remains bounded stack storage. Later output failure cannot undo that acceptance. Diagnostics continue to report that failure, and subsequent data/service calls fail until explicit abort. RX holds at most one accepted pbuf chain; refused chains stay lwIP-owned. Only consumed bytes receive credit. Buffered bytes precede orderly FIN, and peer half-close still permits writes. A frame budget bounds acquisition, not the total wall time of arbitrary raw callbacks. Each nonzero byte attempt may perform one explicitly budgeted network pass.

Official PCB allocation shares the bounded stack pool and its reclamation policy. It may progress pending closes or reclaim TIME_WAIT, LAST_ACK, CLOSING and lower-priority active connections, invoking other clients’ error callbacks even if the new start later fails. Local rejection retains no new references for that client; it does not promise a globally unchanged stack.

After producers join, the owner consumes buffered RX and explicitly progresses and retries close on BUSY under the first finite close deadline. That deadline cannot be extended. Timeout requires explicit abort while storage stays live; abort discards local data and detaches callbacks. Successful close proves this client context’s final stack access. The official stack may still own deferred FIN and TIME_WAIT state. Preserve the network adapter, global pools, timers and unchanged clock domain until the product’s complete stack shutdown/restart procedure permits withdrawal. Client detachment does not prove global stack shutdown or MAC/PHY drain.

Ordinary TLS/MQTT consumers include tls.h or client.h and link Nexus::TLS or Nexus::CoreMQTT. Their public session types are opaque and expose no supplier headers or profile macros. Only the static composition translation unit selects Nexus::TLSStorage with nexus/tls/storage.h, or Nexus::CoreMQTTStorage with nexus/mqtt/core_mqtt_storage.h, to allocate the exact pinned backend layout. Keep explicit storage targets local to composition; fields are implementation state, not business control APIs or binary ABI promises. Products explicitly call nexus_add_tls() or nexus_add_coremqtt() to create the selected targets.

The TLS profile is one serialized TLS 1.2 client/PSA domain using ECDHE-ECDSA P-256 and AES-128-GCM/SHA-256. It requires explicit DER trust, trusted UTC and a reviewed entropy-quality assertion. Its 64 KiB caller arena and 512 B TX stage exclude session metadata, transport memory and stack. Join facade users, abort the session, then stop the runtime; failed or BUSY cleanup retains its resources. The MQTT 3.1.1 profile provides clean sessions and QoS0/1; callbacks borrow incoming views only until return. Explicit DISCONNECT and TLS close report local progress and do not replace lower-layer drain or peer acknowledgement. The component contracts detail network, TLS and MQTT ownership and fixed profile limits.

For both Ethernet adapter profiles, successful link output reports frame admission. A failed SETTLED TX outcome remains observable once through nx_lwip_adapter_service; until that observation, another link output cannot overwrite or reuse the TX buffer. Observing the error clears only the settled, unborrowed request. It adds no error queue or instance storage and does not reset the MAC, replay a packet or choose a product recovery policy. An ACTIVE or QUARANTINED borrow remains retained. The TCP byte facade keeps its existing connection-failure policy; frame-error observation does not promise recovery.

Selected lwIP RX payload loans

Select one singleton NO_SYS stack profile per image. The default Nexus::LwIP and Nexus::LwIPTCP profiles retain copied RX and their existing storage layouts. The explicit targets below select RX payload loans; CMake rejects an image combining copied and loaned profiles, including a copied TCP target combined with loaned adapter storage. These targets create no second stack, netif, executor, worker or allocator.

Consumer

Selected target and header

Boundary

Loaned RX adapter caller

Nexus::LwIPLoanedRX, nexus/network/lwip_loaned_rx.h

Opaque adapter; explicit loaned start

Loaned RX TCP byte caller

Nexus::LwIPTCPLoanedRX, nexus/network/lwip_tcp.h

Existing copied byte-stream contract

Static loaned RX composition

Nexus::LwIPLoanedRXStorage, nexus/network/lwip_loaned_rx_storage.h

Exact adapter, frame-slot and custom-pbuf storage

Static TCP composition over loaned RX

Nexus::LwIPTCPLoanedRXStorage, nexus/network/lwip_tcp_storage.h

Exact selected TCP layout; also provide loaned adapter storage

The owner initializes lwIP once and attaches with nx_lwip_loaned_adapter_start. Supply zero-initialized, disjoint adapter, TX, fragment-view, frame-slot and custom-pbuf-piece storage. Select a nonzero slot_count and at least slot_count * base.rx_capacity pieces, with fragment capacity sized for the actual provider geometry. MAC payload spans must also be disjoint from adapter, TX/view and slot/piece storage. Invalid acquired spans are released without delivery. All raw APIs, reference operations, callbacks, service and stop share the same serialized, nonreentrant task owner. Live or reentrant attachment cannot erase retained references or tokens.

Nexus::LwIPLoanedRXStorage -> adapter + caller slots/pieces
MAC exact RX loan -> copied REF header[136] -> immutable ROM tails
final pbuf_free -> slot ready -> owner service/stop -> exact MAC release

Each frame slot copies at most 136 B into its own writable PBUF_REF prefix. That prefix covers the 14 B Ethernet header, maximum 60 B IPv4 header and maximum 60 B TCP header, including the fields that official TCP input updates in place. The prefix can include payload; a frame of at most 136 B is copied entirely. Only bytes beyond the prefix reference the original immutable MAC fragments through PBUF_ROM tails. Raw consumers must treat those tails as read-only and clone before writing. This is RX payload-tail zero-copy; whole-frame and TX zero-copy are not provided. ICMP echo uses the official copy-for-reply path. VLAN delivery, IPv6, DHCP, DNS and IP reassembly remain unselected.

A retained head or tail pbuf reference keeps its frame slot and exact MAC loan live. The final custom-pbuf free only marks pieces returned; it never calls the provider or rearms DMA. Subsequent owner service or stop releases the exact loan after every piece’s final reference is gone. A failed release retains the token and storage and closes further adapter admission. Products first close PCBs and join raw users, callbacks, queues and observers. Stop returns BUSY while any pbuf reference remains and detaches only after exact RX release and the existing MAC/TX withdrawal obligations. Failed drain never revokes a loan.

Slot count is metadata capacity, not a provider capability or an ACK-progress promise. Concurrent acquisition also requires independent provider loans and enough descriptors for the actual frames. The maintained enhanced F407 and GD470 MAC engine supports independent held RX heads and reverse-order release in software models; this fact does not establish universal capacity, lossless operation or progress under arbitrary retained traffic. Products budget and release loans for their selected frame geometry and workload.

The selected loaned profile keeps two spare 512 B PBUF_POOL payload blocks; the copied profile keeps its existing 24 blocks. The 16 KiB arena and other fixed protocol pools remain unchanged. RX custom-pbuf metadata, 136 B prefixes, MAC buffers and the copied TX buffer are additional caller-supplied storage. TX and ICMP reply fallback may use the existing bounded RAM allocator. These counts require the curated organization fork’s narrow exemption of the explicit custom-RX/custom-pbuf profile from the stock PBUF_POOL/TCP_WND sizing heuristic. Every other stack sanity check remains active. This exemption does not establish stock-upstream admission or complete SRAM fit. Nominal pool counts are not a complete SRAM measurement.

C11 link-only external development probes use two frame slots, four pieces, a 2048 B main stack and zero libc heap. The selected images pass a 32 KiB SRAM budget. The copied-profile BIN bytes and caller storage match the same source baseline with the common TX-outcome improvement, for both reference chips.

Link-only reference

Copied RX flash / SRAM (B)

Loaned RX flash / SRAM (B)

STM32F407VE

32616 / 35416

33244 / 24344

GD32F470ZG

33920 / 35388

34548 / 24316

These probes do not provide a real MAC descriptor ring or payload buffers. The selected adapter costs 628 B more Flash and 11072 B less total SRAM in this exact fixture. Reducing the selected pool from 24 to two blocks saves 11616 B with unchanged adapter behavior and layout. These are image/link measurements; installed-SDK qualification and actual DMA/cache, PHY, throughput, latency and physical HIL evidence remain separate.

Reference software-host interoperability chain

FIG-32: Reference software-host data flow with two independent TCP legs and one end-to-end TLS session

FIG-32 is a reference host-test data flow, not a product architecture or MCU network qualification. Solid bidirectional edges carry the same ciphertext over two independent TCP connections: software Ethernet frames between the Nexus client and a test-only lwIP peer, then a host socket between the transparent relay and local Mosquitto. The dashed edge identifies the one TLS session, which terminates at the Nexus TLS client and Mosquitto; the relay does not decrypt or terminate TLS. Each lwIP process owns its own serialized stack and clock. Editable DOT and the network contract and maintained relay fixture define this figure’s source and lifetime boundaries.

The host fixtures exercise actual pinned stack and protocol implementations with software frame ports and controlled services. Direct POSIX TLS/MQTT fixtures and the full lwIP/TCP relay fixture retain their own execution evidence. Neither model Ethernet nor a real host broker proves Board wiring, physical PHY/DMA, MCU entropy quality, measured resource peaks, installed SDK acceptance or HIL.

byte_stream.h

Immediate partial byte transport without retained buffers.

Author

Nexus Team

struct nx_byte_stream_ops_t
#include <byte_stream.h>

Immutable methods for a serialized nonblocking byte stream.

Note

Every call has a finite absolute monotonic deadline in the transport’s explicit clock domain. Calls do not wait, create workers or retain input/output buffers after return. An accepted write copies bytes into the transport’s own bounded storage; it does not promise peer delivery. SUCCESS writes 1..requested bytes for a nonempty write, or reads 1..requested bytes. SUCCESS with read count zero means orderly EOF. BUSY has count zero and means retry after explicit owner progress. Other results are errors, never alternate encodings of would-block. Zero-byte calls return SUCCESS/count zero without underlying I/O. Output count is disjoint from all buffers and live transport storage. Transport, table and context outlive every consumer and its shutdown.

Public Members

nx_result_t (*write)(void *context, const uint8_t *data, size_t bytes, size_t *accepted, nx_time_us_t deadline)
nx_result_t (*read)(void *context, uint8_t *data, size_t bytes, size_t *received, nx_time_us_t deadline)
struct nx_byte_stream_t
#include <byte_stream.h>

Stable readonly face; no factory lookup, allocation or start.

Public Members

const nx_byte_stream_ops_t *ops
void *context

lwip_adapter.h

Explicit single-owner lwIP Ethernet copying adapter.

Author

Nexus Team

Typedefs

typedef struct nx_lwip_adapter nx_lwip_adapter_t

Backend storage is defined only by the explicit storage header.

Functions

nx_result_t nx_lwip_adapter_start(nx_lwip_adapter_t *adapter, const nx_lwip_config_t *config)

Attach one caller-owned netif without initializing MAC or PHY.

Note

Task-only, one serialized stack execution owner. Address configuration is static IPv4; the underlying stack is the pinned NO_SYS profile. Storage must be disjoint from configuration, TX bytes and RX views. Failure retains no new hardware borrow. Link starts down; only an explicit external PHY observation may bring it up.

Parameters:
  • adapter – [inout] Zero-initialized backend storage, not already live.

  • config – [in] Explicit configuration; copied without retaining it.

Returns:

Success, invalid inputs, or BUSY for an already attached netif.

nx_result_t nx_lwip_adapter_service(nx_lwip_adapter_t *adapter, size_t receive_budget)

Progress MAC, bounded complete RX frames and stack timer callbacks.

Note

Same task owner as every lwIP raw API/callback. Timer callback cost is governed by the fixed stack profile and application callbacks; this is not a hard bound on the entire invocation. The copying profile copies RX bytes before exact release. The explicit loaned-RX profile retains immutable payload tails until its custom-pbuf references end. A failed release retains its token and closes progress; stop retries release without feeding duplicate bytes into the stack. Inline and deferred TX failure remain observable before request reuse; while pending, new link output returns ERR_IF without admitting bytes. Success inline completion remains immediately reusable. Consuming an already-settled failure makes the TX request READY, without automatic reset, replay, adapter close or forced restart. The product chooses provider recovery; an actual unfinished borrow is never revoked.

Parameters:
  • adapter – [inout] Live storage, including any unfinished loans.

  • receive_budget – [in] Nonzero maximum acquired frames this invocation.

Returns:

Success, one pending settled TX failure, or provider/release/state error. A settled TX failure is consumed once before further progress.

Apply a proven external PHY fact to the MAC, then the netif.

Note

One task owner. Existing provider quiescence rules still apply. This does not negotiate, reset, power or prove the physical link.

Parameters:
  • adapter – [inout] Live, nonclosing adapter storage.

  • link – [in] Actual PHY observation, not a software default.

Returns:

Underlying MAC admission result; failure preserves netif flags.

nx_result_t nx_lwip_adapter_stop(nx_lwip_adapter_t *adapter)

Close adapter admission and detach only after actual MAC drain.

Note

The product first closes its PCBs, raw callbacks, queues and observers. This stops only the netif/MAC adapter, not the global lwIP stack or all application connections. A timeout or failed drain never revokes TX or RX loans; retry after explicit provider recovery. No automatic reset or replay occurs. Stop is idempotent after successful detachment.

Parameters:
  • adapter – [inout] Live storage retained on any unfinished withdrawal.

Returns:

Success after detachment; otherwise the actual withdrawal error.

uint32_t nx_lwip_port_now_ms(void)

Product-supplied monotonic milliseconds for lwIP timers.

Note

Task owner only. Supply this symbol once per selected stack profile; its clock source and lifetime must cover every pending stack timer.

Returns:

Wrapping milliseconds in the stack’s unchanged live time domain.

uint32_t nx_lwip_port_random_u32(void)

Product-supplied random word; no libc or timestamp fallback.

Note

Called by the serialized stack owner. Source failure must enter the product’s nonreturning fault path; returning a fixed value is allowed only in an explicitly unqualified host test fixture.

Returns:

A word from the product’s admitted random source.

void nx_lwip_port_assert(const char *message)

Product-supplied nonreturning stack invariant failure observation.

Note

Task owner. Never return or release quarantined hardware storage merely because the stack reported an assertion. No default abort is linked.

Parameters:
  • message – [in] Static diagnostic text, not a retained ownership token.

struct nx_lwip_config_t
#include <lwip_adapter.h>

Explicit static IPv4 configuration and caller-owned frame storage.

Note

The serialized stack owner initializes lwIP once before attachment. The port, clock, TX buffer and views outlive attachment and all loans. Clock and provider deadlines use the same live monotonic domain. No default worker, lock, PHY, address, DHCP, DNS or heap is provided.

Public Members

const nx_eth_frames_port_t *port
nx_clock_t clock
nx_time_us_t tx_timeout_us
uint8_t *tx_buffer
size_t tx_capacity
nx_eth_fragment_t *rx_views
size_t rx_capacity
uint8_t hardware_address[6]
uint8_t address[4]
uint8_t netmask[4]
uint8_t gateway[4]

lwip_loaned_rx.h

Explicit immutable RX-payload loan profile for lwIP.

Author

Nexus Team

Typedefs

typedef struct nx_lwip_rx_slot nx_lwip_rx_slot_t

Exact selected backend slot, defined by its storage target.

typedef struct nx_lwip_rx_piece nx_lwip_rx_piece_t

Exact selected custom-pbuf piece, not a packet allocator.

Functions

nx_result_t nx_lwip_loaned_adapter_start(nx_lwip_adapter_t *adapter, const nx_lwip_loaned_config_t *config)

Attach the explicitly selected payload-zero-copy RX profile.

Note

Task-only, same serialized nonreentrant NO_SYS owner as all raw calls. Select only the loaned profile and its storage target in this image. Ethernet/ARP/max IPv4/max TCP headers are copied; immutable payload tails are loaned. This is not whole-frame or TX zero-copy. No VLAN, IPv6, DHCP, DNS, reassembly, worker, heap or physical link is added. MAC payload spans must be disjoint from the adapter, TX/view storage and all selected slot/piece metadata; admission releases invalid loans. Final custom-pbuf frees only mark a slot ready. Subsequent service or stop performs exact provider release. Failed release preserves the token and closes admission. Stop returns BUSY while references remain. Products close PCBs and all raw observers before adapter withdrawal.

Parameters:
  • adapter – [inout] Zero-initialized selected backend storage.

  • config – [in] Disjoint stable storage description; copied on success.

Returns:

Success, invalid configuration, or an already attached owner.

struct nx_lwip_loaned_config_t
#include <lwip_loaned_rx.h>

Caller-selected RX loan and fragment metadata, without a hidden pool.

Note

Slots and pieces are zero-initialized and remain live through final pbuf release, exact MAC release and adapter detachment. Supply at least slot_count * base.rx_capacity pieces. Each slot owns one copied 136-byte writable header prefix. Remaining packet payload references immutable MAC bytes; raw consumers must not write those PBUF_ROM tail bytes. The exact provider descriptor geometry still limits concurrent loans.

Public Members

nx_lwip_config_t base
nx_lwip_rx_slot_t *slots
size_t slot_count
nx_lwip_rx_piece_t *pieces
size_t piece_count

lwip_loaned_rx_storage.h

This selected-profile header belongs only at static composition. Its fields describe retained frame and pbuf storage, not a mutable consumer interface.

Exact selected RX-loan/custom-pbuf composition storage.

Author

Nexus Team

struct nx_lwip_rx_piece

One caller-owned custom-pbuf header with its unique owning slot.

Note

Private backend fields; raw users own only normal pbuf references.

Public Members

struct pbuf_custom custom
nx_lwip_rx_slot_t *slot
struct nx_lwip_rx_slot

One exact RX token shared by all retained pieces of that frame.

Note

The union provides eight-byte alignment in the maintained profile. A free callback only decrements references; it never touches hardware. A slot cannot be reused until the provider accepts the exact release. Raw users cannot access a pbuf after returning its final reference.

Public Members

nx_eth_frames_rx_loan_t loan
nx_lwip_rx_piece_t header
uint64_t alignment
uint8_t bytes[136]
union nx_lwip_rx_slot prefix
size_t live_pieces
bool held

lwip_tcp.h

Bounded copied TCP client for one NO_SYS stack.

Author

Nexus Team

Version

1.0.0

Date

2026-11-02

Copyright

Copyright (c) 2026 Nexus Team

Typedefs

typedef struct nx_lwip_tcp nx_lwip_tcp_t

Enums

enum nx_lwip_tcp_state_t

Values:

enumerator NX_LWIP_TCP_IDLE
enumerator NX_LWIP_TCP_CONNECTING
enumerator NX_LWIP_TCP_ESTABLISHED
enumerator NX_LWIP_TCP_CLOSING
enumerator NX_LWIP_TCP_CLOSED
enumerator NX_LWIP_TCP_FAILED

Functions

nx_result_t nx_lwip_tcp_start(nx_lwip_tcp_t *client, const nx_lwip_tcp_config_t *config, nx_time_us_t deadline)

Admit one asynchronous connect with a copied configuration.

Note

Initialize lwIP once. SUCCESS never proves ESTABLISHED. Rejection retains no new PCB/pbuf/config reference for this client. An admitted client requires explicit close or abort.

Note

PCBs share the official stack pool and its reclamation policy. Allocation may progress pending closes and reclaim TIME_WAIT, LAST_ACK, CLOSING or lower-priority active PCBs. This can invoke other connections’ error callbacks, even if this start later fails. Local rejection does not promise a globally unchanged stack.

Parameters:
  • client – [inout] Zeroed exact storage with all former users joined.

  • config – [in] Live adapter, copied IPv4 peer, nonzero port/budget.

  • deadline – [in] First finite absolute connect deadline.

Returns:

SUCCESS admits CONNECTING. BUSY rejects an occupied domain. INVALID rejects configuration; EXHAUSTED/IO report stack admission.

nx_result_t nx_lwip_tcp_service(nx_lwip_tcp_t *client)

Perform one budgeted network pass and progress this connection.

Note

No wait or worker. Fatal errors remain sticky until explicit abort. Expiry does not release PCBs, pbufs or any underlying MAC loan.

Parameters:
  • client – [inout] Live client owned by the serialized task executor.

Returns:

SUCCESS for progress; BUSY for connecting/congestion/reentry; TIMEOUT for the locked deadline, or an actual provider/stack error.

nx_result_t nx_lwip_tcp_try_write(nx_lwip_tcp_t *client, const uint8_t *data, size_t bytes, size_t *accepted, nx_time_us_t deadline)

Copy an immediate partial write into bounded stack storage.

Note

Positive acceptance is TCP queue admission, not peer delivery. Delivery/acknowledgement policy belongs to the caller. A later output failure cannot undo an already copied acceptance. Invalid aliased counts are rejected before writing that count.

Parameters:
  • client – [inout] Live serialized task owner, outside raw callbacks.

  • data – [in] Stable input for this call; never retained after return.

  • bytes – [in] Requested length; zero needs no clock/provider progress.

  • accepted – [out] Disjoint copied count; zero on valid BUSY/error.

  • deadline – [in] Finite absolute admission deadline in adapter time.

Returns:

SUCCESS with a positive copied count, BUSY without admission, TIMEOUT before admission, STATE while closing, or a sticky failure.

nx_result_t nx_lwip_tcp_try_read(nx_lwip_tcp_t *client, uint8_t *data, size_t bytes, size_t *received, nx_time_us_t deadline)

Copy partial RX data and credit only bytes actually consumed.

Note

One accepted pbuf chain is held. Refused chains remain lwIP-owned. Buffered bytes precede FIN; peer half-close still permits writes. TLS independently authenticates close-notify. Invalid aliased counts are rejected before writing that count.

Parameters:
  • client – [inout] Serialized task owner; reads may drain while closing.

  • data – [out] Unretained output disjoint from all known live storage.

  • bytes – [in] Capacity; zero needs no clock/provider progress.

  • received – [out] Disjoint count; zero on valid BUSY/error or EOF.

  • deadline – [in] Finite absolute attempt deadline in adapter time.

Returns:

SUCCESS with data, SUCCESS/count zero for orderly TCP EOF, BUSY without data, TIMEOUT, STATE when detached, or sticky failure.

nx_result_t nx_lwip_tcp_close(nx_lwip_tcp_t *client, nx_time_us_t deadline)

Close admission and detach after explicit local drain.

Note

CONNECTING may close before establishment. Callbacks detach before successful tcp_close; its PCB must never be accessed afterwards. The pinned stack can defer FIN allocation while returning success. FIN/TIME_WAIT belong to the still-live stack/network. This operation does not prove global or PHY drain. Timeout requires explicit abort.

Parameters:
  • client – [inout] Producers joined; reads may drain retained RX.

  • deadline – [in] First finite close deadline; never implicitly extended.

Returns:

SUCCESS detaches this context. BUSY retains held/refused RX, unacknowledged TX or a failed close. TIMEOUT retains all ownership.

nx_result_t nx_lwip_tcp_abort(nx_lwip_tcp_t *client)

Explicitly discard data, detach callbacks and abort an owned PCB.

Note

BUSY releases nothing. The error callback already freed its PCB. Product code separately drains the MAC/netif after all clients join.

Parameters:
  • client – [inout] Exclusive storage after facade users have joined.

Returns:

SUCCESS after local cleanup, including a cold client; BUSY while any facade operation/callback executes; INVALID for a null client.

const nx_byte_stream_t *nx_lwip_tcp_stream(const nx_lwip_tcp_t *client)

Return the existing readonly byte face without progressing it.

Note

Readonly query in the same serialized task domain. A face is not connection readiness; its data methods return the actual state.

Parameters:
  • client – [in] Storage retained through every facade user.

Returns:

Stable face while initialized, including CONNECTING/FAILED; NULL before admission or after successful close/abort.

nx_result_t nx_lwip_tcp_diagnostic(const nx_lwip_tcp_t *client, nx_lwip_tcp_diagnostic_t *diagnostic)

Copy a readonly owner snapshot without progressing the stack.

Note

Use the serialized executor. A snapshot neither admits I/O nor authorizes release. Detached queries never follow old borrowed state.

Parameters:
  • client – [in] Live or locally detached storage, still allocated.

  • diagnostic – [out] Output disjoint from known live control/data.

Returns:

SUCCESS for the snapshot; INVALID for null or aliased output.

struct nx_lwip_tcp_config_t
#include <lwip_tcp.h>

One copied IPv4 peer and an explicit network progress budget.

Note

Network storage and its clock epoch outlive every client. They also outlive detached FIN/TIME_WAIT state in the stack.

Note

One serialized NO_SYS executor owns raw APIs and all clients. Call facade data/control outside raw callbacks. Nested mutation across facade instances returns BUSY without recursive progress.

Note

Nonzero I/O may service at most receive_budget Ethernet frames. No worker, DNS, reconnect policy or instance registry is added.

Public Members

nx_lwip_adapter_t *network
size_t receive_budget
uint8_t address[4]
uint16_t port
struct nx_lwip_tcp_diagnostic_t
#include <lwip_tcp.h>

Owner snapshot; it grants no permission to mutate a connection.

Public Members

nx_lwip_tcp_state_t state
nx_result_t result
int stack_error
size_t pending_receive
size_t pending_transmit
bool peer_fin

lwip_tcp_storage.h

This exact-profile header is for static composition. Its fields do not extend the generic client interface.

Exact pinned TCP client storage; composition only.

Author

Nexus Team

Version

1.0.0

Date

2026-11-02

Copyright

Copyright (c) 2026 Nexus Team

struct nx_lwip_tcp
#include <lwip_tcp_storage.h>

Public Members

nx_lwip_tcp_config_t config
nx_byte_stream_t stream
struct tcp_pcb *pcb
struct pbuf *receive
nx_time_us_t connect_deadline
nx_time_us_t close_deadline
nx_lwip_tcp_diagnostic_t diagnostic
uint16_t receive_offset
bool initialized
bool active
bool callback_active

tls.h

Explicit bounded TLS 1.2 client and crypto-domain lifecycle.

Author

Nexus Team

Defines

NX_TLS_ARENA_BYTES
NX_TLS_TX_STAGE_BYTES
NX_TLS_DER_MAX

Typedefs

typedef struct nx_tls_runtime nx_tls_runtime_t
typedef struct nx_tls_session nx_tls_session_t

Enums

enum nx_tls_entropy_quality_t

Source-quality declaration, never inferred from a health check.

Values:

enumerator NX_TLS_ENTROPY_UNKNOWN
enumerator NX_TLS_ENTROPY_FULL_SOURCE
enum nx_tls_state_t

Values:

enumerator NX_TLS_IDLE
enumerator NX_TLS_INITIALIZED
enumerator NX_TLS_HANDSHAKING
enumerator NX_TLS_ESTABLISHED
enumerator NX_TLS_CLOSING
enumerator NX_TLS_CLOSED
enumerator NX_TLS_FAILED

Functions

nx_result_t nx_tls_runtime_start(nx_tls_runtime_t *runtime, const nx_tls_runtime_config_t *config, nx_time_us_t deadline)

Initialize one explicit PSA/arena domain, never once per connection.

Note

No worker/heap/lock. A second live domain is BUSY. Every library entropy callback is guarded by the shorter operation/entropy deadline.

Parameters:
  • runtime – [inout] Zeroed static backend storage.

  • config – [in] Configuration copied; referenced resources stay borrowed.

  • deadline – [in] Finite absolute initialization deadline.

Returns:

Success, permission for undeclared quality, or actual bounded error.

nx_result_t nx_tls_runtime_stop(nx_tls_runtime_t *runtime)

Stop PSA only after all sessions and outside consumers have joined.

Note

No session cleanup calls this operation implicitly. Product code must not use PSA outside this explicit domain or reset its global allocator.

Parameters:
  • runtime – [inout] Exclusive live domain owner.

Returns:

BUSY with a session; success frees PSA then wipes the whole arena.

nx_result_t nx_tls_initialize(nx_tls_session_t *session, const nx_tls_config_t *config, nx_time_us_t deadline)

Prepare one client using public Mbed TLS APIs and required peer auth.

Note

No raw credential input is retained after return. Port and staging stay borrowed until abort; failures clean partial backend state.

Parameters:
  • session – [inout] Zeroed static backend storage.

  • config – [in] Explicit trust, hostname, optional client identity/port.

  • deadline – [in] Finite initialization deadline, including key import.

Returns:

Success, BUSY for the occupied domain, or no-admission failure.

nx_result_t nx_tls_handshake_step(nx_tls_session_t *session, nx_time_us_t deadline)

Perform one public handshake step under the first locked deadline.

Note

First step publicly reseeds PSA with a finite guard. Trusted UTC is sampled coherently; loss during a library date check is latched and overrides a successful library result. Renegotiation is disabled.

Parameters:
  • session – [inout] Initialized exclusive client.

  • deadline – [in] Finite deadline; later calls cannot extend the first.

Returns:

Success only after verified auth; BUSY for progress/WANT; fatal error.

nx_result_t nx_tls_service(nx_tls_session_t *session)

Progress the one accepted plaintext staging block without waiting.

Note

WANT retries keep the backend’s exact original pointer/length. An expired queued write fails the session; only abort releases its stage.

Parameters:
  • session – [inout] Live serialized owner.

Returns:

Success when no pending bytes; BUSY for WANT; sticky fatal error.

nx_result_t nx_tls_try_write(nx_tls_session_t *session, const uint8_t *data, size_t bytes, size_t *accepted, nx_time_us_t deadline)

Copy an immediate partial write into the explicit bounded stage.

Note

Original input may be reused immediately. Pending stage is never overwritten, replayed or discarded on timeout. Late failures are sticky. An invalid aliased count is rejected before writing that count.

Parameters:
  • session – [inout] Established serialized client.

  • data – [in] Immutable input, not retained after return.

  • bytes – [in] Requested bytes; zero performs no I/O.

  • accepted – [out] Disjoint copied count; zero on BUSY/error.

  • deadline – [in] Finite absolute deadline retained for accepted bytes.

Returns:

Success means copied admission, not peer delivery; BUSY or error.

nx_result_t nx_tls_try_read(nx_tls_session_t *session, uint8_t *data, size_t bytes, size_t *received, nx_time_us_t deadline)

Try to copy authenticated plaintext without retaining caller output.

Note

Raw transport EOF without close-notify is a sticky truncation error. An expired preflight retains session state and creates no new borrow. An invalid aliased count is rejected before writing that count. A pending stage with a later effective deadline returns BUSY without automatic I/O; the owner explicitly services that earlier acceptance.

Parameters:
  • session – [inout] Established serialized client.

  • data – [out] Unretained output disjoint from all live session storage.

  • bytes – [in] Writable capacity; zero performs no I/O.

  • received – [out] Disjoint count; zero on BUSY/error or auth EOF.

  • deadline – [in] Finite absolute deadline for this nonblocking attempt.

Returns:

Success/bytes, BUSY, authenticated close-notify EOF, or error.

nx_result_t nx_tls_close_step(nx_tls_session_t *session, nx_time_us_t deadline)

Send close-notify with an explicit first locked deadline.

Note

Pending app bytes must first drain. This never closes the underlying transport or proves the peer consumed data. Abort still frees storage.

Parameters:
  • session – [inout] Exclusive live client after producers have joined.

  • deadline – [in] Finite absolute deadline; no implicit extension.

Returns:

Success means local alert accepted, BUSY for WANT, or sticky error.

nx_result_t nx_tls_abort(nx_tls_session_t *session)

Free synchronous session state and wipe its stage after final access.

Note

BUSY retains all storage; the outer owner retries after callback join. No network I/O or replay. Underlying transport closure remains external. The pinned builtin synchronous crypto profile retains no callback after return. PSA domain/arena stays live for the next explicit session.

Parameters:
  • session – [inout] Exclusive owner, all external facade users joined.

Returns:

Success after cleanup (also cold), BUSY if crypto/BIO is executing.

const nx_byte_stream_t *nx_tls_stream(const nx_tls_session_t *session)

Return an existing no-borrow byte face; no start or allocation.

nx_result_t nx_tls_diagnostic(const nx_tls_session_t *session, nx_tls_diagnostic_t *diagnostic)

Copy current owner diagnosis to unretained disjoint output.

struct nx_tls_utc_t
#include <tls.h>

Explicit trusted UTC, separate from monotonic operation deadlines.

Note

SUCCESS means trusted Unix seconds. Unknown/untrusted/unavailable time returns an error. Calendar years are 1970..9999 within the selected time_t representation. The product owns authentication and clock policy.

Public Members

nx_result_t (*read)(void *context, int64_t *seconds)
void *context
struct nx_tls_runtime_config_t
#include <tls.h>

One serialized crypto owner, caller arena and finite entropy source.

Note

Arena is max_align_t-aligned and exactly NX_TLS_ARENA_BYTES. All faces and opaque contexts outlive every session. FULL_SOURCE explicitly declares 8 bits/byte to the selected PSA entropy-driver API; software health checks and this enum do not establish physical qualification. The profile disables operating-system entropy and seed fallbacks. Clock advances in one unchanged monotonic domain throughout callbacks.

Public Members

void *arena
size_t arena_bytes
const nx_entropy_port_t *entropy
nx_clock_t clock
nx_tls_utc_t utc
nx_time_us_t entropy_timeout_us
nx_tls_entropy_quality_t entropy_quality
struct nx_tls_config_t
#include <tls.h>

Client credentials copied by the backend during initialization.

Note

DER only, no implicit files, key discovery or default trust. hostname has hostname_length non-NUL bytes followed by NUL, length 1..253. Mutual-authentication certificate and key are both supplied or absent. TX staging is exactly 512 caller-owned bytes, disjoint from runtime, session, arena and transport state. It stays borrowed until abort. The single serialized executor owns all session and PSA calls.

Public Members

nx_tls_runtime_t *runtime
const nx_byte_stream_t *transport
const uint8_t *trust_der
size_t trust_bytes
const uint8_t *client_der
size_t client_bytes
const uint8_t *key_der
size_t key_bytes
const char *hostname
size_t hostname_length
uint8_t *tx_stage
size_t tx_stage_bytes
struct nx_tls_diagnostic_t
#include <tls.h>

Read-only diagnosis; no snapshot grants permission to operate.

Public Members

nx_tls_state_t state
nx_result_t result
int library_error
uint32_t verify_flags
size_t pending_plaintext
bool want_read
bool want_write
bool peer_closed

client.h

Bounded synchronous MQTT 3.1.1 client over explicit streams.

Author

Nexus Team

Typedefs

typedef struct nx_mqtt_session nx_mqtt_t
typedef struct nx_mqtt_memory nx_mqtt_memory_t

Enums

enum nx_mqtt_event_kind_t

Values:

enumerator NX_MQTT_EVENT_PUBLISH
enumerator NX_MQTT_EVENT_PUBACK
enumerator NX_MQTT_EVENT_SUBACK
enumerator NX_MQTT_EVENT_UNSUBACK

Functions

nx_time_us_t nx_mqtt_port_now_us(void)

Product clock shared by all clients and their transports.

Note

Required context-free hook matches upstream’s timer API. Never silently change epoch/domain. UINT64_MAX is invalid. No active-instance global registry is used by this adapter.

Returns:

Absolute monotonic microseconds in one stable boot/domain

void nx_mqtt_port_assert(const char *file, unsigned line)

Nonreturning product invariant-failure hook.

Note

Must not reclaim DMA or transport storage on an assertion.

Parameters:
  • file – [in] Static source location

  • line – [in] Source line

nx_result_t nx_mqtt_init(nx_mqtt_t *client, const nx_mqtt_config_t *config, const nx_mqtt_memory_t *memory)

Initialize exact caller storage without opening transport.

Note

Task-only, no I/O/heap. All storage and port contexts remain valid and exclusively owned through successful deinit.

Parameters:
  • client – [inout] Zero-initialized or deinited metadata

  • config – [in] Valid stable ports; values copied, contexts borrowed

  • memory – [inout] Disjoint network, QoS and control storage

Returns:

SUCCESS, INVALID, STATE, OVERFLOW or EXHAUSTED

nx_result_t nx_mqtt_connect(nx_mqtt_t *client, const nx_mqtt_connect_t *connect, nx_mqtt_call_t call)

Send clean-session CONNECT and await CONNACK synchronously.

Note

Does not connect TCP/TLS. The product provides transport and authentication policy. Failed CONNECT is not replayed.

Parameters:
  • client – [inout] Initialized inactive client on a fresh open stream

  • connect – [in] Legal MQTT UTF-8 fields, borrowed for this call

  • call – [in] Finite absolute deadline and nonzero I/O budget

Returns:

SUCCESS, admission error or sticky session/transport failure

nx_result_t nx_mqtt_publish(nx_mqtt_t *client, const nx_mqtt_publish_t *publish, uint16_t *packet_id, nx_mqtt_call_t call)

Publish QoS0/1 with call-scoped topic and payload loans.

Note

QoS1 records remain borrowed through deinit. PUBACK signals confirmation; the application owns message retry/data retention. No persistent-session replay or QoS2 is provided.

Parameters:
  • client – [inout] Connected serialized client

  • publish – [in] Valid UTF-8 topic and byte payload; no aliases

  • packet_id – [out] Written on success only; zero for QoS0

  • call – [in] Finite deadline and nonzero I/O budget

Returns:

SUCCESS for local stream admission, never broker delivery

nx_result_t nx_mqtt_subscribe(nx_mqtt_t *client, const char *topic, size_t topic_size, uint8_t qos, uint16_t *packet_id, nx_mqtt_call_t call)

Send one bounded subscription request.

Parameters:
  • client – [inout] Connected client with a free caller control slot

  • topic – [in] Call-scoped valid MQTT UTF-8 filter

  • topic_size – [in] Nonzero bytes, at most UINT16_MAX

  • qos – [in] Requested maximum zero or one

  • packet_id – [out] Written on successful send only

  • call – [in] Explicit deadline and I/O budget

Returns:

SUCCESS means sent; SUBACK event reports grant/refusal

nx_result_t nx_mqtt_unsubscribe(nx_mqtt_t *client, const char *topic, size_t topic_size, uint16_t *packet_id, nx_mqtt_call_t call)

Send one bounded unsubscribe request.

Parameters:
  • client – [inout] Connected client with a free caller control slot

  • topic – [in] Call-scoped valid MQTT UTF-8 filter

  • topic_size – [in] Nonzero bytes, at most UINT16_MAX

  • packet_id – [out] Written on successful send only

  • call – [in] Explicit deadline and I/O budget

Returns:

SUCCESS means sent; UNSUBACK is observed during process

nx_result_t nx_mqtt_process(nx_mqtt_t *client, nx_mqtt_call_t call)

Caller-driven receive, acknowledgments and keepalive step.

Note

Callback views expire on return; copy needed data there. No implicit timer/task registration or automatic replay.

Parameters:
  • client – [inout] Connected serialized client

  • call – [in] Explicit deadline and I/O budget

Returns:

SUCCESS, BUSY for incomplete data, or sticky failure

nx_result_t nx_mqtt_disconnect(nx_mqtt_t *client, nx_mqtt_call_t call)

Send MQTT DISCONNECT without closing the transport.

Parameters:
  • client – [inout] Connected serialized client

  • call – [in] Explicit deadline and I/O budget

Returns:

SUCCESS means local admission, not TCP/TLS drain

nx_result_t nx_mqtt_deinit(nx_mqtt_t *client)

End local borrows after all synchronous calls return.

Note

No I/O. The product separately drains/closes TCP/TLS before another MQTT session; deinit cannot retract accepted bytes.

Parameters:
  • client – [inout] Inactive initialized client, including failed client

Returns:

SUCCESS, BUSY for reentry or INVALID

nx_result_t nx_mqtt_fault(const nx_mqtt_t *client)

Inspect sticky failure in the same serialized task context.

Parameters:
  • client – [in] Initialized instance

Returns:

First failure, SUCCESS, or STATE for an inactive instance

struct nx_mqtt_event_t
#include <client.h>

Callback-scoped facts; all pointers expire with callback return.

Public Members

nx_mqtt_event_kind_t kind
uint16_t packet_id
uint8_t qos
bool retain
bool duplicate
nx_result_t status
const char *topic
size_t topic_size
const uint8_t *payload
size_t payload_size
struct nx_mqtt_call_t
#include <client.h>

Explicit finite operation deadline and transport-call allocation.

Public Members

nx_time_us_t deadline
uint32_t io_budget
struct nx_mqtt_config_t
#include <client.h>

Caller-owned ports retained until deinit.

Note

All calls/callbacks use one serialized task context. Event and optional idle callbacks must be bounded and may not reenter this client. Idle may service/wait on lower layers; no worker, lock, scheduler or implicit reconnect is created. Idle SUCCESS/BUSY permit retry; other results fail the session. Event views are not NUL-terminated strings.

Public Members

nx_byte_stream_t stream
void (*event)(void *context, const nx_mqtt_event_t *event)
void *event_context
nx_result_t (*idle)(void *context, nx_time_us_t deadline)
void *idle_context
struct nx_mqtt_connect_t
#include <client.h>

Transient CONNECT parameters; this profile always uses clean session.

Public Members

const char *client_id
size_t client_id_size
const char *username
size_t username_size
const uint8_t *password
size_t password_size
uint16_t keepalive_seconds
struct nx_mqtt_publish_t
#include <client.h>

Transient publish; QoS1 confirmation is a later PUBACK event.

Public Members

const char *topic
size_t topic_size
const uint8_t *payload
size_t payload_size
uint8_t qos
bool retain

TMP117 one-shot sampling contract

Select Nexus::TMP117 for the device protocol and Nexus::TMP117I2C for its settled I2C adapter through the firmware target’s LIBRARIES. These optional CMake targets add no generated device category or competing configuration input. The product supplies an already configured, fixed-address endpoint, a monotonic clock, nonzero clock domain/epoch and the expected existing digital offset. ADD0 wiring, power, bus scheduling and physical recovery remain external. The I/O ownership architecture still applies; no sensor worker, heap, address scan or additional owner framework is introduced.

The reviewed device is TI TMP117 with complete identity 0x0117, using one-shot mode and one conversion with averaging disabled. Initialization checks identity, EEPROM readiness and lock, verifies the existing offset, then requests and reads back shutdown. It preserves unrelated configuration bits. Once shutdown is issued, a failed write or verification retains the same port, configuration and clock as an uncertain uninitialized instance; cleanup uses its own deadline. Earlier failures do not acquire a new binding. begin clears stale readiness before requesting one conversion; poll reads readiness and then the temperature. Each register read writes the pointer and repeated-START reads two MSB-first bytes. Only the synchronous endpoint transaction is accepted: every return, including errors, releases its descriptors and TX/RX spans. An async-only endpoint cannot be substituted for this settled contract.

A sample is published only on SUCCESS and contains independent numeric values. BUSY and errors leave the complete output unchanged. Signed raw and existing offset values use 1/128 Celsius per LSB. micro_celsius rounds to the nearest microdegree, with exact ties away from zero; the full signed format conversion fits int32_t. The reviewed output range is -55 to 150 Celsius after the chip’s existing offset. POR, saturation and values outside that range return IO. The chip already applies its offset: the driver verifies and reports it without adding it twice, programming calibration or modifying EEPROM.

observed reuses nx_io_timestamp_t with microsecond rate, explicit domain and epoch, SERVICE_OBSERVATION provenance and unknown physical uncertainty. It is the time of successful register-read completion. The conversion occurred between conversion_started_at and observed.ticks; neither field is a hardware conversion timestamp. To enforce conservative maximum age, compare the current time against the start bound after validating domain, epoch and rate. A recent register read alone does not prove freshness. Copies outlive device stop without retaining device, transport or sample-buffer references; the consumer must still honor the clock continuity assumptions.

All calls use one serialized task executor and finite absolute deadlines. Poll checks the conversion deadline before and after exchange. A successful not-ready read returns BUSY while retaining conversion metadata. Any transport error, including transport BUSY, terminates sampling and requires explicit resync; a CONFIG read clears readiness, so a subsequent failed temperature read must not be retried as cached zero or as an endless not-ready conversion. A second poll after one successful sample returns STATE. Known overlapping control/output spans are rejected; the caller keeps opaque context and borrowed bus storage disjoint because their extents cannot be inferred by the generic driver.

cancel uses a separate finite cleanup deadline and succeeds only after a shutdown readback. It cannot preempt a synchronous exchange. Failed cleanup retains the binding and external physical-recovery responsibility; a timeout or error never proves physical stop. Retry cancellation or perform external recovery, then explicitly reinitialize a closed instance. Only after calls and outer owner users have joined may stop detach the software binding. Stop has no I/O and does not power off the part, release Board resources or erase an unresolved physical-recovery duty. An owner must not enqueue a synchronous stack transaction behind its own executor.

The protocol follows TI SNOSD82D, June 2018 revised September 2022, sections 6.5 and 7.3-7.6 (official data sheet). One-shot conversion takes 13/15.5/17.5 ms minimum/typical/maximum at AVG=00; the caller includes bus and scheduling margin. Power-up readiness requires 1.5 ms and is reported through bus/EEPROM status rather than a hidden sleep. The reviewed Zephyr comparison is drivers/sensor/ti/tmp11x at commit 413b789deb391d3a37d06b463288a5fe765ee57e; no driver source is copied.

Software model tests cover signed conversion, rounding, existing offset, readiness, failure cuts, deadlines, cancellation, independent instances and settled generic-owner integration. ARM link probes use the maintained F407 and GD470 empty assemblies with an explicitly unconnected software endpoint. They establish C11 linking and resource cost only. Device accuracy, PCB wiring, I2C waveforms, power-up behavior, real conversion latency and cancellation require physical HIL and remain unexecuted. A station must record the exact device ID, ADD0 address, rail/power-up timing, pull-ups, bus frequency, known temperature reference, offset, clock identity, failure injection and joined shutdown result.

tmp117.h

Explicit settled TMP117 one-shot sampling and provenance.

Author

Nexus Team

Functions

nx_result_t nx_tmp117_init(nx_tmp117_t *device, nx_tmp117_transport_port_t transport, const nx_tmp117_config_t *config, nx_time_us_t deadline)

Validate ID 0117h, locked EEPROM, offset and shutdown.

Note

No scan, reset, sleep, EEPROM write, worker or Board action. Use a separate cleanup deadline to cancel, or retry init on that same binding. A different binding requires joined software stop; external uncertain-state recovery remains the owner’s duty. Failed write is not a device reset.

Parameters:
  • device – [inout] Fresh zero/stopped or same-binding uncertain storage

  • transport – [in] Copied on success or uncertain shutdown write

  • config – [in] Stable explicit facts, not overlapping device

  • deadline – [in] Finite absolute deadline, shared across accesses

Returns:

SUCCESS, BUSY for power-up/EEPROM, or exact transport error; unsupported identity, offset mismatch and unlocked EEPROM reject without writes. Pre-write failure keeps no new binding. Once shutdown write is issued, failure retains the same port/config/clock as uncertain and uninitialized.

nx_result_t nx_tmp117_begin(nx_tmp117_t *device, nx_time_us_t deadline)

Begin one fresh conversion with averaging disabled.

Note

Clears stale readiness before OS admission. BUSY retains conversion metadata only, never a stack/caller buffer. Failure after I/O closes sampling until explicit resync.

Parameters:
  • device – [inout] Initialized nonmeasuring exclusive device

  • deadline – [in] Finite conversion/read deadline in the same clock

Returns:

SUCCESS, INVALID, BUSY, STATE, TIMEOUT or transport error

nx_result_t nx_tmp117_poll(nx_tmp117_t *device, nx_tmp117_sample_t *sample)

Observe readiness and publish one complete fresh sample.

Note

Reads CONFIG clear readiness. A later temperature-read failure is terminal and requires resync, never cached zero or endless ready retry. Any transport error, including BUSY, closes sampling until resync; only a successful not-ready read retains the conversion. Repeated poll after success is STATE. Output is disjoint from device, opaque port/clock context storage and borrowed bus storage; only known spans can be checked. POR/saturation and values outside the reviewed range return IO.

Parameters:
  • device – [inout] Previously begun conversion, same task executor

  • sample – [out] Aligned separate output, unchanged on every error

Returns:

SUCCESS, INVALID, BUSY before ready, STATE or transport/IO

nx_result_t nx_tmp117_cancel(nx_tmp117_t *device, nx_time_us_t deadline)

Request and verify shutdown under a separate cleanup budget.

Note

Cannot preempt a synchronous exchange. Cancel failure never proves physical stop; no MCU span survives a port return. Success does not close a bus owner or join its observers.

Parameters:
  • device – [inout] Live or uncertain same binding, serialized owner

  • deadline – [in] Finite cleanup deadline, not an expired sample one

Returns:

SUCCESS only after shutdown observation; other results keep recovery responsibility and may require init resync

void nx_tmp117_stop(nx_tmp117_t *device)

Drop software binding after calls and outer owners join.

Note

No physical I/O. Not power-off, verified cancellation, Board release or erasure of external uncertain-state duty. A caller requiring physical shutdown first completes cancel or external recovery. Callback-time calls do nothing.

Parameters:
  • device – [inout] Quiescent instance with no in-progress call

struct nx_tmp117_transport_port_t
#include <tmp117.h>

Synchronous register exchange, settled on every return.

Note

Read writes one register byte then repeated-START reads two bytes; write sends register plus two MSB-first bytes. The serialized task owner keeps context and clock alive through use, uncertain cleanup and joined software stop. Every result releases TX/RX spans, including TIMEOUT/CANCELLED. No asynchronous submit or retained stack span is permitted.

Public Members

void *context
nx_result_t (*exchange)(void *context, const uint8_t *tx, size_t tx_bytes, uint8_t *rx, size_t rx_bytes, nx_time_us_t deadline)
nx_clock_t clock
struct nx_tmp117_config_t
#include <tmp117.h>

Explicit clock identity and expected existing calibration.

Note

Nonzero domain/epoch follow nx_io_timestamp_t. The owner changes epoch on discontinuity/reset/rate change. Offset is already applied by the chip; this driver only verifies and reports it, never programs calibration or EEPROM.

Public Members

uint32_t clock_domain
uint32_t clock_epoch
int16_t expected_offset_lsb
struct nx_tmp117_sample_t
#include <tmp117.h>

Independent copied sample, published only on SUCCESS.

Note

micro_celsius rounds raw/128 Celsius to nearest microdegree, ties away from zero. raw/offset use 1/128 Celsius per LSB; offset is not added again. Reviewed output is -55..150C. observed is software register-read completion with unknown physical uncertainty, never hardware conversion time. Conversion occurred within [conversion_started_at, observed.ticks] in that same domain/epoch. A consumer can use the lower bound for conservative logical-age checks; recent read completion alone does not establish freshness. All fields are values, with no retained device/payload references. Copies survive stop; clock-domain assumptions still require the caller’s continuity/lifetime contract.

Public Members

int32_t micro_celsius
int16_t raw_lsb
int16_t offset_lsb
nx_time_us_t conversion_started_at
nx_io_timestamp_t observed
struct nx_tmp117_t
#include <tmp117.h>

Exact caller-owned instance, fresh zero before first init.

Note

Task-only single executor, no concurrent/reentrant calls. Uncertain physical state retains the port for explicit cancel/resync; it creates no MCU buffer loan. Fields are implementation state, never permission to reclaim a loan.

Public Members

nx_tmp117_transport_port_t transport
nx_tmp117_config_t config
nx_time_us_t deadline
nx_time_us_t conversion_started_at
nx_time_us_t last_clock
uint16_t base_configuration
bool initialized
bool measuring
bool uncertain
bool in_call

tmp117_i2c.h

TMP117 transport over an explicit settled I2C endpoint.

Author

Nexus Team

Functions

nx_tmp117_transport_port_t nx_tmp117_i2c_transport(const nx_i2c_endpoint_t *endpoint, nx_clock_t clock)

Bind an existing polling endpoint without I/O or discovery.

Note

Actual ADD0 wiring/address 48h..4Bh remains external. An async-only endpoint is rejected. No submit fallback borrows stack descriptors. Exactly one serialized bus executor performs exchanges without nested owner queues.

Parameters:
  • endpoint – [in] Explicit fixed-address face, alive until stop/join

  • clock – [in] Same live domain as endpoint transaction deadlines

Returns:

Settled transport, or an invalid zero port for bad methods

bmp280.h

BMP280 calibration and explicit forced-conversion driver.

Author

Nexus Team

Functions

nx_result_t nx_bmp280_parse_calibration(const uint8_t *bytes, size_t length, nx_bmp280_calibration_t *calibration)

Parse the exact 24-byte little-endian calibration block.

Parameters:
  • bytes – [in] Register block beginning at 0x88

  • length – [in] Must be exactly 24

  • calibration – [out] Written only on success

Returns:

SUCCESS or INVALID for length/zero pressure divisor

nx_result_t nx_bmp280_compensate(const nx_bmp280_calibration_t *calibration, uint32_t raw_temperature, uint32_t raw_pressure, nx_bmp280_sample_t *sample)

Compensate one raw sample using checked integer arithmetic.

Parameters:
  • calibration – [in] Parsed calibration

  • raw_temperature – [in] Unsigned 20-bit ADC value

  • raw_pressure – [in] Unsigned 20-bit ADC value

  • sample – [out] Written only on success

Returns:

SUCCESS, INVALID for malformed/overflow calibration or IO for disabled ADC sentinel/out-of-datasheet-range physical output

nx_result_t nx_bmp280_init(nx_bmp280_t *device, nx_bmp280_transport_port_t transport, nx_time_us_t deadline)

Validate chip ID and load calibration, without scanning.

Note

Task context; failure leaves initialized false and no borrow. Does not soft-reset the part or create a wait loop/task. Retry BUSY explicitly.

Parameters:
  • device – [out] Zero-initialized unused instance

  • transport – [in] Synchronous settled port and live monotonic clock

  • deadline – [in] Absolute deadline for all initialization accesses

Returns:

SUCCESS, BUSY for NVM update, or transport/identity error

nx_result_t nx_bmp280_begin(nx_bmp280_t *device, nx_time_us_t deadline)

Start one forced temperature/pressure conversion.

Note

Task-only serialized driver owner; oversampling x1/x1.

Parameters:
  • device – [inout] Initialized non-measuring instance

  • deadline – [in] Absolute deadline covering conversion and reads

Returns:

SUCCESS, BUSY, TIMEOUT or transport error

nx_result_t nx_bmp280_poll(nx_bmp280_t *device, nx_bmp280_sample_t *sample)

Poll conversion without an implicit worker or blocking delay.

Note

Task-only. Every port call releases temporary buffers before return. BUSY retains device conversion state, never stack or caller buffers. After terminal failure, begin may retry; the external owner chooses policy.

Parameters:
  • device – [inout] Instance with a previously started conversion

  • sample – [out] Written only on SUCCESS

Returns:

SUCCESS, BUSY while converting, TIMEOUT or transport error

void nx_bmp280_stop(nx_bmp280_t *device)

Stop software use after all synchronous calls have exited.

Note

Does not power off or reset a physical part. Sensor-internal conversion can finish without accessing MCU storage. No MCU borrow remains.

Parameters:
  • device – [inout] Quiesced driver instance

struct nx_bmp280_transport_port_t
#include <bmp280.h>

Synchronous settled SPI transaction port.

Note

exchange always releases every TX/RX buffer before returning, including TIMEOUT/error. One CS interval covers all bytes; mode 0 or 3, 8-bit words, <=10 MHz. Caller serializes this device and its bus owner. Driver stack transactions never cross asynchronous borrowing boundaries.

Public Members

void *context
nx_result_t (*exchange)(void*, const uint8_t*, uint8_t*, size_t, nx_time_us_t deadline)
nx_clock_t clock
struct nx_bmp280_calibration_t
#include <bmp280.h>

Register calibration, owned by one device instance.

Public Members

uint16_t t1
int16_t t2
int16_t t3
uint16_t p1
int16_t p2
int16_t p3
int16_t p4
int16_t p5
int16_t p6
int16_t p7
int16_t p8
int16_t p9
struct nx_bmp280_sample_t
#include <bmp280.h>

Output is valid only on successful conversion/compensation.

Public Members

int32_t centi_celsius
uint32_t pressure_pa
struct nx_bmp280_t
#include <bmp280.h>

Explicit device context, no Board pins or automatic sampling task.

Public Members

nx_bmp280_transport_port_t transport
nx_bmp280_calibration_t calibration
nx_time_us_t deadline
nx_time_us_t earliest_ready
bool initialized
bool measuring

bmp280_spi.h

Optional BMP280 adapter over a fixed SPI endpoint.

Author

Nexus Team

Functions

nx_bmp280_transport_port_t nx_bmp280_spi_transport(const nx_spi_endpoint_t *endpoint, nx_clock_t clock)

Bind a real polling SPI endpoint as settled transport.

Parameters:
  • endpoint – [in] Fixed endpoint kept alive throughout device use

  • clock – [in] Same monotonic domain as IO transfer deadlines

Returns:

Narrow transport; no global discovery or CS selection

bus_owner.h

Explicit bounded multi-producer, single-executor adapter.

Author

Nexus Team

Functions

nx_result_t nx_bus_owner_init(nx_bus_owner_t *owner, nx_owner_slot_t *slots, size_t capacity, nx_owner_guard_port_t guard, nx_owner_executor_port_t executor, nx_clock_t clock, const nx_wait_port_t *wake)

Initialize unused owner/slot storage.

Note

Startup context; no task, worker, timer or heap is created.

Parameters:
  • owner – [out] Unused caller-owned adapter storage

  • slots – [in] Exact queue capacity, no maximum pool

  • capacity – [in] Number of slots, greater than zero

  • guard – [in] Live short exclusion port

  • executor – [in] Single real execution port

  • clock – [in] Same monotonic domain as request deadlines

  • wake – [in] Optional static executor notification, or NULL

Returns:

SUCCESS or INVALID

nx_result_t nx_bus_owner_submit(nx_bus_owner_t *owner, nx_request_t *request, void *operation, const nx_wait_port_t *completion, nx_owner_ticket_t *ticket)

Establish the chain’s unique admission.

Note

Task multi-producer context. Free-slot admission and FIFO insertion use constant metadata work under the guard. An exhausted epoch permanently retires its slot. Deadline includes queue residence. Caller must not modify request, operation or buffers after admission. A notification error after admission cannot change SUCCESS to rejection; executor must recheck/pump periodically.

Parameters:
  • owner – [inout] Live accepting adapter

  • request – [inout] Prepared READY storage, retained until SETTLED

  • operation – [in] Executor-specific descriptor and payload storage

  • completion – [in] Optional static caller wake port, or NULL

  • ticket – [out] Stable cancellation identity, valid on SUCCESS

Returns:

SUCCESS means ACCEPTED; rejection retains zero references

nx_result_t nx_bus_owner_cancel(nx_bus_owner_t *owner, nx_owner_ticket_t ticket)

Submit cancellation through stable adapter storage.

Note

Task multi-producer context. No request pointer is accepted. Queued cancellation settles without starting. Active cancellation drains cooperatively; an irreversible operation may already have transferred data.

Parameters:
  • owner – [inout] Live adapter

  • ticket – [in] Previously accepted slot/epoch

Returns:

SUCCESS when marked, STATE for stale/released identity

nx_result_t nx_bus_owner_service(nx_bus_owner_t *owner)

Advance at most one bounded execution step.

Note

Task/explicit loop only. Consumers never service through wait. Keep calling during stop until idle; no callback creates a worker.

Parameters:
  • owner – [inout] Live adapter, called by its unique executor

Returns:

SUCCESS for progress/idle, BUSY for provider wait/contention, or provider error while retaining ownership for continued recovery

void nx_bus_owner_stop(nx_bus_owner_t *owner)

Close admission and request every accepted operation to stop.

Note

Task context. Executor must keep servicing/draining while producers wait/join. Stop is not settlement or storage reclamation.

Parameters:
  • owner – [inout] Live adapter

bool nx_bus_owner_idle(nx_bus_owner_t *owner)

Test whether execution and completion publication have exited.

Note

Join producers and any wake publishers before reclaiming owner, slots, guard or notifications. No future submit/cancel is permitted.

Parameters:
  • owner – [inout] Live adapter

Returns:

True if no queue/active/service publisher remains

struct nx_owner_guard_port_t
#include <bus_owner.h>

Explicit bounded metadata exclusion port.

Note

Task producer calls only. enter/leave must serialize all producers and the executor. Never hold this guard over start/service/cancel, waiting, payload copies or notification callbacks. State restores incoming interrupt mask when an architecture guard is used. Port storage stays live.

Public Members

void *context
uintptr_t (*enter)(void*)
void (*leave)(void*, uintptr_t)
struct nx_owner_executor_port_t
#include <bus_owner.h>

One real execution owner, injected without OS dependency.

start SUCCESS borrows operation until service SUCCESS. BUSY or any start error retains zero operation references/hardware effects; an error after partial start must instead accept and report through service. service SUCCESS proves all hardware/IRQ/deferred accesses stopped, writes final result/count, and releases the operation. BUSY still borrows. Other service errors retain ownership and require continued recovery/service. cancel requests drain; it never by itself releases operation. Callbacks run only in the externally scheduled executor, outside adapter metadata guard.

Note

terminal_authority selects providers that observe deadlines and latch their first terminal hardware fact themselves. Their final result survives late cancellation/publication. Other executors use adapter deadline/cancellation results. Queued deadlines always belong to the adapter.

Public Members

void *context
nx_result_t (*start)(void*, void *operation, nx_time_us_t deadline)
nx_result_t (*service)(void*, nx_result_t *result, size_t *transferred)
nx_result_t (*cancel)(void*)
bool terminal_authority
struct nx_owner_ticket_t
#include <bus_owner.h>

Stable control identity; never dereference a stale request pointer.

Public Members

size_t slot
uint64_t epoch
struct nx_owner_slot_t
#include <bus_owner.h>

Exact caller-owned slot, linked in either the free or FIFO chain; initialize only with owner init.

Public Members

nx_request_slot_t identity
void *operation
nx_wait_port_t completion
size_t next
bool cancel_requested
bool cancel_sent
struct nx_bus_owner_t
#include <bus_owner.h>

Explicit adapter state; external application supplies all storage.

Public Members

nx_owner_slot_t *slots
size_t capacity
size_t head
size_t tail
size_t active
size_t free_head
nx_owner_guard_port_t guard
nx_owner_executor_port_t executor
nx_clock_t clock
nx_wait_port_t wake
nx_result_t cancellation_result
bool accepting
bool servicing

clock_domain.h

Explicit clock consumers and epoch-bound drain control.

Author

Nexus Team

Version

1.0.0

Date

2026-10-11

Copyright

Copyright (c) 2026 Nexus Team

Typedefs

typedef struct nx_clock_domain nx_clock_domain_t

Opaque provider, statically supplied by its privileged owner.

typedef struct nx_clock_lease nx_clock_lease_t

One stable caller-owned consumer token.

Note

Zero-initialize before first acquisition. On SUCCESS the provider borrows this exact object; do not copy, mutate or reclaim it until release succeeds. Internal fields are not application controls. A release is the provider’s final access, not proof that a peripheral has stopped. Release only after that consumer’s IRQ, DMA and observer drain.

Enums

enum nx_clock_power_mode_t

Only shallow sleep preserves the established clock/time domain.

Values:

enumerator NX_CLOCK_SHALLOW_SLEEP
enumerator NX_CLOCK_DEEP_STOP
enumerator NX_CLOCK_DYNAMIC_RUN

Functions

nx_result_t nx_clock_domain_acquire(nx_clock_domain_t *domain, nx_clock_lease_t *lease)

Acquire one admitted clock consumer without waiting.

Note

Privileged Thread or configurable IRQ only; same CPU, saved-mask metadata guard. NMI/HardFault/SMP excluded. Capacity bounds token/alias scans. Token remains borrowed until successful release, even while admission is closed.

Returns:

SUCCESS, BUSY for closed admission, EXHAUSTED for budget, or INVALID/STATE/CONTEXT with no retained token or effects

nx_result_t nx_clock_domain_release(nx_clock_domain_t *domain, nx_clock_lease_t *lease)

Remove the exact retained token after consumer drain.

Note

Same contexts as acquire. Copied tokens cannot release the original. There is no callback or last access after SUCCESS.

Returns:

SUCCESS or INVALID/STATE/CONTEXT without removing a borrow

nx_result_t nx_clock_domain_close(nx_clock_domain_t *domain, nx_clock_barrier_t *control)

Close admission and return the current epoch control.

Note

Serialized privileged Thread only. No waiting, cancellation, clock writes or implicit consumer shutdown. Idempotent in the same closed epoch; output must not alias live storage.

nx_result_t nx_clock_domain_quiescent(nx_clock_barrier_t control)

Validate closed admission and zero retained consumers.

Note

Same CPU privileged Thread. This certifies only explicitly enrolled consumers. It does not authorize PLL reprogramming, suspend kernel Tick or change the Core deadline domain.

Returns:

SUCCESS, BUSY while consumers remain, STATE for stale/open control, INVALID or CONTEXT; no state changes

nx_result_t nx_clock_domain_reopen(nx_clock_barrier_t control)

Reopen a drained domain under a new admission epoch.

Note

Serialized privileged Thread. Does not restart the clock or reinterpret existing deadlines. Actual cold clock changes additionally require all Tick/time providers stopped and a new explicit deadline domain; this API performs neither.

Returns:

SUCCESS, BUSY, STATE, EXHAUSTED or CONTEXT without changes

struct nx_clock_lease
#include <clock_domain.h>

One stable caller-owned consumer token.

Note

Zero-initialize before first acquisition. On SUCCESS the provider borrows this exact object; do not copy, mutate or reclaim it until release succeeds. Internal fields are not application controls. A release is the provider’s final access, not proof that a peripheral has stopped. Release only after that consumer’s IRQ, DMA and observer drain.

Public Members

nx_clock_domain_t *owner
struct nx_clock_lease *next
uint64_t epoch
struct nx_clock_barrier_t
#include <clock_domain.h>

Epoch-bound close control and quiescence evidence.

Note

A value copy is allowed. This is not an authorization token or proof about unregistered consumers. Domain storage lives longer than every copy. A successful reopen invalidates all prior controls without resetting the epoch.

Public Members

nx_clock_domain_t *domain
uint64_t epoch

dp83848.h

Explicit DP83848 identity, reset and observed link mechanism.

Author

Nexus Team

Defines

NX_DP83848_TI_ID
NX_DP83848_NS_ID
NX_DP83848_10_HALF
NX_DP83848_10_FULL
NX_DP83848_100_HALF
NX_DP83848_100_FULL

Functions

nx_result_t nx_dp83848_probe(nx_dp83848_t *phy, nx_time_us_t deadline)

Read exact supported identity; mismatch never becomes a default PHY.

Parameters:
  • phy – [inout] Explicit MDIO face, address and expected supported model.

  • deadline – [in] Finite absolute MDIO clock deadline.

Returns:

Success, UNSUPPORTED for identity mismatch, or MDIO error.

nx_result_t nx_dp83848_reset(nx_dp83848_t *phy, nx_time_us_t deadline)

Bounded BMCR soft reset and observed self-clearing acknowledgement.

Note

Task-only finite absolute deadline; reset restraps the device and clears configured truth. This is not a GPIO, power or strap proof.

Parameters:
  • phy – [inout] Proved identity and caller-owned component state.

  • deadline – [in] Finite absolute MDIO clock deadline.

Returns:

Success after real reset acknowledgement, or state/MDIO error.

nx_result_t nx_dp83848_configure(nx_dp83848_t *phy, const nx_dp83848_mode_t *mode, nx_time_us_t deadline)

Start explicit negotiation or fixed mode, never wait for fake link.

Note

Task-only; identity must be proved. SUCCESS means registers configured, not autonegotiation complete. Failures retain configured=false.

Parameters:
  • phy – [inout] Proved identity, kept live through operations.

  • mode – [in] Explicit fixed mode or negotiation advertisement.

  • deadline – [in] Finite absolute MDIO clock deadline.

Returns:

Success means configured registers; otherwise no configured truth.

Observe latch-low BMSR twice and DP83848 PHYSTS speed/duplex truth.

Note

Task-only; output changes only on SUCCESS. up requires actual link and complete autonegotiation when selected. Protocol or remote fault does not invent speed/link. MAC application remains an external action.

Parameters:
  • phy – [inout] Probed and configured caller-owned component.

  • link – [out] Observed value, separate from component storage.

  • deadline – [in] Finite absolute MDIO clock deadline.

Returns:

Success copies observed link; other results preserve output.

struct nx_dp83848_mode_t
#include <dp83848.h>

External policy explicitly selects autonegotiation or fixed mode.

Public Members

uint8_t advertisement
bool autonegotiation
bool full_duplex
uint16_t speed_mbps
struct nx_dp83848_t
#include <dp83848.h>

Caller-owned PHY state; no board address, reset GPIO or worker default.

Note

expected_id selects TI or NS model, ignoring revision nibble only. One task owner serializes this component and the shared MDIO port.

Public Members

const nx_mdio_port_t *mdio
uint32_t expected_id
uint8_t address
bool probed
bool configured
nx_dp83848_mode_t mode

file_flash.h

Native persistent file Flash model with fault injection.

Author

Nexus Team

Version

1.0.0

Date

2026-10-09

Copyright

Copyright (c) 2026 Nexus Team

Functions

nx_storage_status_t nx_file_flash_open(nx_file_flash_t *flash, const char *path, size_t size, size_t erase_size, size_t program_size)

Open an exclusively locked persistent host Flash model.

Note

Task-only POSIX model. Does not qualify MCU Flash or actual power loss; existing file size mismatch is rejected without truncation.

Parameters:
  • flash – [out] Unused caller-owned storage

  • path – [in] Regular-file path; symlink traversal rejected

  • size – [in] Exact persistent byte size

  • erase_size – [in] Uniform erase block bytes

  • program_size – [in] Aligned program bytes, 1..256

Returns:

OK or INVALID/IO; failed open retains no file descriptor

void nx_file_flash_close(nx_file_flash_t *flash)

Close the host file after all store users have quiesced.

Note

No future port calls are permitted until explicit reopen.

Parameters:
  • flash – [inout] Open serialized model

void nx_file_flash_fail_after(nx_file_flash_t *flash, int64_t events)

Set an explicit model interruption boundary.

Note

Zero simulates power-off until explicitly cleared.

Parameters:
  • flash – [inout] Serialized open model

  • events – [in] Programmed/erased bytes and sync attempts permitted; negative disables

struct nx_file_flash_t
#include <file_flash.h>

Public Members

int fd
nx_storage_port_t port
int64_t fail_after
uint64_t mutation_events

flash_storage.h

Explicit physical Flash-region adapter without global registry.

Author

Nexus Team

Functions

nx_result_t nx_flash_storage_bind(nx_flash_storage_adapter_t *adapter, nx_flash_region_t region, nx_time_us_t deadline, nx_storage_port_t *port)

Bind an explicit writable uniform-erase physical region.

Note

Task-only, serialized caller. No region is reserved by the platform. Mixed sector geometries require another explicit storage adapter; this one rejects them. IO pulse settlement guarantees sync durability; no caller buffer survives a port call. Physical power-loss remains unqualified. The caller must honor geometry.program_flags when using this port directly: ECC units require actual erase provenance, not an all-0xff read. nx_storage_save erases its inactive bank and writes each distinct full program unit at most once before its next erase, including its separate final commit marker. This adapter does not track hidden program-pulse history.

Parameters:
  • adapter – [out] Unused caller storage kept through all store calls

  • region – [in] Externally selected writable physical region

  • deadline – [in] Absolute whole-transaction deadline for mutations

  • port – [out] Narrow synchronous persistent port, valid on SUCCESS

Returns:

SUCCESS or INVALID/PERMISSION/UNSUPPORTED geometry error

void nx_flash_storage_set_deadline(nx_flash_storage_adapter_t *adapter, nx_time_us_t deadline)

Set the next transaction’s one absolute mutation deadline.

Note

Caller serializes and sets this before open/save/recovery. Per-pulse timeouts cannot preempt hardware pulses; IO settles before return.

Parameters:
  • adapter – [inout] Bound adapter with no active store operation

  • deadline – [in] Absolute deadline in nx_time_now_us domain

struct nx_flash_storage_adapter_t
#include <flash_storage.h>

Caller-owned adapter, no dynamic binding or global token lookup.

Public Members

nx_flash_region_t region
nx_time_us_t deadline

log.h

Instance-local synchronous bounded log sink.

Author

Nexus Team

Enums

enum nx_log_level_t

Structured severity, with filtering before touching a sink.

Values:

enumerator NX_LOG_DEBUG
enumerator NX_LOG_INFO
enumerator NX_LOG_WARNING
enumerator NX_LOG_ERROR

Functions

nx_result_t nx_log_init(nx_log_t *logger, nx_log_sink_port_t sink, nx_log_level_t minimum)

Initialize an unused logger before exposing it to tasks.

Parameters:
  • logger – [out] Unused caller storage

  • sink – [in] Required bounded synchronous sink

  • minimum – [in] Minimum accepted severity

Returns:

SUCCESS or INVALID

nx_result_t nx_log_write(nx_log_t *logger, nx_log_level_t level, const void *bytes, size_t length, nx_time_us_t deadline)

Write caller bytes, with no implicit allocation/formatting.

Note

Task multi-producer entry with nonblocking serialization. M0/M0+ use CPU-local saved-PRIMASK metadata exclusion and require privileged callers on one CPU. Sink calls run after restoring the incoming mask. This does not make NMI/HardFault or cross-security-domain writers valid. IRQ use is prohibited. Drop/retry policy remains with the external caller.

Parameters:
  • logger – [inout] Live instance

  • level – [in] Message severity

  • bytes – [in] Message bytes, borrowed only during this call

  • length – [in] Byte count; zero permits NULL

  • deadline – [in] Absolute deadline understood by sink

Returns:

SUCCESS for filtered/sent bytes, BUSY for concurrent/recursive writes, STATE after stop, otherwise sink error

nx_result_t nx_log_flush(nx_log_t *logger, nx_time_us_t deadline)

Flush an explicit sink without creating a background worker.

Note

Same task/privilege/CPU domain as write.

Parameters:
  • logger – [inout] Live instance

  • deadline – [in] Absolute sink deadline

Returns:

SUCCESS, BUSY, STATE, UNSUPPORTED or sink error

nx_result_t nx_log_stop(nx_log_t *logger)

Reject new writes and test whether the sink has exited.

Note

Task context. A stop caller may retry; no active sink call is forcibly cancelled. Join publishers before reclaiming logger/sink storage.

Parameters:
  • logger – [inout] Live instance; external users must eventually join

Returns:

SUCCESS when no sink call is active, BUSY while draining

struct nx_log_sink_port_t
#include <log.h>

Synchronous caller-injected sink.

Note

write/flush release every byte buffer before returning even on timeout/error; asynchronous/DMA sinks require their own settled adapter. Calls are bounded by absolute monotonic deadlines, in task context. No sink discovery, allocation, formatting, worker or global error handler exists.

Public Members

void *context
nx_result_t (*write)(void*, nx_log_level_t, const void*, size_t, nx_time_us_t deadline)
nx_result_t (*flush)(void*, nx_time_us_t deadline)
struct nx_log_t
#include <log.h>

Logger storage belongs to its caller; shared immutable port is copied.

Public Members

nx_log_sink_port_t sink
nx_log_level_t minimum
uint32_t busy
uint32_t stopped

modbus_rtu.h

Bounded Modbus RTU core and explicit RS485 ports.

Author

Nexus Team

Defines

NX_MODBUS_ADU_MAX
NX_MODBUS_REGISTER_MAX

Enums

enum nx_modbus_register_result_t

Values:

enumerator NX_MODBUS_OK
enumerator NX_MODBUS_ILLEGAL_ADDRESS
enumerator NX_MODBUS_ILLEGAL_VALUE
enumerator NX_MODBUS_DEVICE_FAILURE
enumerator NX_MODBUS_DEVICE_BUSY

Values:

Functions

uint16_t nx_modbus_crc16(const uint8_t *bytes, size_t length)

Compute standard Modbus CRC16 over caller bytes.

Parameters:
  • bytes – [in] Input, NULL only when length is zero

  • length – [in] Byte count

Returns:

CRC16; zero for invalid NULL input with nonzero length

bool nx_modbus_rtu_init(nx_modbus_rtu_t *server, const nx_modbus_config_t *config)

Initialize an unused or fully quiesced protocol instance.

Note

Task-only; configuration is copied, contexts stay live. First direction(false) failure is reported; no worker or UART is created. Reinitializing a faulted TX borrow is prohibited; stop/recover it first.

Parameters:
  • server – [out] Caller-owned storage, no existing transport borrow

  • config – [in] Explicit register/RS485 ports and finite budgets

Returns:

True when initialized into RX silence acquisition

bool nx_modbus_rtu_feed(nx_modbus_rtu_t *server, uint8_t byte, uint64_t arrival_us)

Feed an externally timestamped UART byte.

Note

Task-only. IRQ queues are external, bounded and explicit; queue overflow must call rx_error. No live UART discovery or ISR callback.

Parameters:
  • server – [inout] Initialized instance, serialized by caller

  • byte – [in] Wire byte

  • arrival_us – [in] Capture timestamp in port monotonic domain

Returns:

True if byte joined the frame, false for discard/error

bool nx_modbus_rtu_poll(nx_modbus_rtu_t *server, uint64_t now_us)

Service RTU silence and bounded synchronous RS485 response.

Note

Task-only, explicit external scheduling. RS485 drain must observe the final stop bit. Failed abort retains TX bytes and asserted DE in LINK_FAULTED; keep instance/port alive until successful recover or stop.

Parameters:
  • server – [inout] Initialized instance, single execution owner

  • now_us – [in] Snapshot in the same monotonic domain

Returns:

True for successful progress, false for clock/transport error

void nx_modbus_rtu_rx_error(nx_modbus_rtu_t *server, uint64_t now_us)

Discard an errored or overrun receive frame.

Note

Task-only. Does not discard a retained faulted TX borrow.

Parameters:
  • server – [inout] Initialized serialized instance

  • now_us – [in] Error timestamp in port’s monotonic domain

bool nx_modbus_rtu_recover(nx_modbus_rtu_t *server)

Settle retained TX then restore receive silence acquisition.

Note

Explicit task maintenance action, no fabricated recovery.

Parameters:
  • server – [inout] Initialized serialized instance with live ports

Returns:

True only after actual port abort/drain and receive direction

bool nx_modbus_rtu_stop(nx_modbus_rtu_t *server)

Settle the port before reclaiming protocol storage.

Note

Stop future feed/poll users first. No future use except explicit initialization is allowed after successful stop.

Parameters:
  • server – [inout] Initialized, exclusively owned instance

Returns:

True when no transport borrow remains and instance is stopped; false preserves fault state, TX bytes and all port lifetime obligations

struct nx_modbus_registers_t
#include <modbus_rtu.h>

Public Members

void *context
nx_modbus_register_result_t (*read)(void*, uint16_t, uint16_t, uint16_t*)
nx_modbus_register_result_t (*authorize_write)(void*, uint16_t, uint16_t, const uint16_t*)
nx_modbus_register_result_t (*write_atomic)(void*, uint16_t, uint16_t, const uint16_t*)
struct nx_modbus_rs485_port_t
#include <modbus_rtu.h>

Public Members

void *context
uint64_t (*now_us)(void*)
bool (*direction)(void*, bool transmit)
bool (*write)(void*, const uint8_t*, size_t, uint64_t deadline_us)
bool (*drain)(void*, uint64_t deadline_us)
bool (*abort_and_settle)(void*, uint64_t deadline_us)
struct nx_modbus_counters_t
#include <modbus_rtu.h>

Public Members

uint64_t frames
uint64_t accepted
uint64_t crc_errors
uint64_t timing_errors
uint64_t overflows
uint64_t exceptions
uint64_t broadcasts
uint64_t tx_errors
uint64_t clock_errors
struct nx_modbus_config_t
#include <modbus_rtu.h>

Public Members

uint8_t address
uint32_t baudrate
uint8_t bits_per_character
uint32_t tx_timeout_us
uint32_t abort_timeout_us
nx_modbus_registers_t registers
nx_modbus_rs485_port_t port
struct nx_modbus_rtu_t
#include <modbus_rtu.h>

Public Members

nx_modbus_config_t config
nx_modbus_counters_t counters
nx_modbus_link_state_t state
uint32_t t1_5_us
uint32_t t3_5_us
uint64_t last_byte_us
uint64_t last_event_us
uint16_t rx_length
uint16_t tx_length
uint8_t rx[NX_MODBUS_ADU_MAX]
uint8_t tx[NX_MODBUS_ADU_MAX]
uint16_t values[NX_MODBUS_REGISTER_MAX]
bool initialized
bool clock_started

owner_observer.h

Explicit owner progress diagnostics without default state.

Author

Nexus Team

Functions

nx_result_t nx_owner_observer_bind(nx_owner_observer_t *observer, nx_bus_owner_t *owner)

Bind an initialized exact owner without creating work.

Parameters:
  • observer – [inout] Fresh zero/detached sidecar, distinct from owner.

  • owner – [inout] Initialized stable owner, no concurrent lifecycle.

Returns:

SUCCESS or INVALID/STATE, no service or borrow on rejection.

nx_result_t nx_owner_observer_service(nx_owner_observer_t *observer, nx_time_us_t now, nx_owner_observation_t *out)

Execute exactly one real service step and copy diagnostics.

Note

Clock reversal never blocks drain or rewrites its result. Snapshot uses the existing guard outside hardware service. No callback, slot scan or worker occurs under that guard. Quarantine and elapsed deadlines never release a loan. Output also excludes accepted descriptors and payloads. Only the owner/slot control spans are checked here.

Parameters:
  • observer – [inout] Bound sidecar on the unique executor.

  • now – [in] Monotonic timestamp, independent of service result.

  • out – [out] Distinct stable output, no retained references.

Returns:

Actual service result; invalid bindings reject beforehand.

void nx_owner_observer_detach(nx_owner_observer_t *observer)

Drop only the observation binding, no owner/loan teardown.

Parameters:
  • observer – [inout] Caller-serialized sidecar, no remaining readers.

struct nx_owner_observation_t
#include <owner_observer.h>

Copied service facts without request, payload or slot references.

Public Members

nx_result_t service_result
nx_result_t diagnostic_result
nx_time_us_t observed_at
nx_time_us_t max_gap
uint32_t calls
uint32_t busy
uint32_t errors
uint32_t quarantines
uint32_t clock_errors
nx_owner_ticket_t active
nx_request_state_t active_state
bool has_active
bool idle
bool accepting
bool queued
bool slot_available
struct nx_owner_observer_t
#include <owner_observer.h>

Opt-in caller sidecar; no pointer added to default owner.

Note

Exact owner, slots and guard remain live until detach and all observer calls exit. The same unique owner executor calls this wrapper; producer calls retain the owner guard. Never reinitialize/replace the bound owner underneath it.

Public Members

nx_bus_owner_t *owner
nx_time_us_t last_observed
nx_owner_observation_t observation
bool observed

settings.h

Bounded key/value staging over durable whole-blob storage.

Author

Nexus Team

Defines

NX_SETTINGS_HEADER_SIZE

Functions

nx_storage_status_t nx_settings_open(nx_settings_t *settings, nx_storage_t *storage, uint32_t schema, void *image, size_t image_bytes, uint32_t max_entries)

Load one exact schema or stage an empty, uncommitted image.

Note

Synchronous task-only scan. Missing blob stages an empty image, without reading defaults or writing Flash. Different schema/format is UNSUPPORTED and never rewritten. Truncated, duplicate or unordered keys are CORRUPT. A failed load never becomes an empty writable store; the instance stays closed.

Parameters:
  • settings – [out] Unused or closed instance, exclusively owned

  • storage – [inout] Open durable store; no other mutating client while this settings instance is open

  • schema – [in] Product-defined schema identity, including zero

  • image – [inout] Caller buffer, disjoint from both instances and the storage workspace; borrowed until close or a failed commit

  • image_bytes – [in] At least HEADER_SIZE and at most UINT32_MAX

  • max_entries – [in] Nonzero upper bound on staged entries

Returns:

OK, INVALID, NO_SPACE, CORRUPT, UNSUPPORTED or port error

nx_storage_status_t nx_settings_get(const nx_settings_t *settings, uint32_t key, void *output, size_t *size)

Copy a staged value without exposing internal storage.

Note

Task-only synchronous copy; no pointer is retained. Missing key reports size zero. NO_SPACE leaves output untouched and reports required bytes. No underlying Flash operation occurs.

Parameters:
  • settings – [in] Open instance, serialized with all mutation

  • key – [in] Exact product-assigned identifier

  • output – [out] Disjoint destination, or NULL to query size only

  • size – [inout] Capacity on input, required/value bytes on output; disjoint from metadata, staging image and output

Returns:

OK, NOT_FOUND, NO_SPACE or INVALID

nx_storage_status_t nx_settings_set(nx_settings_t *settings, uint32_t key, const void *value, size_t size)

Insert or replace one copied value in bounded RAM staging.

Note

Task-only, bounded by image capacity and entry limit. Failed admission changes neither entries nor dirty state. A changed value marks staging dirty without touching Flash; an identical value preserves both image and the previous dirty state.

Parameters:
  • settings – [inout] Open exclusively owned instance

  • key – [in] Exact product-assigned identifier

  • value – [in] Input disjoint from instance and staging image; NULL only for an empty value, borrowed during this call

  • size – [in] Value byte count, at most UINT32_MAX

Returns:

OK, NO_SPACE or INVALID

nx_storage_status_t nx_settings_remove(nx_settings_t *settings, uint32_t key)

Remove a staged key without writing Flash.

Note

Task-only synchronous operation. Missing keys have no effects. Success compacts staging and marks it dirty.

Parameters:
  • settings – [inout] Open exclusively owned instance

  • key – [in] Exact product-assigned identifier

Returns:

OK, NOT_FOUND or INVALID

nx_storage_status_t nx_settings_commit(nx_settings_t *settings)

Commit the complete staged snapshot through durable Storage.

Note

Task-only settled call; underlying Flash may stall execution. Clean staging does not write. Successful save clears dirty. A mutating I/O failure closes the instance and preserves the dirty flag for diagnosis, but retains no staging borrow. Reopen Storage, then Settings to determine the surviving commit; failure may occur after a new marker became durable. Retrying a failed commit without recovery is rejected.

Parameters:
  • settings – [inout] Open exclusively owned instance

Returns:

OK or underlying storage error

void nx_settings_close(nx_settings_t *settings)

Release settings metadata without committing staged values.

Note

Task-only, serialized after all calls. No I/O or retained references remain. Underlying Storage stays open; its scratch lifetime remains governed by the Storage contract.

Parameters:
  • settings – [inout] Quiesced instance, or NULL

struct nx_settings_t
#include <settings.h>

Caller-owned settings metadata and bounded staging image.

Note

Task-only; serialize all operations and the underlying storage. No heap, workers or global key registry. Keys are product-assigned uint32 identifiers; values are byte strings, including empty strings. The format is little-endian, not authenticated. Products own defaults, schema migration, authorization, durability frequency and Flash reservations. Only commit writes storage; close discards staged changes.

Public Members

nx_storage_t *storage
uint8_t *image
size_t capacity
size_t size
uint32_t schema
uint32_t count
uint32_t max_entries
bool opened
bool dirty

spi_async_owner.h

Optional finite async SPI executor for one explicit bus.

Author

Nexus Team

Functions

nx_owner_executor_port_t nx_spi_async_owner_executor_port(nx_spi_async_owner_executor_t *executor, const nx_spi_port_t *port)

Bind one async-capable bus to an explicit owner executor.

Note

Startup/task context. Operations use nx_spi_owner_operation_t endpoints on this bus only; membership is checked before admission. No polling fallback is selected. Controller and executor remain live through drain, control acknowledgement and observer exit. QUARANTINED retains both buffer loans. Hardware stop and IRQ/notification destruction are explicit external steps after owner shutdown, not part of this bind.

Parameters:
  • executor – [out] Fresh storage with no previous outstanding loans.

  • port – [in] Initialized controller exclusively owned by this executor; direct clients and other owners must quiesce.

Returns:

Valid executor port, or a zero port for incomplete methods.

struct nx_spi_async_owner_executor_t
#include <spi_async_owner.h>

Exact async storage independent of the polling adapter.

Note

inner is a private publication object. Its borrow must end before the outer owner publishes SETTLED. No queue, payload copy, allocation or hidden worker is created.

Public Members

const nx_spi_port_t *port
nx_spi_request_t inner
bool pending

spi_owner.h

Explicit polling SPI executor for the bounded owner adapter.

Author

Nexus Team

Functions

nx_owner_executor_port_t nx_spi_owner_executor_port(nx_spi_owner_executor_t *executor, const nx_spi_port_t *port)

Bind an explicit synchronous SPI execution adapter.

Note

start executes a real CPU-active polling transaction and releases all IO buffers before returning. Owner service later publishes its caller-owned request. Polling cannot be preempted by another task’s cancel; once the polling call returns, its result is final despite later cancellation or publication delay. Do not claim IRQ/DMA mode or low-CPU asynchronous hardware execution. Endpoints must prove their controller identity before any wire effect; distinct chip selects on this controller remain valid. The controller and executor outlive owner shutdown and all observers.

Parameters:
  • executor – [out] Fresh storage with no outstanding operation

  • port – [in] Controller exclusively serviced by this owner

Returns:

Port for nx_bus_owner_init, or a zero port for invalid input

struct nx_spi_owner_operation_t
#include <spi_owner.h>

Caller-owned SPI transaction descriptor, borrowed until SETTLED.

Public Members

const nx_spi_endpoint_t *endpoint
const uint8_t *tx
uint8_t *rx
size_t length
struct nx_spi_owner_executor_t
#include <spi_owner.h>

Exact polling executor storage; no payload copy or queue.

Public Members

const nx_spi_port_t *port
nx_result_t result
size_t transferred
bool pending

storage.h

Two-bank durable blob storage over an explicit narrow port.

Author

Nexus Team

Defines

NX_STORAGE_HEADER_SIZE

Enums

enum nx_storage_status_t

Storage errors expose retry/reopen/recovery decisions.

Values:

enumerator NX_STORAGE_OK
enumerator NX_STORAGE_INVALID
enumerator NX_STORAGE_IO
enumerator NX_STORAGE_CORRUPT
enumerator NX_STORAGE_NO_SPACE
enumerator NX_STORAGE_NOT_FOUND
enumerator NX_STORAGE_UNSUPPORTED

Functions

nx_storage_status_t nx_storage_open(nx_storage_t *storage, const nx_storage_port_t *port, size_t offset, size_t bank_size, void *workspace, size_t workspace_bytes)

Open/recover two externally supplied uniform erase banks.

Note

Task-only bounded scan over both bank payloads. Workspace remains borrowed by the instance through every subsequent load/save call.

Parameters:
  • storage – [out] Unused or quiesced instance, no concurrent calls

  • port – [in] Persistent settled port, may be storage’s existing port

  • offset – [in] Erase-aligned start within port region

  • bank_size – [in] Each bank’s erase-aligned byte size

  • workspace – [in] Caller buffer, disjoint from instance/payload

  • workspace_bytes – [in] At least max(32, port.program_size)

Returns:

OK for recovered/empty store, CORRUPT for ambiguous or only invalid committed generations, IO/INVALID for port/geometry failures

nx_storage_status_t nx_storage_load(nx_storage_t *storage, void *output, size_t *size)

Load and validate the latest committed whole blob.

Note

Output bytes valid only on OK; failure may partially write output. No destination pointer is retained after returning.

Parameters:
  • storage – [inout] Open instance, exclusively owned for this call

  • output – [out] Destination; NULL requests only required size

  • size – [inout] Input capacity, output payload/required bytes

Returns:

OK, NOT_FOUND, NO_SPACE, CORRUPT or IO/INVALID

nx_storage_status_t nx_storage_save(nx_storage_t *storage, const void *data, size_t size)

Commit a complete blob to the inactive bank.

Note

Marker is programmed last after sync. Failed mutation keeps the previous bank and requires reopen; ambiguous marker failure can mean the new blob committed. Product owns migration/authentication/recovery policy.

Parameters:
  • storage – [inout] Open exclusively owned instance

  • data – [in] Payload disjoint from workspace, borrowed during call

  • size – [in] Payload bytes; zero permits NULL

Returns:

OK, NO_SPACE, INVALID or underlying port error

size_t nx_storage_capacity(const nx_storage_t *storage)

Query usable blob capacity without touching hardware.

Parameters:
  • storage – [in] Geometry-established instance, or NULL

Returns:

Payload bytes per bank, or zero for invalid geometry

struct nx_storage_port_t
#include <storage.h>

Synchronous settled persistent Flash port.

Note

Task-only; caller serializes every operation. Offsets are byte-relative to the supplied region. program changes only 1 to 0 in complete aligned program units; erase uses complete uniform erase units. sync makes earlier successful writes durable. Errors can change a subset of addressed units, but never retain caller buffers after returning. RAM is a model, not a persistent implementation. Product owns the region/layout and power policy.

Public Members

void *ctx
size_t size
size_t erase_size
size_t program_size
nx_storage_status_t (*read)(void*, size_t, void*, size_t)
nx_storage_status_t (*program)(void*, size_t, const void*, size_t)
nx_storage_status_t (*erase)(void*, size_t, size_t)
nx_storage_status_t (*sync)(void*)
struct nx_storage_t
#include <storage.h>

Instance metadata with caller-sized workspace.

Note

Two independently erasable banks commit whole blobs. No heap, global registry, maximum pool or default product reservation. Wire format v1 is explicit little-endian and CRC-protected, not authenticated. Keep instance, port context and workspace alive through close/quiescence. A mutating I/O error invalidates opened; reopen to establish which commit actually survived.

Public Members

nx_storage_port_t flash
size_t offset
size_t bank_size
size_t payload_offset
uint64_t generation
size_t payload_size
int active_bank
bool opened
uint8_t *workspace
size_t workspace_bytes

uart_owner.h

Explicit IRQ UART executor with private provider settlement.

Author

Nexus Team

Functions

nx_owner_executor_port_t nx_uart_owner_executor_port(nx_uart_owner_executor_t *executor, const nx_uart_port_t *uart)

Bind a UART controller to one explicit service executor.

Note

Startup/task context. Controller and executor remain alive through owner stop/drain and external observer quiescence. Direct UART users must not share this controller. Queued time belongs to the bus owner; after start the UART’s first terminal TC/error/cancel/deadline fact is authoritative. cancel observes provider completion/deadline before asking it to abort. Failed drain keeps both requests QUARANTINED; service must continue during recovery. Outer SETTLED never precedes inner acquire-observed SETTLED and pointer detach. The application separately stops hardware and RX consumers only after all owner operations and controls quiesce.

Parameters:
  • executor – [inout] Unused caller-owned storage, no concurrent calls

  • uart – [inout] Initialized UART exclusively owned by this executor

Returns:

Port for nx_bus_owner_init, or an invalid zero port for NULL

struct nx_uart_owner_operation_t
#include <uart_owner.h>

Caller-owned TX payload descriptor borrowed until outer SETTLED.

Public Members

const uint8_t *data
size_t length
struct nx_uart_owner_executor_t
#include <uart_owner.h>

One executor’s exact private provider request.

Note

inner is a separate publication object, not another outer queue or caller admission. Only this executor accesses it; producers retain their outer request and payload until the bus owner publishes outer SETTLED. No buffer copy, heap, worker or pool. Never pass inner to application observers.

Public Members

const nx_uart_port_t *port
nx_uart_tx_request_t inner
bool pending

usb_acm.h

Optional caller-owned CDC ACM control subset.

Author

Nexus Team

Enums

enum nx_usb_acm_change_t

Values:

enumerator NX_USB_ACM_GET_LINE_CODING
enumerator NX_USB_ACM_SET_LINE_CODING
enumerator NX_USB_ACM_SET_CONTROL_LINE_STATE
enumerator NX_USB_ACM_SEND_BREAK

Functions

nx_result_t nx_usb_acm_initialize(nx_usb_acm_t *acm, const nx_usb_device_profile_t *profile, uint8_t interface_number, const nx_usb_acm_state_t *initial)

Bind one explicit communication interface and initial state.

Note

Same privileged unmasked serialized task as USBControl; no ISR, callback or second-task reentry. The external dispatcher gives this adapter exclusive EP0 use while active. Interface descriptors, class capabilities and configuration readiness are external; initialization does not validate class bytes.

Parameters:
  • acm – [inout] Naturally aligned zero-initialized caller storage.

  • profile – [in] Immutable selected USB profile with a guarded SETUP rejection port, disjoint from acm.

  • interface_number – [in] Exact externally described ACM interface.

  • initial – [in] Disjoint naturally aligned initial software intent.

Returns:

SUCCESS, INVALID, STATE or CONTEXT; no hardware is started.

nx_result_t nx_usb_acm_begin(nx_usb_acm_t *acm, uint64_t epoch, nx_time_us_t deadline)

Dispatch the current software-published SETUP to the subset.

Note

Exact class/interface direction, wIndex, wValue and wLength are checked. GET_LINE_CODING returns seven committed bytes. SET_LINE_CODING receives exactly seven bytes but waits for explicit approval. Control-line/break requests wait before starting STATUS. Invalid/unknown dispatch deliberately has the documented STALL effect, but retains no new loan. Route standard/other-class requests externally before calling.

Parameters:
  • acm – [inout] Bound inactive adapter; no other EP0 packet user.

  • epoch – [in] Exact nonzero published SETUP identity.

  • deadline – [in] One independent absolute deadline for all stages and external approval; NEVER permits an indefinite wait.

Returns:

SUCCESS accepts the operation; BUSY/STATE/TIMEOUT reject without a new loan. Unknown requests return UNSUPPORTED and malformed fields INVALID after guarded STALL succeeds; otherwise the guarded rejection error is returned.

nx_result_t nx_usb_acm_step(nx_usb_acm_t *acm)

Advance USBControl once and fold only acquired completion.

Note

At most one underlying USBControl step, with its one service, one state read and one packet action bounds. No loop drains a transaction. Continue after cancel/supersession/timeouts. OUT0 quarantine still needs explicit external device-owner stop, then further steps. Never auto-stop the controller. Only approved outer acquire SUCCESS commits intent: it proves the matching STATUS packet’s real ACK. A later SETUP/reset, closing or failed state read cannot revoke an ACK already acquired by the packetizer. Supersession before ACK aborts and drains without commit. Resetting class state after a completed command is separate external owner policy. Software epoch checks do not promise atomicity with uncollected physical SETUP packets.

Parameters:
  • acm – [inout] Same executor; keep all storage while active.

Returns:

Progress/provider result; an error never revokes a loan.

nx_result_t nx_usb_acm_pending(const nx_usb_acm_t *acm, nx_usb_acm_pending_t *pending)

Copy staged intent for external validation/authorization.

Note

Wire format allows nonzero rate, stop bits 0..2, parity 0..4 and data bits 5/6/7/8/16. External hardware/policy may support fewer values. This value may become stale; approve rechecks the software epoch. Inspecting is not approval.

Parameters:
  • acm – [in] Same task; SET_LINE_CODING must be DATA_READY.

  • pending – [out] Disjoint naturally aligned value output; unchanged on rejection. No pointer into the borrowed payload escapes.

Returns:

SUCCESS, STATE, INVALID or CONTEXT. INVALID on a malformed or short line-coding DATA stage; owner can reject explicitly.

nx_result_t nx_usb_acm_approve(nx_usb_acm_t *acm, uint64_t epoch, bool accepted)

Authorize staged intent before STATUS, or reject this epoch.

Note

Approval must not apply UART/physical lines. After a newer committed_epoch appears, the external owner applies the copied intent and owns application failures/recovery. No callback runs here. SEND_BREAK records 0 (stop), 0xffff (indefinite), or a finite millisecond intent, without timer, automatic expiry or assertion that physical break occurred.

Parameters:
  • acm – [inout] Same active adapter and serialized task executor.

  • epoch – [in] Exact operation identity.

  • accepted – [in] True authorizes only; false requests guarded STALL.

Returns:

SUCCESS changes authorization; other results retain live loans and do not authorize a change. Malformed line coding cannot be approved; false is still allowed at DATA_READY.

nx_result_t nx_usb_acm_cancel(nx_usb_acm_t *acm, uint64_t epoch)

Cancel one active identity, preserving all admitted storage.

Parameters:
  • acm – [inout] Same executor, retained through actual drain.

  • epoch – [in] Exact active identity.

Returns:

SUCCESS requests drain or discards unadmitted zero-data intent; STATE for stale identity. Cancellation only requests drain. A matching STATUS ACK acquired before or during cancellation still wins at the packetizer; step commits the approved original epoch on acquire outer SUCCESS without later epoch revocation.

nx_result_t nx_usb_acm_snapshot(const nx_usb_acm_t *acm, nx_usb_acm_snapshot_t *snapshot)

Copy current software intent and the last observed outcome.

Note

A committed_epoch update is a software notification, not an event queue or physical apply acknowledgement. Poll after each step before dispatching the next operation if every committed change must be consumed. GET never changes it.

Parameters:
  • acm – [in] Same executor; this does not refresh device state.

  • snapshot – [out] Disjoint naturally aligned value output, unchanged on error. result is the adapter outcome, wire_result the outer transport outcome (STATE if no outer was admitted).

Returns:

SUCCESS, INVALID or CONTEXT; no loan is released.

struct nx_usb_acm_line_coding_t
#include <usb_acm.h>

CDC wire values, not a claim that a UART supports every value.

Public Members

uint32_t rate
uint8_t stop_bits
uint8_t parity
uint8_t data_bits
struct nx_usb_acm_state_t
#include <usb_acm.h>

Last acknowledged software intent; physical application is external.

Public Members

nx_usb_acm_line_coding_t line_coding
uint16_t control_lines
uint16_t break_duration
struct nx_usb_acm_pending_t
#include <usb_acm.h>

Value copy for external authorization, never a mutable DATA view.

Public Members

nx_usb_acm_state_t proposed
uint64_t epoch
nx_usb_acm_change_t change
struct nx_usb_acm_snapshot_t
#include <usb_acm.h>

Public Members

nx_usb_acm_state_t committed
uint64_t committed_epoch
uint64_t completed_epoch
nx_result_t result
nx_result_t wire_result
nx_usb_control_phase_t phase
bool active
struct nx_usb_acm_t
#include <usb_acm.h>

Fixed caller storage; fields are private while bound.

Note

Metadata require natural C alignment and nonwrapping extents; wire bytes require only byte alignment. Bind once from zero initialization. Never zero/rebind to revoke a loan. The profile, faces and this complete context outlive every packet/outer loan and separate observer. No dynamic allocation, per-instance operation table, worker or default instance exists. Provider faces retain shared readonly ops.

Public Members

nx_usb_control_t control
nx_usb_control_request_t reply
nx_usb_acm_state_t committed
nx_usb_acm_pending_t pending
nx_time_us_t deadline
uint64_t last_epoch
uint64_t committed_epoch
uint64_t completed_epoch
nx_result_t result
nx_result_t wire_result
uint8_t wire[7]
uint8_t interface_number
bool active
bool outer_started
bool approved

usb_control.h

Caller-owned single-executor EP0 packetizer.

Author

Nexus Team

Enums

enum nx_usb_control_reply_kind_t

Values:

enumerator NX_USB_CONTROL_IN_REPLY
enumerator NX_USB_CONTROL_OUT_REPLY
enumerator NX_USB_CONTROL_STATUS_REPLY
enum nx_usb_control_phase_t

Values:

enumerator NX_USB_CONTROL_IDLE
enumerator NX_USB_CONTROL_WAIT_REPLY
enumerator NX_USB_CONTROL_DATA_IN
enumerator NX_USB_CONTROL_DATA_IN_ZLP
enumerator NX_USB_CONTROL_DATA_OUT
enumerator NX_USB_CONTROL_DATA_READY
enumerator NX_USB_CONTROL_STATUS_IN
enumerator NX_USB_CONTROL_STATUS_OUT
enumerator NX_USB_CONTROL_DRAINING
enumerator NX_USB_CONTROL_NEEDS_DEVICE_STOP
enumerator NX_USB_CONTROL_STALLED
enumerator NX_USB_CONTROL_CLOSED

Functions

nx_result_t nx_usb_control_initialize(nx_usb_control_t *control, const nx_usb_device_profile_t *profile)

Bind zero-initialized caller storage to a stable validated ROM profile.

Note

Every function except preparation uses one serialized privileged task executor with IRQ masks clear. No callback, second task or ISR may reenter. The owner gives this adapter exclusive EP0 packet use; it retains external event-ring and explicit device recovery policy. No controller/endpoint reset invalidates a loan. A successful bind owns no provider references until begin.

Parameters:
  • control – [inout] Zero-initialized storage, disjoint from the profile.

  • profile – [in] Immutable facts and faces outliving every adapter loan.

Returns:

Success or rejection; no hardware, task or allocation is created.

nx_result_t nx_usb_control_in_prepare(nx_usb_control_request_t *request, const uint8_t *bytes, size_t length, uint64_t epoch, nx_time_us_t deadline)

Prepare a reply without borrowing or reading immutable IN bytes.

Note

Task-only preparation; bytes stay alive until the admitted outer acquire SETTLED. A short full-MPS reply emits an acknowledged DATA ZLP.

Parameters:
  • request – [inout] Initialized READY or consumed SETTLED storage.

  • bytes – [in] Immutable external descriptor/reply; NULL only if empty.

  • length – [in] Available bytes; reply is clipped to SETUP wLength.

  • epoch – [in] Nonzero SETUP identity.

  • deadline – [in] Absolute independent monotonic deadline for all stages.

Returns:

Success, INVALID or STATE; rejection retains no references.

nx_result_t nx_usb_control_out_prepare(nx_usb_control_request_t *request, uint8_t *bytes, size_t capacity, uint64_t epoch, nx_time_us_t deadline)

Prepare caller storage for OUT DATA requiring explicit approval.

Note

Task-only. Accepted bytes remain borrowed through STATUS or actual drain. DATA_READY grants only the documented const inspection view.

Parameters:
  • request – [inout] Initialized unborrowed request.

  • bytes – [out] Stable writable payload, no early writes at preparation.

  • capacity – [in] Must cover matching SETUP wLength at admission.

  • epoch – [in] Nonzero SETUP identity.

  • deadline – [in] Absolute independent deadline, including policy delay.

Returns:

Success, INVALID or STATE; no loan before successful begin.

nx_result_t nx_usb_control_status_prepare(nx_usb_control_request_t *request, uint64_t epoch, nx_time_us_t deadline)

Prepare only the zero-data request’s status-IN reply.

Note

Task-only. External standard-request policy must stage SET_ADDRESS itself and inspect authoritative address/closing state after wire ACK.

Parameters:
  • request – [inout] Initialized unborrowed request.

  • epoch – [in] Nonzero matching SETUP identity.

  • deadline – [in] Absolute independent deadline.

Returns:

Success, INVALID or STATE; no transfer is started.

nx_result_t nx_usb_control_begin(nx_usb_control_t *control, nx_usb_control_request_t *request)

Admit one explicit reply to the current authoritative SETUP epoch.

Note

No packet is submitted by admission. Payload, request, profile and adapter remain alive until acquire-observed outer SETTLED. Never call prepare/reinitialize to revoke a loan. Epochs do not repeat. Products stage SET_ADDRESS explicitly; transport success means wire ACK only.

Parameters:
  • control – [inout] Bound single-executor adapter; no other live reply.

  • request – [inout] READY metadata and disjoint payload. OUT capacity must cover wLength; IN sends min(length,wLength), including required ZLP.

Returns:

Success means ACCEPTED; every failure retains no request or payload.

nx_result_t nx_usb_control_step(nx_usb_control_t *control)

Make one bounded progress step, at most one poll and one packet action.

Note

No queue or worker. All packet deadlines use the outer independent absolute monotonic deadline. Poll while borrowed, even after cancel, reset, SETUP supersession or device stop. Cancel/drain/quarantine retain descriptor bytes and outer context. OUT0 quarantine exposes NEEDS_DEVICE_STOP; only the external controller owner may authorize stop. This adapter never stops the shared controller automatically. One SETTLED packet is folded before observing newer controller epochs.

Parameters:
  • control – [inout] Same serialized executor and lifetime as begin.

Returns:

Success or provider error; an error never revokes accepted storage.

nx_result_t nx_usb_control_cancel(nx_usb_control_t *control, nx_usb_control_request_t *request, uint64_t epoch)

Request cancellation without revoking the old packet or outer loan.

Note

An already acquired STATUS ACK wins. The next step issues at most one packet cancel; continue polling and retain quarantine until actual source withdrawal. OUT0 recovery may need explicit device-owner stop.

Parameters:
  • control – [inout] Same serialized privileged task executor.

  • request – [inout] Exact active outer request, kept alive until SETTLED.

  • epoch – [in] Exact active SETUP identity; no cross-task raw pointer use.

Returns:

Success requests drain; STATE rejects stale identity without effects.

nx_result_t nx_usb_control_out_view(const nx_usb_control_t *control, nx_usb_control_out_view_t *view)

Inspect completed OUT DATA before the external policy approves STATUS.

Note

The view expires at the next same-owner adapter call. No mutation, free, cross-task access or implicit status acknowledgement is allowed.

Parameters:
  • control – [in] DATA_READY with no provider packet references.

  • view – [out] Disjoint value output, unchanged on rejection.

Returns:

Success grants a const inspection view only; outer borrow continues.

nx_result_t nx_usb_control_approve(nx_usb_control_t *control, uint64_t epoch, bool accepted)

Approve OUT policy before STATUS IN, or reject with a bounded STALL.

Note

Bytes, class dispatch, configuration readiness and recovery policy are external. No CDC/HID stack is supplied. A guarded decision excludes an already software-published replacement SETUP. Physical bus packets not yet collected by IRQ are outside that software epoch boundary. Cancellation drains before the outer loan ends.

Parameters:
  • control – [inout] DATA_READY same-owner adapter.

  • epoch – [in] Exact active SETUP epoch, checked against fresh state.

  • accepted – [in] True permits status; false stalls the old transaction.

Returns:

Success changes policy only; the next step performs packet/STALL.

nx_result_t nx_usb_control_snapshot(const nx_usb_control_t *control, nx_usb_control_snapshot_t *snapshot)

Copy the last acquired authoritative state and adapter phase.

Note

Call step to refresh controller state. Wire success does not imply address/configuration readiness. Snapshots never release a loan.

Parameters:
  • control – [in] Same single task executor; no provider operation occurs.

  • snapshot – [out] Disjoint value output, unchanged on rejection.

Returns:

Success, INVALID or CONTEXT.

struct nx_usb_control_request_t
#include <usb_control.h>

Public Members

nx_request_t base
const uint8_t *in
uint8_t *out
size_t length
uint64_t setup_epoch
nx_usb_control_reply_kind_t kind
struct nx_usb_control_out_view_t
#include <usb_control.h>

Public Members

const uint8_t *bytes
size_t length
uint64_t setup_epoch
struct nx_usb_control_snapshot_t
#include <usb_control.h>

Public Members

nx_usb_device_state_t device
size_t confirmed_bytes
nx_usb_control_phase_t phase
bool outer_active
struct nx_usb_control_t
#include <usb_control.h>

Adapter-private fields, caller-owned and fixed capacity.

Note

Public context/request/output metadata require natural C alignment and nonwrapping extents. Misalignment is INVALID before typed access. Pointers still require documented readable/writable storage: numeric checks cannot validate arbitrary address maps or opaque private provider contexts.

Public Members

const nx_usb_device_profile_t *profile
nx_usb_request_t packets[2]
nx_usb_control_request_t *active
nx_usb_device_state_t latest
nx_usb_setup_t setup
uint64_t completed_epoch
size_t goal
size_t confirmed_bytes
nx_result_t terminal
nx_usb_control_phase_t phase
bool borrowed[2]
bool cancel_sent[2]
bool cancel_pending
bool stall_pending

usb_descriptors.h

Bounded descriptor views; product bytes stay external.

Author

Nexus Team

Functions

nx_result_t nx_usb_descriptor_validate(const nx_usb_device_profile_t *profile, const nx_usb_descriptor_view_t *descriptor)

Validate complete device, configuration or string descriptor bytes.

Note

Configuration views require alternate zero, endpoint plans matching selected bulk or interrupt IN ports, consistent totals and unique interface numbers. Interrupt bInterval is a nonzero linear count of full-speed 1 ms frames in external descriptor bytes. Bulk bInterval is not interpreted; no polling is scheduled. Class-specific subordinate bytes are bounds-checked but not decoded. Class dispatch, VID/PID, strings, policy, CDC/HID and descriptor lookup remain external. Success is structural validation, not enumeration or physical qualification. To send bytes, preserve their lifetime through the control adapter’s acquire-observed outer SETTLED. The view struct requires natural C alignment; rejection is not an arbitrary address probe. Descriptor bytes need only byte alignment and remain externally readable.

Parameters:
  • profile – [in] Immutable exact selected FS endpoint facts.

  • descriptor – [in] Complete external descriptor; never copied/retained.

Returns:

Success, INVALID or UNSUPPORTED, with no hardware or output effects.

struct nx_usb_descriptor_view_t
#include <usb_descriptors.h>

Public Members

const uint8_t *bytes
size_t length

user_io_broker.h

Narrow kernel-invoked user GPIO message contract.

Author

Nexus Team

Version

1.0.0

Date

2026-10-11

Copyright

Copyright (c) 2026 Nexus Team

Typedefs

typedef struct nx_user_io_broker nx_user_io_broker_t

Broker and persistent kernel call storage stay provider private.

typedef struct nx_user_io_call nx_user_io_call_t

Enums

enum nx_user_io_constants

Only scalar GPIO operations are admitted by this message ABI.

Values:

enumerator NX_USER_IO_ABI
enumerator NX_USER_GPIO_READ
enumerator NX_USER_GPIO_WRITE

Functions

nx_user_io_result_t nx_user_io_broker_gpio(nx_user_io_broker_t *broker, nx_user_io_call_t *call, const nx_user_io_message_t *message, nx_user_io_reply_t *reply)

Execute one scalar GPIO message through a trusted gateway.

Note

Kernel-invoked privileged Thread with incoming masks clear, one serialized broker executor. Principal comes from the configured trusted kernel identity port. Pin both validated memory ranges before any GPIO call; snapshot input once, copy an initialized reply. Kernel call storage is zero-initialized outside user RAM and must outlive retained pins. No OS SVC/MPU/TZ wiring or user privilege elevation is provided by this component.

Returns:

REJECTED has accepted=false, no pin/effect. ACCEPTED may already be detached or retain cleanup after a failure.

nx_user_io_result_t nx_user_io_broker_gpio_finish(nx_user_io_broker_t *broker, nx_user_io_call_t *call)

Retry retained cleanup without reading users or replaying IO.

Note

Same privileged serialized kernel owner, incoming masks clear. Successful unpin follows actual provider/observer drain; a failed unpin keeps memory, call slot and identity retained. Does not imply that a previously performed GPIO write can be reversed.

struct nx_user_io_message_t
#include <user_io_broker.h>

Untrusted copied message; identity never comes from users.

Note

No arbitrary port, MMIO, callback, slot or principal pointer. reserved words must be zero. WRITE has read_mask=0 and disjoint set/reset masks. READ has zero set/reset masks and a positive authorized read_mask. Caller keeps storage immutable until the gateway completes or retains its pin.

Public Members

uint32_t abi
uint32_t device
uint32_t operation
uint32_t set_mask
uint32_t reset_mask
uint32_t read_mask
uint32_t reserved[2]
struct nx_user_io_reply_t
#include <user_io_broker.h>

Fully initialized copied result; value is zero for errors/WRITE.

Public Members

uint32_t result
uint32_t value
struct nx_user_io_result_t
#include <user_io_broker.h>

Distinguish admission, cleanup retention and possible effect.

Note

accepted means at least one memory pin was acquired. On retained=true the exact kernel call slot and user address space remain borrowed. device_effect_possible is set before a WRITE provider call; an error cannot authorize replay. result describes admission/device execution; cleanup_result separately describes the most recent release attempt. This is software responsibility, not physical pin evidence.

Public Members

nx_result_t result
nx_result_t cleanup_result
bool accepted
bool retained
bool device_effect_possible