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

The single esp-hosted transaction, its decode and its verdict. More...

#include <stdint.h>
#include "c6_hosted.h"
#include "esp_hosted_header.h"
#include "esp_hosted_interface.h"
#include "esp_hosted_os_abstraction.h"
#include "esp_hosted_transport.h"
#include "port_esp_hosted_host_os.h"
#include "port_esp_hosted_host_spi.h"
#include "transport_drv.h"
Include dependency graph for c6_hosted_frame.c:

Go to the source code of this file.

Enumerations

enum  c6_hosted_proto_t : uint16_t {
  k_c6_hosted_hdr_bytes = (uint16_t)sizeof(struct esp_payload_header) ,
  k_c6_hosted_max_payload = (uint16_t)MAX_PAYLOAD_SIZE ,
  k_c6_hosted_byte_ones = 0xFFU ,
  k_c6_hosted_filler_if_num = 0x0FU
}
 Protocol sizes the verdict is judged against. More...
enum  c6_hosted_fill_t : uint8_t {
  k_c6_hosted_fill_mixed = 0U ,
  k_c6_hosted_fill_zero = 1U ,
  k_c6_hosted_fill_ones = 2U
}
 Coarse classification of the whole received buffer. More...
enum  c6_hosted_verdict_t : uint8_t {
  k_c6_hosted_verdict_pass = 0U ,
  k_c6_hosted_verdict_idle = 1U ,
  k_c6_hosted_verdict_transfer = 2U ,
  k_c6_hosted_verdict_zero = 3U ,
  k_c6_hosted_verdict_ones = 4U ,
  k_c6_hosted_verdict_offset = 5U ,
  k_c6_hosted_verdict_length = 6U ,
  k_c6_hosted_verdict_csum = 7U
}
 Outcome of the single transaction, in the order it is tested. More...

Functions

static void c6_hosted_build_idle_frame (void)
 Build the idle frame this application transmits.
static c6_hosted_fill_t c6_hosted_rx_fill (void)
 Classify the received buffer as all-zero, all-ones or mixed.
static uint16_t c6_hosted_rx_checksum (void)
 Recompute the checksum of the received frame.
static c6_hosted_verdict_t c6_hosted_classify (int32_t rc, uint16_t calc)
 Decide the verdict for the completed transaction.
static const char * c6_hosted_verdict_text (c6_hosted_verdict_t verdict)
 Map a verdict onto the text printed after PASS or FAIL.
static void c6_hosted_print_rx_header (uint16_t calc)
 Print every field of the received payload header.
void c6_hosted_run_transaction (void)
 Clock one full-duplex transaction and report the verdict.

Variables

static c6_hosted_frame_t s_c6_hosted_tx
 Transmit buffer holding the single idle frame this app sends.
static c6_hosted_frame_t s_c6_hosted_rx
 Receive buffer the co-processor's frame lands in.

Detailed Description

The single esp-hosted transaction, its decode and its verdict.

Tag
[Ring 6 / APP] {World: S}

Builds one valid zero-length esp-hosted frame, clocks it through the OS-abstraction vtable's _h_do_bus_transfer, decodes whatever came back and prints a single PASS/FAIL verdict line.

PASS criteria, in the order they are tested
  1. _h_do_bus_transfer returned RET_OK.
  2. The received buffer is neither uniformly 0x00 nor uniformly 0xFF.
  3. Either the frame is the co-processor's idle filler – if_type = ESP_MAX_IF, if_num = 0x0F, zero length – which is a pass in its own right, or every remaining test below holds.
  4. offset equals sizeof(struct esp_payload_header).
  5. len is within MAX_PAYLOAD_SIZE.
  6. The received checksum equals the recomputed one.

The undriven-bus test comes before the header tests deliberately. The C6 holds its controller-in line with an internal pull-down, so a connected co-processor that never saw a valid transaction reads all-zero, while an unterminated RA8 input floats to all-ones; the two are different faults, and reporting either as a checksum mismatch would point at the wrong problem entirely. See the app README for what each verdict implicates.

Every protocol size is read from the vendored headers rather than restated, so an upstream change moves this file with it.

Since
0.1.0

Definition in file c6_hosted_frame.c.

Enumeration Type Documentation

◆ c6_hosted_fill_t

enum c6_hosted_fill_t : uint8_t

Coarse classification of the whole received buffer.

A buffer that is uniformly 0x00 or uniformly 0xFF did not come from a peripheral, so it is reported as an undriven bus rather than as whatever header-shaped nonsense its first twelve bytes happen to form.

Invariant
Exactly one value describes a given buffer.
Example:
if (c6_hosted_rx_fill() != k_c6_hosted_fill_mixed) { report_undriven(); }
@ k_c6_hosted_fill_mixed
The buffer holds a mix of byte values.
static c6_hosted_fill_t c6_hosted_rx_fill(void)
Classify the received buffer as all-zero, all-ones or mixed.
See also
c6_hosted_verdict_t
Since
0.1.0
Enumerator
k_c6_hosted_fill_mixed 

The buffer holds a mix of byte values.

k_c6_hosted_fill_zero 

Every byte is 0x00.

k_c6_hosted_fill_ones 

Every byte is 0xFF.

Definition at line 97 of file c6_hosted_frame.c.

◆ c6_hosted_proto_t

enum c6_hosted_proto_t : uint16_t

Protocol sizes the verdict is judged against.

Each value is derived from a vendored header, so an upstream change to the transport buffer or the payload header moves these with it instead of leaving a stale literal behind.

Invariant
k_c6_hosted_hdr_bytes is the offset a well-formed frame carries, which is exactly what the PASS test compares against.
k_c6_hosted_max_payload bounds the length a valid frame may advertise; anything larger cannot fit the transaction.
Example:
if (frame->header.len > (uint16_t)k_c6_hosted_max_payload) { reject(); }
@ k_c6_hosted_max_payload
Largest payload a valid frame may advertise.
See also
esp_payload_header
Since
0.1.0
Enumerator
k_c6_hosted_hdr_bytes 

Payload-header size; twelve bytes on this ABI.

k_c6_hosted_max_payload 

Largest payload a valid frame may advertise.

k_c6_hosted_byte_ones 

The all-ones byte an unterminated RA8 input reads.

k_c6_hosted_filler_if_num 

The if_num the co-processor stamps into a filler frame.

Observed on silicon on 2026-07-28 and matching what c6_spi_probe recorded: a filler frame is if_type = ESP_MAX_IF, if_num = 0x0F, and length, offset and checksum all zero. It is NOT a data frame with a missing header, and judging it by a data frame's rules is a false negative – which is exactly what this application did on its first silicon run.

Definition at line 66 of file c6_hosted_frame.c.

◆ c6_hosted_verdict_t

enum c6_hosted_verdict_t : uint8_t

Outcome of the single transaction, in the order it is tested.

One enumerator per failing check, so the printed reason names the first thing that was actually wrong instead of a generic failure.

Invariant
k_c6_hosted_verdict_pass and k_c6_hosted_verdict_idle are the two values that print PASS; every other value prints FAIL.
Example:
void c6_hosted_puts(const char *text)
Write a NUL-terminated string to the board console.
static const char * c6_hosted_verdict_text(c6_hosted_verdict_t verdict)
Map a verdict onto the text printed after PASS or FAIL.
See also
c6_hosted_fill_t
Since
0.1.0
Enumerator
k_c6_hosted_verdict_pass 

A data frame arrived and verified.

k_c6_hosted_verdict_idle 

The co-processor's filler frame arrived: also a pass, and the usual answer to a host that asked nothing of a co-processor with nothing queued.

k_c6_hosted_verdict_transfer 

The vtable transfer did not return RET_OK.

k_c6_hosted_verdict_zero 

Receive buffer all-zero: bus not driven.

k_c6_hosted_verdict_ones 

Receive buffer all-ones: bus not driven.

k_c6_hosted_verdict_offset 

Header offset is not the payload-header size.

k_c6_hosted_verdict_length 

Advertised length exceeds MAX_PAYLOAD_SIZE.

k_c6_hosted_verdict_csum 

Received checksum differs from the recomputed one.

Definition at line 117 of file c6_hosted_frame.c.

Function Documentation

◆ c6_hosted_build_idle_frame()

void c6_hosted_build_idle_frame ( void )
static

Build the idle frame this application transmits.

Returns
Nothing.
Precondition
s_c6_hosted_tx is at least k_c6_hosted_hdr_bytes long.
The payload area is already zero, which .bss guarantees.
Postcondition
s_c6_hosted_tx holds a well-formed zero-length frame addressed to ESP_MAX_IF, the interface the transport treats as no-payload.
The checksum covers exactly the header, since the length is zero.
Note
Mirrors the filler frame the vendored spi_drv.c sends when it has nothing queued, so the co-processor sees nothing unusual.
Since
0.1.0

Definition at line 169 of file c6_hosted_frame.c.

References k_c6_hosted_hdr_bytes, and s_c6_hosted_tx.

Referenced by c6_hosted_run_transaction().

◆ c6_hosted_classify()

c6_hosted_verdict_t c6_hosted_classify ( int32_t rc,
uint16_t calc )
static

Decide the verdict for the completed transaction.

Parameters
[in]rcValue _h_do_bus_transfer returned.
[in]calcChecksum recomputed by c6_hosted_rx_checksum.
Returns
The first failing check, or k_c6_hosted_verdict_pass.
Return values
k_c6_hosted_verdict_transferThe transfer itself failed.
k_c6_hosted_verdict_zeroThe bus was never driven (all-zero).
k_c6_hosted_verdict_onesThe bus was never driven (all-ones).
k_c6_hosted_verdict_offsetOffset is not the header size.
k_c6_hosted_verdict_lengthLength exceeds MAX_PAYLOAD_SIZE.
k_c6_hosted_verdict_csumChecksum mismatch.
k_c6_hosted_verdict_idleThe co-processor's filler frame.
k_c6_hosted_verdict_passEvery check passed.
Precondition
The transfer has completed and s_c6_hosted_rx is stable.
calc came from c6_hosted_rx_checksum for this same buffer.
Postcondition
No application state is modified.
Exactly one verdict is returned.
Note
The undriven-bus tests come first deliberately: a missing wire and a mis-clocked link are different faults and must not be reported as one another.
Since
0.1.0

Definition at line 271 of file c6_hosted_frame.c.

References c6_hosted_rx_fill(), k_c6_hosted_fill_ones, k_c6_hosted_fill_zero, k_c6_hosted_filler_if_num, k_c6_hosted_hdr_bytes, k_c6_hosted_max_payload, k_c6_hosted_verdict_csum, k_c6_hosted_verdict_idle, k_c6_hosted_verdict_length, k_c6_hosted_verdict_offset, k_c6_hosted_verdict_ones, k_c6_hosted_verdict_pass, k_c6_hosted_verdict_transfer, k_c6_hosted_verdict_zero, RET_OK, and s_c6_hosted_rx.

Referenced by c6_hosted_run_transaction().

◆ c6_hosted_print_rx_header()

void c6_hosted_print_rx_header ( uint16_t calc)
static

Print every field of the received payload header.

Parameters
[in]calcChecksum recomputed by c6_hosted_rx_checksum.
Returns
Nothing.
Precondition
The transfer has completed and s_c6_hosted_rx is stable.
The console is up.
Postcondition
One line carrying all header fields and both checksums was emitted.
No application state is modified.
Note
Printed for every outcome: on a dead bus the field values are themselves the evidence.
Since
0.1.0

Definition at line 352 of file c6_hosted_frame.c.

References c6_hosted_put_hex(), c6_hosted_put_u32(), c6_hosted_puts(), k_c6_hosted_hex_byte, k_c6_hosted_hex_csum, and s_c6_hosted_rx.

Referenced by c6_hosted_run_transaction().

◆ c6_hosted_run_transaction()

void c6_hosted_run_transaction ( void )

Clock one full-duplex transaction and report the verdict.

Returns
Nothing.
Precondition
ra8_esp_hosted_port_init returned k_ra8_ok.
The console is up.
Postcondition
Exactly one transfer line, one header line and one verdict line were emitted.
The receive buffer holds whatever the co-processor drove.
Note
Runs once, on the worker thread. The first completed transaction drains the co-processor's queued boot event for good, so a rerun needs the C6 reset.
See also
c6_hosted_report_sideband
Since
0.1.0

Definition at line 373 of file c6_hosted_frame.c.

References c6_hosted_build_idle_frame(), c6_hosted_classify(), c6_hosted_print_rx_header(), c6_hosted_put_i32(), c6_hosted_put_u32(), c6_hosted_puts(), c6_hosted_rx_checksum(), c6_hosted_verdict_text(), g_h, k_c6_hosted_frame_bytes, k_c6_hosted_verdict_idle, k_c6_hosted_verdict_pass, s_c6_hosted_rx, and s_c6_hosted_tx.

Referenced by c6_hosted_worker_entry().

◆ c6_hosted_rx_checksum()

uint16_t c6_hosted_rx_checksum ( void )
static

Recompute the checksum of the received frame.

Returns
The checksum computed over the received frame with its checksum field taken as zero.
Precondition
The transfer has completed and s_c6_hosted_rx is stable.
No other context is reading the header concurrently.
Postcondition
The checksum field holds exactly the value it held on entry.
No other buffer byte is modified.
Note
The span covers header plus payload only when the header is self-consistent; a garbage offset or length would otherwise run past the buffer, so those cases are summed over the header alone and fail on their own grounds instead.
Since
0.1.0

Definition at line 235 of file c6_hosted_frame.c.

References k_c6_hosted_hdr_bytes, k_c6_hosted_max_payload, and s_c6_hosted_rx.

Referenced by c6_hosted_run_transaction().

◆ c6_hosted_rx_fill()

c6_hosted_fill_t c6_hosted_rx_fill ( void )
static

Classify the received buffer as all-zero, all-ones or mixed.

Returns
The classification of s_c6_hosted_rx.
Return values
k_c6_hosted_fill_zeroEvery byte is 0x00.
k_c6_hosted_fill_onesEvery byte is 0xFF.
k_c6_hosted_fill_mixedAnything else.
Precondition
The transfer has completed, so the buffer is stable.
s_c6_hosted_rx is k_c6_hosted_frame_bytes long.
Postcondition
No buffer byte is modified.
Exactly one classification is returned.
Note
Scans the whole transaction, not just the header: a header that happens to look plausible inside an otherwise dead buffer is still a dead buffer. The scan is bounded by k_c6_hosted_frame_bytes.
Since
0.1.0

Definition at line 200 of file c6_hosted_frame.c.

References k_c6_hosted_byte_ones, k_c6_hosted_fill_mixed, k_c6_hosted_fill_ones, k_c6_hosted_fill_zero, k_c6_hosted_frame_bytes, and s_c6_hosted_rx.

Referenced by c6_hosted_classify().

◆ c6_hosted_verdict_text()

const char * c6_hosted_verdict_text ( c6_hosted_verdict_t verdict)
static

Map a verdict onto the text printed after PASS or FAIL.

Parameters
[in]verdictVerdict to describe.
Returns
A static NUL-terminated reason string; never null.
Return values
link upThe verdict is k_c6_hosted_verdict_pass.
link up &ndash; co-processor returned its idle filler frameThe verdict is k_c6_hosted_verdict_idle.
Precondition
verdict came from c6_hosted_classify.
The caller prints the string rather than storing it.
Postcondition
No application state is modified.
The returned pointer stays valid for the life of the program.
Note
An unrecognised verdict yields a distinct string rather than null, so a future enumerator cannot crash the report.
Since
0.1.0

Definition at line 316 of file c6_hosted_frame.c.

References k_c6_hosted_verdict_csum, k_c6_hosted_verdict_idle, k_c6_hosted_verdict_length, k_c6_hosted_verdict_offset, k_c6_hosted_verdict_ones, k_c6_hosted_verdict_pass, k_c6_hosted_verdict_transfer, and k_c6_hosted_verdict_zero.

Referenced by c6_hosted_run_transaction().

Variable Documentation

◆ s_c6_hosted_rx

c6_hosted_frame_t s_c6_hosted_rx
static

Receive buffer the co-processor's frame lands in.

Same type and alignment as s_c6_hosted_tx, and left zero until the transfer runs, so an all-zero buffer afterwards genuinely means nothing was clocked in.

Note
Touched only by the worker thread and the transfer it starts.
Warning
c6_hosted_rx_checksum zeroes the checksum field in place and restores it; do not read that field concurrently.
Since
0.1.0

Definition at line 155 of file c6_hosted_frame.c.

Referenced by c6_hosted_classify(), c6_hosted_print_rx_header(), c6_hosted_run_transaction(), c6_hosted_rx_checksum(), and c6_hosted_rx_fill().

◆ s_c6_hosted_tx

c6_hosted_frame_t s_c6_hosted_tx
static

Transmit buffer holding the single idle frame this app sends.

A c6_hosted_frame_t, so the payload header is reached through a union member rather than a cast. Aligned to k_c6_hosted_dma_align, the alignment the transport expects of a transaction buffer. Zero as .bss, so the bytes after the header are already the padding a valid frame wants.

Note
Touched only by the worker thread and the transfer it starts.
Warning
Do not resize independently of s_c6_hosted_rx; both ends clock exactly k_c6_hosted_frame_bytes.
Since
0.1.0

Definition at line 142 of file c6_hosted_frame.c.

Referenced by c6_hosted_build_idle_frame(), and c6_hosted_run_transaction().