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

ra8_io SPI-bus facade – one controller-transfer vtable over thechip's two SPI implementations. More...

#include <stdint.h>
#include "ra8_err.h"
#include "ra8_spi.h"
#include "ra8_spi_bus_ops.h"
Include dependency graph for ra8_io_spi_bus.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_io_spi_bus_t
 Caller-allocated SPI-bus handle binding a backend to its context. More...

Typedefs

typedef struct ra8_io_spi_bus_iface ra8_io_spi_bus_iface_t

Functions

ra8_err_t ra8_io_spi_bus_xfer8 (const ra8_io_spi_bus_t *bus, uint8_t tx, uint8_t *rx)
 Full-duplex single-byte exchange on the bound bus.
ra8_err_t ra8_io_spi_bus_write_read (const ra8_io_spi_bus_t *bus, const void *tx, void *rx, uint32_t len, ra8_spi_bit_width_t width)
 Full-duplex multi-frame transfer on the bound bus.
ra8_err_t ra8_io_spi_bus_set_clock (const ra8_io_spi_bus_t *bus, uint32_t baud_hz, uint32_t pclk_hz)
 Re-program the bound bus bit-rate without reconfiguring.
ra8_err_t ra8_io_spi_bus_as_ops (const ra8_io_spi_bus_t *bus, ra8_spi_bus_ops_t *out)
 Expose a bound bus through the Ring-3 seam ra8_spi_bus_ops_t.

Detailed Description

ra8_io SPI-bus facade – one controller-transfer vtable over the

chip's two SPI implementations.

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

The RA8D2 implements SPI twice: the dedicated SPI_B block (ra8_spi.h) and SCI in Simple-SPI mode (ra8_sci_spi.h – the transport behind the Pmod2 microSD path). Their controller transfer surfaces are byte-for-byte identical, but every consumer used to hard-wire one side by function name. This facade gives callers one handle-based surface so the physical peripheral a board revision routes to a device is a bind-time decision, not a call-site rewrite.

Modeled directly on the ra8_io_blockdev_t pattern: the handle (ra8_io_spi_bus_t) is caller-allocated; a backend _bind_*() helper (see ra8_io_spi_bus_spi_b.h and ra8_io_spi_bus_sci_spi.h) fills the opaque vtable with thin trampolines to the existing ra8_spi_* / ra8_sci_spi_* drivers, unmodified. No dynamic allocation occurs and no MMIO happens here – the wrapped drivers carry every HUM citation.

Bus bring-up (peripheral init, CPOL/CPHA, chip-select GPIO) stays with the caller: SPI device select is an out-of-band GPIO, so it is not part of this interface. I2C/I3C, which carry an in-band address, get their own facade (ra8_io_i2c_bus.h) rather than a merged one.

Boundary with Ring-3 device drivers

A Ring-3 device driver (e.g. ra8_epaper) must not depend on this Ring-4 facade – that would invert ring ordering (see docs/RING_AND_WORLD.md). The sanctioned bridge is ra8_io_spi_bus_as_ops, which exposes a bound bus through the Ring-3 seam ra8_spi_bus_ops_t (ra8_spi_bus_ops.h), mirroring ra8_io_blockdev_as_fs_backend().

Example:
(void)ra8_io_spi_bus_bind_spi_b(&bus, 0U); // today's board
// (void)ra8_io_spi_bus_bind_sci_spi(&bus, 0U); // future board revision
uint8_t rx = 0U;
(void)ra8_io_spi_bus_xfer8(&bus, 0xA5U, &rx);
ra8_err_t ra8_io_spi_bus_xfer8(const ra8_io_spi_bus_t *bus, uint8_t tx, uint8_t *rx)
Full-duplex single-byte exchange on the bound bus.
ra8_err_t ra8_io_spi_bus_bind_spi_b(ra8_io_spi_bus_t *bus, uint8_t channel)
Bind bus to SPI_B channel channel.
Caller-allocated SPI-bus handle binding a backend to its context.
Since
0.1.0

Definition in file ra8_io_spi_bus.h.

Typedef Documentation

◆ ra8_io_spi_bus_iface_t

Definition at line 83 of file ra8_io_spi_bus.h.

Function Documentation

◆ ra8_io_spi_bus_as_ops()

ra8_err_t ra8_io_spi_bus_as_ops ( const ra8_io_spi_bus_t * bus,
ra8_spi_bus_ops_t * out )
nodiscard

Expose a bound bus through the Ring-3 seam ra8_spi_bus_ops_t.

Fills out with a trampoline that forwards the seam's xfer8 into this facade, with out->ctx pointing at bus. This is the sanctioned bridge for handing a bound bus to a Ring-3 device driver (e.g. ra8_epaper) without the driver depending upward on ra8_io – the exact analogue of ra8_io_blockdev_as_fs_backend().

Parameters
[in]busBound bus handle (must out-live every seam call).
[out]outSeam to populate.
Returns
ra8_err_t Error code.
Return values
k_ra8_ok*out wired to bus.
k_ra8_err_null_ptrbus or out was NULL.
k_ra8_err_not_initializedNo backend is bound to bus.
Precondition
A backend has been bound into bus.
out is writable and out-lives no call made through it after bus is destroyed.
Postcondition
On success out->xfer8 is non-NULL and out->ctx references bus.
No bus or handle state is mutated.
Note
bus must remain valid for the entire lifetime of the seam.
See also
ra8_spi_bus_ops_t The Ring-3 seam definition.
Since
0.1.0

Definition at line 150 of file ra8_io_spi_bus.c.

References ra8_spi_bus_ops_t::ctx, internal_ops_xfer8(), internal_validate(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and ra8_spi_bus_ops_t::xfer8.

Referenced by ep_bringup_panel_bus().

◆ ra8_io_spi_bus_set_clock()

ra8_err_t ra8_io_spi_bus_set_clock ( const ra8_io_spi_bus_t * bus,
uint32_t baud_hz,
uint32_t pclk_hz )
nodiscard

Re-program the bound bus bit-rate without reconfiguring.

Forwards to ra8_spi_set_clock / ra8_sci_spi_set_clock. Used by protocols that must start slow and speed up after negotiation (e.g. the SD-card 400 kHz identification phase).

Parameters
[in]busBound bus handle.
[in]baud_hzTarget bit-rate in Hz (non-zero).
[in]pclk_hzCurrent peripheral clock in Hz (PCLKA on RA8D2).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBit-rate divider reprogrammed.
k_ra8_err_null_ptrbus was NULL.
k_ra8_err_not_initializedNo backend is bound to bus.
k_ra8_err_invalid_argbaud_hz zero or divider out of range.
Precondition
A backend has been bound into bus.
The underlying channel was initialised by its own driver init.
Postcondition
On success the channel's divider reflects the new rate.
On any non-ok return no caller-visible handle state changed.
Note
Not thread-safe with respect to the same channel.
Since
0.1.0

Definition at line 103 of file ra8_io_spi_bus.c.

References ra8_io_spi_bus_t::ctx, ra8_io_spi_bus_t::iface, internal_validate(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and ra8_io_spi_bus_iface::set_clock.

◆ ra8_io_spi_bus_write_read()

ra8_err_t ra8_io_spi_bus_write_read ( const ra8_io_spi_bus_t * bus,
const void * tx,
void * rx,
uint32_t len,
ra8_spi_bit_width_t width )
nodiscard

Full-duplex multi-frame transfer on the bound bus.

Forwards to the backend's bulk primitive (ra8_spi_write_read or ra8_sci_spi_xfer). Either buffer may be NULL: a NULL tx shifts idle fill bytes (SD / SPI-flash read convention) and a NULL rx discards the received bytes; both NULL is rejected by the backend. len == 0 is a no-op success. The SCI Simple-SPI backend supports 8-bit frames only and reports k_ra8_err_not_supported for wider width values.

Parameters
[in]busBound bus handle.
[in]txSource buffer (len units of width) or NULL.
[out]rxDestination buffer (len units of width) or NULL.
[in]lenNumber of frames to exchange.
[in]widthPer-frame bit width (ra8_spi_bit_width_t).
Returns
ra8_err_t Error code.
Return values
k_ra8_okEvery frame exchanged.
k_ra8_err_null_ptrbus was NULL, or both buffers NULL with len > 0.
k_ra8_err_not_initializedNo backend is bound to bus.
k_ra8_err_not_supportedBackend cannot do width (SCI != 8).
k_ra8_err_hw_timeoutThe transport's status poll expired.
Precondition
A backend has been bound into bus.
Buffer alignment matches width (16/32-bit frames need aligned pointers on the SPI_B backend).
Postcondition
On success len frames were clocked in both directions.
On any non-ok return no caller-visible handle state changed.
Note
Not thread-safe with respect to the same channel.
See also
ra8_io_spi_bus_xfer8 Single-byte variant.
Since
0.1.0

Definition at line 89 of file ra8_io_spi_bus.c.

References ra8_io_spi_bus_t::ctx, ra8_io_spi_bus_t::iface, internal_validate(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and ra8_io_spi_bus_iface::write_read.

Referenced by internal_do_bus_transfer().

◆ ra8_io_spi_bus_xfer8()

ra8_err_t ra8_io_spi_bus_xfer8 ( const ra8_io_spi_bus_t * bus,
uint8_t tx,
uint8_t * rx )
nodiscard

Full-duplex single-byte exchange on the bound bus.

Forwards to the bound backend's xfer8 primitive (ra8_spi_xfer8 or ra8_sci_spi_xfer8): shifts tx out on COPI and captures the CIPO byte into *rx.

Parameters
[in]busBound bus handle.
[in]txByte to transmit.
[out]rxReceive slot; may be NULL to discard the received byte.
Returns
ra8_err_t Error code.
Return values
k_ra8_okFrame exchanged.
k_ra8_err_null_ptrbus was NULL.
k_ra8_err_not_initializedNo backend is bound to bus.
k_ra8_err_hw_timeoutThe transport's status poll expired.
Precondition
A backend has been bound into bus.
The underlying channel was initialised by its own driver init.
Postcondition
On success one frame was clocked; *rx (if non-NULL) holds the received byte.
On any non-ok return no caller-visible handle state changed.
Note
Not thread-safe with respect to the same channel.
See also
ra8_io_spi_bus_write_read Multi-frame variant.
Since
0.1.0

Definition at line 79 of file ra8_io_spi_bus.c.

References ra8_io_spi_bus_t::ctx, ra8_io_spi_bus_t::iface, internal_validate(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and ra8_io_spi_bus_iface::xfer8.

Referenced by internal_ops_xfer8().