|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
The single integration boundary between this firmware and the ESP32-C6. More...
#include <stdint.h>#include "ra8_c6link_transport.h"#include "ra8_err.h"#include "ra8_mdl_protocol.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_c6link_mac |
| One IEEE 802 address, by value. More... | |
| struct | ra8_c6link_fw_version |
| Identity the co-processor reports about itself. More... | |
| struct | ra8_c6link_event |
| One decoded co-processor announcement. More... | |
| struct | ra8_c6link_fault |
| What the co-processor said when a request did not succeed. More... | |
| struct | ra8_c6link_stats |
| What one pump did on the wire, counted rather than inferred. More... | |
| struct | ra8_c6link_cfg |
| Everything ra8_c6link_open needs that the link cannot discover. More... | |
| struct | ra8_c6link_wait |
| The one outstanding request a link is waiting on. More... | |
| struct | ra8_c6link |
| Caller-allocated link handle. More... | |
Typedefs | |
| typedef struct ra8_c6link_mac | ra8_c6link_mac_t |
| typedef struct ra8_c6link_fw_version | ra8_c6link_fw_version_t |
| typedef struct ra8_c6link_event | ra8_c6link_event_t |
| typedef struct ra8_c6link_fault | ra8_c6link_fault_t |
| typedef struct ra8_c6link_stats | ra8_c6link_stats_t |
| typedef void(* | ra8_c6link_event_cb_t) (void *ctx, const ra8_c6link_event_t *ev) |
| Receiver for one decoded co-processor announcement. | |
| typedef void(* | ra8_c6link_rx_cb_t) (void *ctx, const uint8_t *frame, uint16_t len) |
| Receiver for one 802.3 frame the co-processor forwarded. | |
| typedef struct ra8_c6link_cfg | ra8_c6link_cfg_t |
| typedef ra8_err_t(* | ra8_c6link_take_fn_t) (void *ctx, const void *msg) |
| Extractor that copies an answer's fields out. | |
| typedef struct ra8_c6link_wait | ra8_c6link_wait_t |
| typedef struct ra8_c6link | ra8_c6link_t |
Enumerations | |
| enum | ra8_c6link_geometry_t : uint16_t { k_ra8_c6link_frame_bytes = 1600U , k_ra8_c6link_header_bytes = 12U , k_ra8_c6link_max_payload = 1588U , k_ra8_c6link_mac_bytes = 6U , k_ra8_c6link_ssid_max = 32U , k_ra8_c6link_dma_align = 64U , k_ra8_c6link_arena_min = 2048U } |
| Fixed sizes of the esp-hosted wire this link speaks. More... | |
| enum | ra8_c6link_budget_t : uint16_t { k_ra8_c6link_hs_wait_ms = 200U , k_ra8_c6link_hs_poll_ms = 1U , k_ra8_c6link_hs_giveup = 3U , k_ra8_c6link_gap_ms = 2U , k_ra8_c6link_rpc_transfers = 64U , k_ra8_c6link_announce_transfers = 8U } |
| Default pacing and bounds the link works to. More... | |
| enum | ra8_c6link_event_kind_t : uint8_t { k_ra8_c6link_event_boot = 0U , k_ra8_c6link_event_sta_connected = 1U , k_ra8_c6link_event_sta_disconnected = 2U , k_ra8_c6link_event_wifi = 3U } |
| The co-processor announcements this link surfaces to its owner. More... | |
Functions | |
| ra8_err_t | ra8_c6link_open (ra8_c6link_t *link, const ra8_c6link_cfg_t *cfg) |
| Bind a transport to a link handle and make it usable. | |
| ra8_err_t | ra8_c6link_close (ra8_c6link_t *link) |
| Release a link handle. | |
| bool | ra8_c6link_is_open (const ra8_c6link_t *link) |
| Report whether a handle is currently open. | |
| ra8_err_t | ra8_c6link_poll (ra8_c6link_t *link, uint16_t max_transactions, ra8_c6link_stats_t *stats) |
| Clock transactions, delivering whatever the co-processor sends. | |
| ra8_err_t | ra8_c6link_await_ready (ra8_c6link_t *link, uint16_t max_transactions, ra8_c6link_fw_version_t *out) |
| Announce this host and prove the co-processor is answering. | |
| ra8_err_t | ra8_c6link_fw_version (ra8_c6link_t *link, ra8_c6link_fw_version_t *out) |
| Ask the co-processor to identify itself. | |
| ra8_err_t | ra8_c6link_eth_send (ra8_c6link_t *link, const uint8_t *frame, uint16_t len) |
| Hand one 802.3 frame to the co-processor for transmission. | |
| ra8_err_t | ra8_c6link_last_fault (const ra8_c6link_t *link, ra8_c6link_fault_t *out) |
| Report the last request that failed on this link. | |
The single integration boundary between this firmware and the ESP32-C6.
Application code reaches the co-processor here and nowhere else. Above this header there is no protobuf, no TLV envelope, no payload header, no checksum and no SPI: there is a link you open, poll, send Ethernet frames on, and receive events from. Below it, ra8_c6link_transport_t is the only thing that touches hardware.
Definition in file ra8_c6link.h.
| typedef struct ra8_c6link_cfg ra8_c6link_cfg_t |
| typedef void(* ra8_c6link_event_cb_t) (void *ctx, const ra8_c6link_event_t *ev) |
Receiver for one decoded co-processor announcement.
| [in] | ctx | Opaque context from ra8_c6link_cfg::cb_ctx. |
| [in] | ev | Decoded announcement; never null and valid only for the duration of the call. |
Definition at line 389 of file ra8_c6link.h.
| typedef struct ra8_c6link_event ra8_c6link_event_t |
| typedef struct ra8_c6link_fault ra8_c6link_fault_t |
| typedef struct ra8_c6link_fw_version ra8_c6link_fw_version_t |
| typedef struct ra8_c6link_mac ra8_c6link_mac_t |
| typedef void(* ra8_c6link_rx_cb_t) (void *ctx, const uint8_t *frame, uint16_t len) |
Receiver for one 802.3 frame the co-processor forwarded.
| [in] | ctx | Opaque context from ra8_c6link_cfg::cb_ctx. |
| [in] | frame | Frame bytes, starting at the destination address; never null and valid only for the duration of the call. |
| [in] | len | Frame length in bytes; never zero, never above k_ra8_c6link_max_payload. |
Definition at line 407 of file ra8_c6link.h.
| typedef struct ra8_c6link_stats ra8_c6link_stats_t |
| typedef struct ra8_c6link ra8_c6link_t |
| typedef ra8_err_t(* ra8_c6link_take_fn_t) (void *ctx, const void *msg) |
Extractor that copies an answer's fields out.
Treat as private.
Declared here only because ra8_c6link_wait_t must have a complete layout for ra8_c6link_t to be caller-allocated. The msg argument is really a const Rpc* from the generated codec; it is typed opaquely so this public header needs no esp-hosted include path. Only translation units inside libs/ra8_c6link/src/ ever produce or call one.
| [in] | ctx | Extractor context supplied alongside the request. |
| [in] | msg | The decoded answer, valid only for the duration of the call. |
| k_ra8_ok | The answer was accepted and its fields copied out. |
Definition at line 462 of file ra8_c6link.h.
| typedef struct ra8_c6link_wait ra8_c6link_wait_t |
| enum ra8_c6link_budget_t : uint16_t |
Default pacing and bounds the link works to.
Every one of these exists to give a loop a statically provable bound (NASA Power of 10 Rule 2) and to turn "the co-processor never answered" into a returned error instead of a hang. The transaction rate is the bench-proven one: c6_hosted_init and c6_fw_version both ran the link at 5 MHz with a two-millisecond gap between transactions and zero bad checksums.
| Enumerator | |
|---|---|
| k_ra8_c6link_hs_wait_ms | Milliseconds to wait for HANDSHAKE before abandoning a transaction. |
| k_ra8_c6link_hs_poll_ms | Sampling period while waiting for HANDSHAKE. |
| k_ra8_c6link_hs_giveup | Consecutive HANDSHAKE timeouts after which a pump stops early. A co-processor that has not armed the line three times running is not there, and spending the rest of the budget re-asking turns "absent" into a minutes-long hang. |
| k_ra8_c6link_gap_ms | Settling gap between consecutive transactions. |
| k_ra8_c6link_rpc_transfers | Transactions one RPC call may clock while waiting for its response. |
| k_ra8_c6link_announce_transfers | Transactions ra8_c6link_await_ready spends on the announcement before it probes. Enough to place the capabilities frame and drain whatever the co-processor volunteers behind it; the bench bring-up settled on the same figure. Readiness is decided by the probe that follows, not by this budget, so a larger one would only lengthen the absent-hardware case. |
Definition at line 155 of file ra8_c6link.h.
| enum ra8_c6link_event_kind_t : uint8_t |
The co-processor announcements this link surfaces to its owner.
Deliberately short. These are the four unsolicited messages a station join and its supervision actually depend on; every other event the protocol defines is counted as unhandled rather than half-decoded into a type nobody consumes.
| Enumerator | |
|---|---|
| k_ra8_c6link_event_boot | Event_ESPInit: the co-processor has booted and is accepting RPC. |
| k_ra8_c6link_event_sta_connected | Event_StaConnected: the station has associated with an AP. |
| k_ra8_c6link_event_sta_disconnected | Event_StaDisconnected: the station has lost or left its AP. |
| k_ra8_c6link_event_wifi | Event_WifiEventNoArgs: a Wi-Fi event carrying only its own id, reported verbatim in ra8_c6link_event::wifi_event_id. |
Definition at line 255 of file ra8_c6link.h.
| enum ra8_c6link_geometry_t : uint16_t |
Fixed sizes of the esp-hosted wire this link speaks.
These are protocol facts, not tuning knobs. Each is cross-checked against the vendored esp-hosted headers by a static_assert in ra8_c6link_frame.c, so an upstream change breaks the build here instead of silently mis-framing. They are restated rather than included so that this public header – and therefore every consumer of the facade, including the NetX Duo glue – needs no esp-hosted include path at all.
| Enumerator | |
|---|---|
| k_ra8_c6link_frame_bytes | Bytes in one transaction; ESP_TRANSPORT_SPI_MAX_BUF_SIZE upstream. |
| k_ra8_c6link_header_bytes | sizeof(struct esp_payload_header) on this ABI. |
| k_ra8_c6link_max_payload | Largest payload one frame can carry. |
| k_ra8_c6link_mac_bytes | Octets in an IEEE 802 address. |
| k_ra8_c6link_ssid_max | Octets in the longest SSID 802.11 allows. |
| k_ra8_c6link_dma_align | Alignment the transport expects of a transaction buffer. The handle's two frames carry it so a DMA-capable backend can clock them without a bounce buffer. |
| k_ra8_c6link_arena_min | Smallest decode arena ra8_c6link_open accepts. The largest message this library decodes is the station's AP record, whose nested country and HE sub-messages plus their binary fields fit inside this with room to spare; a smaller arena would fail a decode at run time rather than at open, which is the wrong place to find out. |
Definition at line 108 of file ra8_c6link.h.
|
nodiscard |
Announce this host and prove the co-processor is answering.
Transmits the privileged host-capabilities frame – upstream's send_slave_config(), byte for byte – drains the few transactions behind LEGACY-OK: send_slave_config() is the upstream esp-hosted symbol name it so anything the co-processor volunteers reaches the event callback, and then decides readiness by asking a question and getting an answer: one identity exchange, whose reply is handed back in out.
Readiness is deliberately not the boot event. Event_ESPInit is emitted once, when the co-processor boots. On this bench the ESP32-C6 has its own supply, so resetting the RA8 does not reboot it and that event is long gone – it was consumed by whichever application was clocking the bus when it fired. A facade that waited for it therefore worked exactly once, on a freshly-flashed co-processor, and timed out on every run after. Waiting on a one-shot announcement to decide a steady-state property is the same defect #529 records against the ESP_PRIV_IF frame, wearing the RPC layer's clothes; the fix is to stop inferring liveness and measure it.
The announcement is still sent, because a co-processor that has just booted services no RPC until the host has introduced itself. Sending it to one that is already up is harmless – it re-states capabilities that have not changed.
| [in,out] | link | Open handle; must be non-null. |
| [in] | max_transactions | Transactions the announcement phase may clock; must be non-zero. See k_ra8_c6link_announce_transfers. |
| [out] | out | Receives the co-processor's identity; must be non-null. |
| k_ra8_ok | The co-processor answered; out is populated. |
| k_ra8_err_null_ptr | link or out was null. |
| k_ra8_err_not_initialized | link is not open. |
| k_ra8_err_invalid_arg | max_transactions was zero. |
| k_ra8_err_busy | A payload is already staged on link. |
| k_ra8_err_invalid_size | The capabilities frame would not fit, which is a build-time impossibility and therefore a corrupted handle. |
| k_ra8_err_timeout | The identity request went unanswered. |
| k_ra8_err_hw_timeout | The co-processor never armed HANDSHAKE, so no transaction was clocked. |
| k_ra8_err_spi_error | The transport refused a transfer. |
| k_ra8_err_protocol_error | The answer arrived malformed. |
link. out holds the identity and the link is usable. max_transactions transactions were clocked announcing, plus k_ra8_c6link_rpc_transfers probing.Definition at line 233 of file ra8_c6link.c.
References k_ra8_c6link_caps_bytes, k_ra8_c6link_header_bytes, k_ra8_err_busy, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_err_not_initialized, k_ra8_err_null_ptr, k_ra8_ok, ra8_c6link::open, priv_c6link_caps(), priv_c6link_pump(), ra8_c6link_fw_version(), ra8_c6link::tx, ra8_c6link::tx_if, and ra8_c6link::tx_len.
Referenced by c6_join_phase_ready(), c6_wifi_phase_ready(), internal_c6_cam_prepare_link(), internal_c6link_op_open(), and internal_open_and_join().
|
nodiscard |
Release a link handle.
Drops the transport binding, the callbacks and the arena reference, and marks the handle closed. The transport itself is not torn down – whoever brought it up owns that.
| [in,out] | link | Handle to release; must be non-null and open. |
| k_ra8_ok | The handle is closed. |
| k_ra8_err_null_ptr | link was null. |
| k_ra8_err_not_initialized | link was not open. |
link. link is invoked again.Definition at line 178 of file ra8_c6link.c.
References ra8_c6link::arena, ra8_c6link::cb_ctx, ra8_c6link::event_cb, k_ra8_err_not_initialized, k_ra8_err_null_ptr, k_ra8_ok, ra8_c6link::open, ra8_c6link::rx_cb, ra8_c6link::stats, ra8_c6link::transport, ra8_c6link::tx_len, and ra8_c6link::wait.
Referenced by internal_c6link_op_close(), and internal_run().
|
nodiscard |
Hand one 802.3 frame to the co-processor for transmission.
Stages the frame on the station interface and pumps until a transaction has carried it out. The data plane needs no protobuf: the frame is the payload, behind the same twelve-byte header the control plane uses.
| [in,out] | link | Open handle; must be non-null. |
| [in] | frame | Frame bytes, starting at the destination address; must be non-null. |
| [in] | len | Frame length; must be non-zero and at most k_ra8_c6link_max_payload. |
| k_ra8_ok | The frame was clocked out. |
| k_ra8_err_null_ptr | link or frame was null. |
| k_ra8_err_not_initialized | link is not open. |
| k_ra8_err_invalid_size | len was zero or above the payload cap. |
| k_ra8_err_busy | Another payload is already staged. |
| k_ra8_err_hw_timeout | The co-processor never armed HANDSHAKE. |
| k_ra8_err_spi_error | The transport refused a transfer. |
len bytes are readable at frame. Definition at line 338 of file ra8_c6link.c.
References k_ra8_c6link_header_bytes, k_ra8_c6link_hs_giveup, k_ra8_c6link_max_payload, k_ra8_err_busy, k_ra8_err_hw_timeout, k_ra8_err_invalid_size, k_ra8_err_not_initialized, k_ra8_err_null_ptr, k_ra8_ok, ra8_c6link::open, priv_c6link_pump(), ra8_c6link::tx, ra8_c6link::tx_if, and ra8_c6link::tx_len.
Referenced by internal_handle_send().
|
nodiscard |
Ask the co-processor to identify itself.
Issues Req_GetCoprocessorFwVersion and decodes the answer. This is the cheapest complete proof that the whole stack works – framing, checksum, TLV, protobuf, correlation – because the answer is a fact the host can check rather than merely receive.
| [in,out] | link | Open handle; must be non-null. |
| [out] | out | Identity to fill; must be non-null. |
| k_ra8_ok | out holds the co-processor's answer. |
| k_ra8_err_null_ptr | link or out was null. |
| k_ra8_err_not_initialized | link is not open. |
| k_ra8_err_busy | A request is already outstanding on link. |
| k_ra8_err_timeout | The co-processor did not answer within the budget. |
| k_ra8_err_hw_timeout | The co-processor never armed HANDSHAKE, so no transaction was clocked. |
| k_ra8_err_protocol_error | The answer arrived but reported a failure. |
| k_ra8_err_spi_error | The transport refused a transfer. |
link. out is set from the answer. Definition at line 310 of file ra8_c6link.c.
References internal_c6link_take_fw(), k_ra8_err_not_initialized, k_ra8_err_null_ptr, ra8_c6link::open, and priv_c6link_rpc_call().
Referenced by ra8_c6link_await_ready().
|
nodiscard |
Report whether a handle is currently open.
| [in] | link | Handle to inspect; null reads as closed. |
| true | The handle is usable. |
| false | The handle is null, never opened, or closed. |
Definition at line 198 of file ra8_c6link.c.
References ra8_c6link::open.
Referenced by ra8_c6link_wifi_ap_info(), ra8_c6link_wifi_join(), ra8_c6link_wifi_leave(), ra8_c6link_wifi_mac(), ra8_c6link_wifi_start(), and ra8_c6link_wifi_stop().
|
nodiscard |
Report the last request that failed on this link.
| [in] | link | Open handle; must be non-null. |
| [out] | out | Fault record to fill; must be non-null. |
| k_ra8_ok | out holds the record; an all-zero record means no request has failed since the handle was opened. |
| k_ra8_err_null_ptr | link or out was null. |
out is fully written, including on the no-fault path.Definition at line 203 of file ra8_c6link.c.
References ra8_c6link::fault, k_ra8_err_null_ptr, and k_ra8_ok.
Referenced by c6_join_report_fault(), and c6_wifi_report_fault().
|
nodiscard |
Bind a transport to a link handle and make it usable.
Validates the seam and the arena, copies both into the handle, and resets every counter. No hardware is touched: bringing the transport itself up (pin routing, bus open, clocking) belongs to the backend that fills the seam, and happens before this call.
| [out] | link | Handle to initialise; must be non-null. |
| [in] | cfg | Configuration; must be non-null with every transport row filled and an arena of at least k_ra8_c6link_arena_min bytes. |
| k_ra8_ok | The link is open. |
| k_ra8_err_null_ptr | link, cfg, a transport row, or the arena pointer was null. |
| k_ra8_err_invalid_size | arena_bytes is below k_ra8_c6link_arena_min. |
| k_ra8_err_invalid_state | link is already open. |
link is zero-initialised, or has been closed. link is not modified.Definition at line 146 of file ra8_c6link.c.
References ra8_c6link::arena, ra8_c6link_cfg::arena, ra8_c6link::arena_bytes, ra8_c6link_cfg::arena_bytes, ra8_c6link::arena_last, ra8_c6link::arena_used, ra8_c6link::boot_seen, ra8_c6link::cb_ctx, ra8_c6link_cfg::cb_ctx, ra8_c6link::event_cb, ra8_c6link_cfg::event_cb, ra8_c6link::fault, internal_c6link_check_cfg(), k_ra8_err_invalid_state, k_ra8_err_null_ptr, k_ra8_ok, ra8_c6link::next_uid, ra8_c6link::open, ra8_c6link::rx_cb, ra8_c6link_cfg::rx_cb, ra8_c6link::stats, ra8_c6link::transport, ra8_c6link_cfg::transport, ra8_c6link::tx_if, ra8_c6link::tx_len, and ra8_c6link::wait.
Referenced by c6_join_open_link(), c6_wifi_open_link(), internal_c6_cam_open_link(), internal_c6link_op_open(), and internal_open_and_join().
|
nodiscard |
Clock transactions, delivering whatever the co-processor sends.
The pump. Each iteration waits for HANDSHAKE, transmits either a staged payload or an idle filler frame, clocks k_ra8_c6link_frame_bytes both ways, and classifies what came back: filler is counted, malformed and checksum-failing frames are counted and dropped, and well-formed frames are routed by interface – control plane to the RPC decoder, station traffic to the receive callback.
Call it to drive the link when no request is outstanding: to drain events, to receive Ethernet frames, or to give a staged transmit somewhere to go. Requests issued through this library pump internally and need no help.
| [in,out] | link | Open handle; must be non-null. |
| [in] | max_transactions | Transactions this call may clock; must be non-zero. |
| [out] | stats | Counters describing the run, or null to discard them. |
| k_ra8_ok | The pump ran; stats says what happened. |
| k_ra8_err_null_ptr | link was null. |
| k_ra8_err_not_initialized | link is not open. |
| k_ra8_err_invalid_arg | max_transactions was zero. |
| k_ra8_err_hw_timeout | HANDSHAKE never went active, so not one transaction was clocked. |
| k_ra8_err_spi_error | The transport refused a transfer. |
max_transactions transactions were clocked. stats, when non-null, holds the counts for exactly this call.max_transactions and the handshake wait by k_ra8_c6link_hs_wait_ms.Definition at line 212 of file ra8_c6link.c.
References k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_err_null_ptr, ra8_c6link::open, and priv_c6link_pump().
Referenced by c6_join_wait_connected(), c6_wifi_phase_station(), internal_c6_cam_wait_connected(), internal_c6link_op_service(), internal_rx_worker_entry(), and internal_wait_connected().