|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Link lifecycle, frame routing and the identity round-trip. More...
#include "ra8_c6link.h"#include <stddef.h>#include <stdint.h>#include "ra8_attributes.h"#include "ra8_c6link_internal.h"Go to the source code of this file.
Functions | |
| uint8_t | priv_c6link_copy_str (char *dst, uint8_t cap, const ProtobufCBinaryData *src) |
| Copy a length-counted binary field into a NUL-terminated string. | |
| bool | priv_c6link_copy_mac (ra8_c6link_mac_t *dst, const ProtobufCBinaryData *src) |
| Copy a binary field into a MAC address, all-or-nothing. | |
| void | priv_c6link_emit (ra8_c6link_t *link, const ra8_c6link_event_t *ev) |
| Deliver one decoded announcement to the registered callback. | |
| bool | priv_c6link_dispatch (ra8_c6link_t *link, const ra8_c6link_rx_view_t *view) |
| Route one well-formed received frame to whatever understands it. | |
| static ra8_err_t | internal_c6link_check_cfg (const ra8_c6link_cfg_t *cfg) |
| Reject a configuration the link cannot honour. | |
| 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_last_fault (const ra8_c6link_t *link, ra8_c6link_fault_t *out) |
| Report the last request that failed on this link. | |
| 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. | |
| static ra8_err_t | internal_c6link_take_fw (void *ctx, const void *msg_v) |
| Extract the co-processor identity from its answer. | |
| 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. | |
Link lifecycle, frame routing and the identity round-trip.
The handle's own file: opening and closing it, deciding which consumer a received frame belongs to, delivering announcements, and the one request that belongs to the link rather than to Wi-Fi – asking the co-processor who it is.
Definition in file ra8_c6link.c.
|
static |
Reject a configuration the link cannot honour.
Rejects a seam with a missing row here rather than discovering it as a null call at the first transaction, and refuses an arena too small to decode the largest message this library reads.
| [in] | cfg | Configuration the caller supplied; must be non-null. |
| k_ra8_ok | Every field is usable. |
| k_ra8_err_null_ptr | A transport row or the arena pointer was null. |
| k_ra8_err_invalid_size | The arena is smaller than the minimum. |
cfg is non-null, which the caller has already checked. cfg. Definition at line 134 of file ra8_c6link.c.
References ra8_c6link_cfg::arena, ra8_c6link_cfg::arena_bytes, ra8_c6link_transport::delay_ms, ra8_c6link_transport::handshake_active, k_ra8_c6link_arena_min, k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, RA8_INTERNAL, ra8_c6link_transport::transfer, and ra8_c6link_cfg::transport.
Referenced by ra8_c6link_open().
|
static |
Extract the co-processor identity from its answer.
The co-processor's identity is the host/co-processor version lock, so every field is copied out for the caller to compare rather than judged here.
| [in] | ctx | A ra8_c6link_take_ctx_t whose out is the identity record. |
| [in] | msg_v | The decoded Rpc; must be non-null. |
| k_ra8_ok | The identity was copied out. |
| k_ra8_err_protocol_error | The answer carried no body, or the co-processor reported a failure. |
ctx names a live link and a writable identity record. msg_v is still owned by the decoder. Definition at line 291 of file ra8_c6link.c.
References ra8_c6link_fw_version::chip_id, k_ra8_err_protocol_error, ra8_c6link_take_ctx::link, ra8_c6link_fw_version::major, ra8_c6link_fw_version::minor, ra8_c6link_take_ctx::out, ra8_c6link_fw_version::patch, priv_c6link_copy_str(), priv_c6link_resp(), RA8_INTERNAL, ra8_c6link_fw_version::target, and ra8_c6link_fw_version::target_len.
Referenced by ra8_c6link_fw_version().
|
nodiscard |
Copy a binary field into a MAC address, all-or-nothing.
| [out] | dst | Address to fill; must be non-null. |
| [in] | src | Binary field from a decoded message; null clears dst. |
| true | dst holds the address. |
| false | The field was absent or the wrong length; dst is cleared. |
dst does not overlap src. dst is either fully written or fully cleared. src is not modified.Definition at line 56 of file ra8_c6link.c.
References k_ra8_c6link_mac_bytes, ra8_c6link_mac::octet, and RA8_PRIV.
Referenced by internal_c6link_rpc_ev_connected(), internal_c6link_rpc_ev_disconnected(), internal_c6link_take_ap(), and internal_c6link_take_mac().
| uint8_t priv_c6link_copy_str | ( | char * | dst, |
| uint8_t | cap, | ||
| const ProtobufCBinaryData * | src ) |
Copy a length-counted binary field into a NUL-terminated string.
Shared by the event decoder and the AP-record decoder. The co-processor supplies the bytes, so nothing about them is trusted: the copy is bounded by the destination and terminated whatever the source did.
| [out] | dst | Destination; must be non-null and cap bytes long. |
| [in] | cap | Bytes available at dst, including the terminator. |
| [in] | src | Binary field from a decoded message; null copies nothing. |
| 0 | The field was absent, empty, or cap left no room. |
cap is at least one, so a terminator always fits. dst does not overlap src. dst is NUL-terminated. Definition at line 37 of file ra8_c6link.c.
References RA8_PRIV.
Referenced by internal_c6link_rpc_ev_connected(), internal_c6link_rpc_ev_disconnected(), internal_c6link_take_ap(), and internal_c6link_take_fw().
|
nodiscard |
Route one well-formed received frame to whatever understands it.
Control-plane frames go to the RPC decoder, station and access-point frames to the Ethernet receive callback, and everything else is counted. ESP_PRIV_IF frames are counted rather than decoded: this co-processor build transmits its only privileged frame with a checksum that does not match its own header (#529), so a conformant host never sees a valid one.
| [in,out] | link | Open handle; must be non-null. |
| [in] | view | Payload location from the classifier; must be non-null. |
| true | The awaited answer arrived. |
| false | Keep clocking. |
view is populated. Definition at line 87 of file ra8_c6link.c.
References ra8_c6link::cb_ctx, ra8_c6link_stats::eth_in, ra8_c6link_rx_view::if_type, ra8_c6link_rx_view::len, ra8_c6link_rx_view::offset, priv_c6link_rpc_consume(), RA8_PRIV, ra8_c6link::rx, ra8_c6link::rx_cb, ra8_c6link::stats, and ra8_c6link_stats::unrouted.
Referenced by internal_c6link_pump_receive().
| void priv_c6link_emit | ( | ra8_c6link_t * | link, |
| const ra8_c6link_event_t * | ev ) |
Deliver one decoded announcement to the registered callback.
Lives in ra8_c6link.c beside the rest of the handle's state, and is called from the RPC decoder once it has turned an Event_* message into a first-party record.
| [in,out] | link | Open handle; must be non-null. |
| [in] | ev | Decoded announcement; must be non-null. |
ev is fully populated for its kind. ev is the boot announcement.Definition at line 71 of file ra8_c6link.c.
References ra8_c6link::boot_seen, ra8_c6link::cb_ctx, ra8_c6link::event_cb, ra8_c6link_stats::events, k_ra8_c6link_event_boot, ra8_c6link_event::kind, RA8_PRIV, and ra8_c6link::stats.
Referenced by internal_c6link_rpc_event().
|
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().