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

One full esp-hosted SPI full-duplex transaction against the C6. More...

#include <stdint.h>
#include "c6_probe.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_err.h"
#include "ra8_port_utils.h"
#include "ra8_sci_spi.h"
#include "ra8_spi.h"
#include "ra8_time.h"
Include dependency graph for c6_xfer.c:

Go to the source code of this file.

Functions

static void internal_fill_idle_tx (void)
 Stamp the transmit buffer as an esp-hosted idle host frame.
static void internal_cs (ra8_level_t level)
 Drive the chip-select and let the line settle.
static bool internal_sample_ready (const c6_sideband_sample_t *s, uint8_t hs_idx)
 Decide whether one side-band sample says the C6 is ready.
static bool internal_wait_ready (uint8_t hs_idx)
 Wait, with a bounded poll, for the peripheral-ready condition.
static ra8_err_t internal_transfer (c6_sideband_sample_t *pre, c6_sideband_sample_t *mid, c6_sideband_sample_t *post)
 Clock one full esp-hosted transaction, sampling the side-band pins.
static c6_frame_kind_t internal_report_frame (c6_probe_stats_t *st)
 Decode, classify, tally and narrate the frame in the receive buffer.
static c6_frame_kind_t internal_one_xfer (uint32_t index, uint8_t hs_idx, c6_probe_stats_t *st)
 Clock one transaction and report everything it revealed.
ra8_err_t c6_probe_spi_pins_init (void)
 Route the Pmod1 SPI pins to SCI2 and own the chip-select as GPIO.
bool c6_probe_sweep_mode (ra8_spi_mode_t mode, uint32_t pclka_hz, c6_probe_stats_t *st, uint8_t *hs_idx)
 Run the transaction burst for one SPI mode.

Variables

static uint8_t s_c6_tx [k_c6_proto_buf_size]
 Transmit buffer: one full esp-hosted SPI transaction.
static uint8_t s_c6_rx [k_c6_proto_buf_size]
 Receive buffer: one full esp-hosted SPI transaction.

Detailed Description

One full esp-hosted SPI full-duplex transaction against the C6.

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

Owns the two 1600-byte transport buffers and the SCI2 Simple-SPI channel that clocks them. The transfer is split after the twelve-byte header so a side-band sample lands while the chip-select is still asserted – that is the window in which the C6 holds HANDSHAKE low, and it is what identifies the pin. Both halves go out inside one chip-select assertion, which is what the esp-hosted peripheral expects.

Since
0.1.0

Definition in file c6_xfer.c.

Function Documentation

◆ c6_probe_spi_pins_init()

ra8_err_t c6_probe_spi_pins_init ( void )
nodiscard

Route the Pmod1 SPI pins to SCI2 and own the chip-select as GPIO.

The three clocked signals go to their SCI function (PSEL = 00100b, which HUM Ch 20.6 "Multiplexed Pin Function Selector" maps to SCI 0/2/4/6/8), while the chip-select stays a GPIO so one assertion can span the whole 1600-byte esp-hosted frame.

Returns
ra8_err_t error code.
Return values
k_ra8_okAll four pins routed or claimed.
k_ra8_err_gpio_conflictA pin is already owned elsewhere.
k_ra8_err_gpio_invalid_portBoard pin table disagrees with the HAL.
Precondition
ra8_mstp_init has run so PFS writes land.
The diagnostics released every Pmod1 pin they claimed.
Postcondition
On success the chip-select is an output driven high (deasserted).
On success SCK / CIPO / COPI carry their SCI2 function.
Note
Not thread-safe; boot-time only.
Example:
if (c6_probe_spi_pins_init() != k_ra8_ok) { panic(); }
ra8_err_t c6_probe_spi_pins_init(void)
Route the Pmod1 SPI pins to SCI2 and own the chip-select as GPIO.
Definition c6_xfer.c:322
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
See also
c6_probe_sweep_mode
Since
0.1.0

Definition at line 322 of file c6_xfer.c.

References k_ra8_board_pmod1_spi_cipo, k_ra8_board_pmod1_spi_copi, k_ra8_board_pmod1_spi_cs, k_ra8_board_pmod1_spi_sck, k_ra8_level_high, k_ra8_ok, k_ra8_psel_sci_async, ra8_gpio_output_init(), and ra8_pfs_route_peripheral().

Referenced by main().

◆ c6_probe_sweep_mode()

bool c6_probe_sweep_mode ( ra8_spi_mode_t mode,
uint32_t pclka_hz,
c6_probe_stats_t * st,
uint8_t * hs_idx )

Run the transaction burst for one SPI mode.

Parameters
[in]modeClock polarity / phase to open the channel with.
[in]pclka_hzSCI baud-clock source, in hertz.
[in,out]stStatistics block to accumulate into.
[in,out]hs_idxHandshake index, refined as evidence accumulates.
Returns
true when the C6 answered with a recognisable frame.
Return values
trueAt least one idle or data frame decoded in this mode.
falseThe mode produced nothing recognisable.
Precondition
pclka_hz is non-zero.
st and hs_idx are non-NULL.
Postcondition
The SPI channel is closed again before returning.
*hs_idx names the best handshake candidate seen so far.
Note
Not thread-safe.
Example:
const bool up = c6_probe_sweep_mode(k_ra8_spi_mode_3, pclka, &st, &hs);
bool c6_probe_sweep_mode(ra8_spi_mode_t mode, uint32_t pclka_hz, c6_probe_stats_t *st, uint8_t *hs_idx)
Run the transaction burst for one SPI mode.
Definition c6_xfer.c:345
@ k_ra8_spi_mode_3
CPOL=1, CPHA=1.
Definition ra8_spi.h:65
See also
c6_probe_spi_pins_init
Since
0.1.0

Definition at line 345 of file c6_xfer.c.

References c6_probe_best(), c6_probe_put_u32(), c6_probe_puts(), c6_probe_stats_t::hs_vote, internal_one_xfer(), k_c6_frame_data, k_c6_frame_idle, k_c6_probe_gap_ms, k_c6_probe_min_votes, k_c6_probe_sck_hz, k_c6_probe_xfer_per_mode, k_c6_sb_count, k_ra8_board_pmod1_sci_channel, k_ra8_ok, ra8_delay_ms(), ra8_sci_spi_deinit(), and ra8_sci_spi_init().

Referenced by c6_probe_run().

◆ internal_cs()

void internal_cs ( ra8_level_t level)
static

Drive the chip-select and let the line settle.

Parameters
[in]levelLevel to drive: low asserts the C6's chip-select.
Precondition
The chip-select was claimed by c6_probe_spi_pins_init.
level is a valid ra8_level_t.
Postcondition
The chip-select holds level.
At least k_c6_probe_cs_hold_ms of setup or hold time elapsed.
Note
Not thread-safe.
Since
0.1.0

Definition at line 93 of file c6_xfer.c.

References k_c6_probe_cs_hold_ms, k_ra8_board_pmod1_spi_cs, ra8_delay_ms(), and ra8_gpio_write().

Referenced by internal_transfer().

◆ internal_fill_idle_tx()

void internal_fill_idle_tx ( void )
static

Stamp the transmit buffer as an esp-hosted idle host frame.

The reference host does exactly this when it has nothing to send: zero the whole 1600-byte buffer and set if_type = ESP_MAX_IF, leaving length, offset and checksum at zero (the dummy-buffer branch of spi_transaction() in esp-hosted-mcu host/drivers/transport/spi/spi_drv.c). The C6 recognises the marker and drops the frame without complaint.

Precondition
s_c6_tx is at least k_c6_proto_buf_size bytes.
No transfer is in flight.
Postcondition
Every byte of s_c6_tx outside byte zero is zero.
Byte zero carries k_c6_if_max in its low nibble.
Note
Not thread-safe.
Since
0.1.0

Definition at line 71 of file c6_xfer.c.

References k_c6_hdr_off_iface, k_c6_if_max, k_c6_proto_buf_size, s_c6_rx, and s_c6_tx.

Referenced by internal_transfer().

◆ internal_one_xfer()

c6_frame_kind_t internal_one_xfer ( uint32_t index,
uint8_t hs_idx,
c6_probe_stats_t * st )
static

Clock one transaction and report everything it revealed.

Parameters
[in]indexOne-based transaction number, for the log.
[in]hs_idxIdentified handshake index, or k_c6_sb_count.
[in,out]stStatistics block to accumulate into.
Returns
The classification of the received frame.
Return values
k_c6_frame_garbageThe transfer failed, was skipped, or the received bytes carry no esp-hosted structure.
k_c6_frame_idleThe C6 answered with its idle filler frame.
k_c6_frame_dataA real frame arrived and its checksum verified.
k_c6_frame_bad_csumA real-looking frame failed its checksum.
Precondition
The SPI channel is initialised and the console is up.
st is non-NULL.
Postcondition
st->attempts grew by one whenever a transfer was clocked.
One transaction block was printed to the console.
Note
Not thread-safe.
Since
0.1.0

Definition at line 292 of file c6_xfer.c.

References c6_probe_stats_t::attempts, c6_probe_print_sideband(), c6_probe_put_u32(), c6_probe_puts(), c6_probe_vote(), internal_report_frame(), internal_transfer(), internal_wait_ready(), k_c6_frame_garbage, and k_ra8_ok.

Referenced by c6_probe_sweep_mode().

◆ internal_report_frame()

c6_frame_kind_t internal_report_frame ( c6_probe_stats_t * st)
static

Decode, classify, tally and narrate the frame in the receive buffer.

Split out of internal_one_xfer so each stays inside the project's function-length budget: this half owns everything that happens after the bytes have been clocked, which is exactly the part a reader wants to follow without the pin-sampling around it.

Parameters
[in,out]stStatistics block whose per-kind counters are incremented.
Returns
The classification of the received frame.
Return values
k_c6_frame_garbageNo esp-hosted structure, or st was NULL.
k_c6_frame_idleThe C6 answered with its idle filler frame.
k_c6_frame_dataA real frame arrived and its checksum verified.
k_c6_frame_bad_csumA real-looking frame failed its checksum.
Precondition
s_c6_rx holds a completed transaction.
st is non-NULL and the console is up.
Postcondition
Exactly one counter in st grew, unless the frame was garbage.
One header line, one verdict line and (for a payload-bearing frame) one hex-dump line were printed.
Note
Not thread-safe.
Since
0.1.0

Definition at line 244 of file c6_xfer.c.

References c6_probe_stats_t::bad_csum_frames, c6_probe_classify(), c6_probe_decode_header(), c6_probe_dump_payload(), c6_probe_print_header(), c6_probe_puts(), c6_probe_stats_t::data_frames, c6_probe_stats_t::idle_frames, k_c6_frame_bad_csum, k_c6_frame_data, k_c6_frame_garbage, k_c6_frame_idle, c6_hdr_t::len, and s_c6_rx.

Referenced by internal_one_xfer().

◆ internal_sample_ready()

bool internal_sample_ready ( const c6_sideband_sample_t * s,
uint8_t hs_idx )
static

Decide whether one side-band sample says the C6 is ready.

Once HANDSHAKE has been identified the decision is that one pin. Before then no single pin can be gated on, so the weaker "some pin is asserted" rule stands in: the C6 raises HANDSHAKE whenever it is armed, so an all-low side-band means the C6 is not ready (or nothing is wired) and clocking would be pointless.

Parameters
[in]sSide-band sample to judge.
[in]hs_idxIdentified handshake index, or k_c6_sb_count when the map is not yet resolved.
Returns
true when the sample satisfies the ready condition.
Return values
trueThe gating pin (or, pre-map, any pin) read high.
falseNothing in the sample indicates readiness, or s was NULL.
Precondition
s was filled by c6_probe_sample_sideband.
hs_idx is a valid index or k_c6_sb_count.
Postcondition
Neither argument is modified.
Exactly one verdict is returned.
Note
Pure function; safe from any context.
Since
0.1.0

Definition at line 125 of file c6_xfer.c.

References k_c6_sb_count, and c6_sideband_sample_t::level.

Referenced by internal_wait_ready().

◆ internal_transfer()

ra8_err_t internal_transfer ( c6_sideband_sample_t * pre,
c6_sideband_sample_t * mid,
c6_sideband_sample_t * post )
static

Clock one full esp-hosted transaction, sampling the side-band pins.

Parameters
[out]preSample taken before the chip-select is asserted.
[out]midSample taken mid-transfer, chip-select asserted.
[out]postSample taken after the transfer and a settle delay.
Returns
ra8_err_t error code.
Return values
k_ra8_okBoth halves of the frame were clocked.
k_ra8_err_hw_timeoutThe SCI transmit or receive poll expired.
k_ra8_err_null_ptrA sample pointer was NULL.
Precondition
ra8_sci_spi_init succeeded for the Pmod1 channel.
All three sample pointers are non-NULL.
Postcondition
On success s_c6_rx holds a complete received frame.
The chip-select is released whether or not the transfer succeeded.
Note
Not thread-safe; blocks for the whole frame.
Since
0.1.0

Definition at line 193 of file c6_xfer.c.

References c6_probe_sample_sideband(), internal_cs(), internal_fill_idle_tx(), k_c6_probe_settle_ms, k_c6_proto_buf_size, k_c6_proto_hdr_size, k_ra8_board_pmod1_sci_channel, k_ra8_err_null_ptr, k_ra8_level_high, k_ra8_level_low, k_ra8_ok, ra8_delay_ms(), ra8_sci_spi_xfer(), s_c6_rx, and s_c6_tx.

Referenced by internal_one_xfer().

◆ internal_wait_ready()

bool internal_wait_ready ( uint8_t hs_idx)
static

Wait, with a bounded poll, for the peripheral-ready condition.

Parameters
[in]hs_idxIdentified handshake index, or k_c6_sb_count when the map is not yet resolved.
Returns
true when the ready condition was observed in budget.
Return values
trueinternal_sample_ready accepted a sample.
falseThe poll budget expired with no pin ready.
Precondition
The side-band pins were configured as inputs.
hs_idx is a valid index or k_c6_sb_count.
Postcondition
At most k_c6_probe_hs_poll_max samples were taken.
No pin state was modified.
Note
Not thread-safe.
Since
0.1.0

Definition at line 159 of file c6_xfer.c.

References c6_probe_sample_sideband(), internal_sample_ready(), k_c6_probe_hs_poll_max, k_c6_probe_hs_poll_ms, and ra8_delay_ms().

Referenced by internal_one_xfer().

Variable Documentation

◆ s_c6_rx

uint8_t s_c6_rx[k_c6_proto_buf_size]
static

Receive buffer: one full esp-hosted SPI transaction.

Statically allocated for the same reason as s_c6_tx.

Note
Written only by the SCI transfer.
Warning
Contents are meaningful only after a completed transfer.
Since
0.1.0

Definition at line 50 of file c6_xfer.c.

Referenced by internal_fill_idle_tx(), internal_report_frame(), and internal_transfer().

◆ s_c6_tx

uint8_t s_c6_tx[k_c6_proto_buf_size]
static

Transmit buffer: one full esp-hosted SPI transaction.

Statically allocated (NASA Power of 10 Rule 3 – no dynamic memory) and re-stamped before every transfer.

Note
Written only by internal_fill_idle_tx.
Warning
Never write past k_c6_proto_buf_size.
Since
0.1.0

Definition at line 40 of file c6_xfer.c.

Referenced by internal_fill_idle_tx(), and internal_transfer().