ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_c6link_tlv.c File Reference

The two-tag envelope the co-processor's serial endpoint speaks. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_c6link.h"
#include "ra8_c6link_internal.h"
Include dependency graph for ra8_c6link_tlv.c:

Go to the source code of this file.

Functions

static uint16_t internal_c6link_tlv_tag (uint8_t *out, uint16_t at, uint8_t type, uint16_t len)
 Write one three-byte tag header at a cursor.
static uint16_t internal_c6link_tlv_len (const uint8_t *buf, uint16_t at)
 Read one tag's little-endian 16-bit length.
ra8_err_t priv_c6link_tlv_open (uint8_t *out, uint16_t cap, uint16_t proto_len, uint16_t *body_at)
 Write both envelope tags ahead of a protobuf payload.
static bool internal_c6link_tlv_named (const uint8_t *payload)
 Check that a payload names one of the two RPC endpoints.
const uint8_t * priv_c6link_tlv_body (const uint8_t *payload, uint16_t len, uint16_t *proto_len)
 Strip the envelope off a received serial payload.

Detailed Description

The two-tag envelope the co-processor's serial endpoint speaks.

Tag
[Ring 4 / PAL] {World: NS}

Six bytes of framing sit between the payload header and the protobuf message: a tag naming the endpoint, then a tag introducing the data. Upstream builds and parses them in compose_tlv() and parse_tlv() inside drivers/virtual_serial_if/serial_if.c, which this tree does not compile – its transmit path expands HOSTED_CALLOC, whose failure arm is a goto to a caller-supplied label, and NASA Power of 10 Rule 1 forbids that. The envelope itself is trivial, so it is restated here rather than dragged in with a rule violation attached.

Both endpoint names are accepted on receive. A response arrives on RPCRsp and an unsolicited event on RPCEvt; upstream requires every registered endpoint name to be the same length, and its own parser checks that, so the two are interchangeable as far as the framing is concerned.

Since
0.1.0

Definition in file ra8_c6link_tlv.c.

Function Documentation

◆ internal_c6link_tlv_len()

uint16_t internal_c6link_tlv_len ( const uint8_t * buf,
uint16_t at )
static

Read one tag's little-endian 16-bit length.

Reads what the sender wrote rather than assuming the host's own byte order, which is what makes the parser portable to a big-endian host.

Parameters
[in]bufBuffer holding the tag; must be non-null.
[in]atOffset of the tag's type byte.
Returns
The length the tag declares.
Return values
0The tag declares an empty value.
Precondition
At least k_ra8_c6link_tlv_value bytes are readable at buf + at.
The caller has already bounds-checked at against the payload.
Postcondition
No buffer is modified.
The result is the value the sender wrote, byte order reversed.
Note
Split out so both tags are read by the same code path.
Since
0.1.0

Definition at line 84 of file ra8_c6link_tlv.c.

References k_ra8_c6link_tlv_len_hi, k_ra8_c6link_tlv_len_lo, k_ra8_c6link_tlv_shift, and RA8_INTERNAL.

Referenced by priv_c6link_tlv_body().

◆ internal_c6link_tlv_named()

bool internal_c6link_tlv_named ( const uint8_t * payload)
static

Check that a payload names one of the two RPC endpoints.

Compares against both registered endpoint names at once, so a response and an unsolicited event are accepted by one pass rather than two.

Parameters
[in]payloadFrame payload; must be non-null and long enough.
Returns
true when every octet matches RPCRsp or matches RPCEvt.
Return values
trueThe envelope is addressed to this host's RPC endpoint.
falseAt least one octet matched neither name.
Precondition
k_ra8_c6link_tlv_overhead bytes are readable at payload.
Both endpoint names have the same length, which a static_assert above guarantees.
Postcondition
No buffer is modified.
The loop ran exactly k_ra8_c6link_tlv_ep_len times.
Note
The loop is bounded by k_ra8_c6link_tlv_ep_len (NASA Rule 2).
Since
0.1.0

Definition at line 133 of file ra8_c6link_tlv.c.

References k_ra8_c6link_tlv_ep_len, k_ra8_c6link_tlv_value, and RA8_INTERNAL.

Referenced by priv_c6link_tlv_body().

◆ internal_c6link_tlv_tag()

uint16_t internal_c6link_tlv_tag ( uint8_t * out,
uint16_t at,
uint8_t type,
uint16_t len )
static

Write one three-byte tag header at a cursor.

Parameters
[out]outBuffer being filled; must be non-null.

One tag header is a type octet and a little-endian length, and both tags of the envelope are written by this.

Parameters
[in]atOffset to write at.
[in]typeTag type.
[in]lenValue length that follows.
Returns
The offset just past the tag header, which addresses its value.
Return values
non-zeroThe offset of the tag's value, always three past at.
Precondition
At least k_ra8_c6link_tlv_value bytes are writable at out + at.
The caller has already checked the buffer capacity.
Postcondition
Exactly three bytes were written, length low octet first.
The returned offset addresses the tag's value.
Note
Matches the byte order compose_tlv() writes upstream.
Since
0.1.0

Definition at line 59 of file ra8_c6link_tlv.c.

References k_ra8_c6link_tlv_len_hi, k_ra8_c6link_tlv_len_lo, k_ra8_c6link_tlv_mask, k_ra8_c6link_tlv_shift, k_ra8_c6link_tlv_type, and k_ra8_c6link_tlv_value.

Referenced by priv_c6link_tlv_open().

◆ priv_c6link_tlv_body()

const uint8_t * priv_c6link_tlv_body ( const uint8_t * payload,
uint16_t len,
uint16_t * proto_len )
nodiscard

Strip the envelope off a received serial payload.

Both endpoint names are accepted, as upstream's parse_tlv() does: a response arrives on RPCRsp and an unsolicited event on RPCEvt, and the two are the same length by construction.

Parameters
[in]payloadFrame payload; must be non-null.
[in]lenPayload length in bytes.
[out]proto_lenProtobuf length found; must be non-null.
Returns
Pointer to the protobuf bytes, or null when the envelope is not one this endpoint recognises.
Return values
NULLThe tags, the endpoint name or the lengths did not check out.
Precondition
len bytes are readable at payload.
proto_len is writable.
Postcondition
On success the returned range lies wholly inside payload.
On failure proto_len is zero.
Note
Pure parsing; touches no hardware.
Example:
uint16_t n = 0U;
const uint8_t* proto = priv_c6link_tlv_body(payload, len, &n);
See also
priv_c6link_tlv_open
Since
0.1.0
MC/DC:
The tag test is a three-condition decision and the tests drive N+1 vectors against it; see tests/wireless/src/test_ra8_c6link.c.

Definition at line 146 of file ra8_c6link_tlv.c.

References internal_c6link_tlv_len(), internal_c6link_tlv_named(), k_ra8_c6link_tlv_ep_len, k_ra8_c6link_tlv_overhead, k_ra8_c6link_tlv_t_data, k_ra8_c6link_tlv_t_epname, k_ra8_c6link_tlv_type, and k_ra8_c6link_tlv_value.

Referenced by priv_c6link_rpc_consume().

◆ priv_c6link_tlv_open()

ra8_err_t priv_c6link_tlv_open ( uint8_t * out,
uint16_t cap,
uint16_t proto_len,
uint16_t * body_at )
nodiscard

Write both envelope tags ahead of a protobuf payload.

Parameters
[out]outBuffer to fill; must be non-null.
[in]capBytes available at out.
[in]proto_lenProtobuf length that will follow the envelope.
[out]body_atOffset the protobuf must be written at; must be non-null.
Returns
ra8_err_t Error code.
Return values
k_ra8_okThe envelope is written and body_at names its payload.
k_ra8_err_null_ptrout or body_at was null.
k_ra8_err_invalid_sizecap cannot hold envelope plus payload.
Precondition
cap bytes are writable at out.
proto_len is the exact packed size, not an estimate.
Postcondition
On success k_ra8_c6link_tlv_overhead bytes were written.
On failure out is not modified and body_at is zero.
Note
Pure formatting; touches no hardware.
Example:
uint16_t at = 0U;
(void)priv_c6link_tlv_open(buf, cap, packed, &at);
See also
priv_c6link_tlv_body
Since
0.1.0

Definition at line 91 of file ra8_c6link_tlv.c.

References internal_c6link_tlv_tag(), k_ra8_c6link_tlv_ep_len, k_ra8_c6link_tlv_overhead, k_ra8_c6link_tlv_t_data, k_ra8_c6link_tlv_t_epname, k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, and RA8_PRIV.

Referenced by internal_c6link_rpc_stage().