|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
SPI_B peripheral (target) mode driver – polling single-byte xfer. More...
#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_hw_err.h"#include "ra8_log.h"#include "ra8_mstp.h"#include "ra8_spi.h"#include "ra8_spi_regs.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_spi_b_target_poll_t : uint32_t { k_spi_b_target_poll_limit = 200000U } |
| Polling-loop budget for SPSR flag waits in target mode. More... | |
Functions | |
| static ra8_err_t | internal_target_wait_spsr (volatile r_spi_regs_t *reg, uint32_t flag_mask) |
| Wait for a single SPSR flag to assert, with a bounded poll. | |
| static uint32_t | internal_target_spcr (void) |
| Build the SPCR value for target (peripheral) mode. | |
| static uint32_t | internal_spcmd_target (const ra8_spi_cfg_t *cfg) |
| Build SPCMD0 value from a caller-supplied configuration. | |
| static void | internal_target_program_regs (volatile r_spi_regs_t *reg, const ra8_spi_cfg_t *cfg) |
| Write all control registers while SPCR.SPE=0. | |
| ra8_err_t | ra8_spi_b_target_init (uint8_t channel, const ra8_spi_cfg_t *cfg) |
| Initialise an SPI_B channel in target (peripheral) mode. | |
| ra8_err_t | ra8_spi_b_target_xfer (uint8_t channel, uint8_t tx, uint8_t *rx) |
| Exchange one byte as the SPI target in a polled blocking call. | |
Variables | |
| static const char * | s_tag = "SPI_B_TGT" |
| static const ra8_mstp_t | s_spi_mstp_table [k_ra8_spi_b_channel_count] |
| Channel-index -> MSTP id (HUM Ch 11.2.7 "MSTPCRB", p 444). | |
SPI_B peripheral (target) mode driver – polling single-byte xfer.
Companion translation unit to ra8_spi_b.c for the RA8D2 SPI_B (Type-B SPI) peripheral. Where ra8_spi_b.c implements the controller role – the MCU drives RSPCK and SSL – this file implements the target (peripheral) role in which an EXTERNAL controller drives RSPCK and asserts SSL (CS), and the MCU responds on CIPO (SDO) while receiving on COPI (SDI).
Register-level design (HUM Ch 43 "Serial Peripheral Interface" p 2877):
The SPSR flag waits run the same bounded polling loop on target and on the host unit-test build; on host the ra8_hw_err MMIO fault seam (ra8_fake_mmio_*) drives that real loop to succeed-after-N or to time out, so both the success and timeout legs execute on host. See internal_target_wait_spsr for the full rationale.
Inclusive terminology (this driver's names -> RA8D2 register effect):
Definition in file ra8_spi_b_target.c.
| enum ra8_spi_b_target_poll_t : uint32_t |
Polling-loop budget for SPSR flag waits in target mode.
Matches k_ra8_spi_b_poll_limit in ra8_spi_b.c so that both controller and target paths share the same worst-case timeout budget per flag wait. The value is large enough to cover the maximum SPI frame period at the minimum supported bit-rate (about 10 kHz) across the SPI_B clock divider range.
| Enumerator | |
|---|---|
| k_spi_b_target_poll_limit | Max iterations per flag wait. |
Definition at line 100 of file ra8_spi_b_target.c.
|
static |
Build SPCMD0 value from a caller-supplied configuration.
Encodes CPHA (bit 0), CPOL (bit 1), LSBF (bit 12), and SPB[20:16] from the public ra8_spi_cfg_t. The bit-rate divider and SSL-select fields are left at zero (clock is external; SSL is an input in target mode). See HUM Ch 43.2.7 "SPCMDm : SPI Command Register" p 2893.
A switch statement is used in place of || chains so that compiler MC/DC instrumentation tracks each mode as a distinct branch rather than a compound boolean.
| [in] | cfg | Caller-supplied configuration; must be non-NULL (validated by ra8_spi_b_target_init before this call). |
| SPCMD0 | CPHA/CPOL bits encode cfg->mode; LSBF set when cfg->lsb_first is true; SPB[4:0] set to k_ra8_spcmd_spb_8bit; all other fields (bit-rate divider, SSL-select) left zero. |
Definition at line 215 of file ra8_spi_b_target.c.
References k_ra8_spcmd_bit_spb_lo, k_ra8_spcmd_mask_cpha, k_ra8_spcmd_mask_cpol, k_ra8_spcmd_mask_lsbf, k_ra8_spcmd_mask_spb, k_ra8_spcmd_spb_8bit, k_ra8_spi_mode_0, k_ra8_spi_mode_1, k_ra8_spi_mode_2, k_ra8_spi_mode_3, ra8_spi_cfg_t::lsb_first, ra8_spi_cfg_t::mode, and RA8_INTERNAL.
Referenced by internal_target_program_regs().
|
static |
Write all control registers while SPCR.SPE=0.
Called from ra8_spi_b_target_init after SPCR has been cleared to zero (SPE=0). All registers that the HUM restricts to writes while SPE=0 (SPCR2, SPCMD0) are programmed here. SPCR3 is written with zero because SPBR is irrelevant in target mode (the external controller drives RSPCK). The FIFO is reset via SPFCR and SPSR flags are cleared twice (before and after the FIFO reset) to ensure the first call to ra8_spi_b_target_xfer sees a clean status.
| [in] | reg | Channel register block; validated non-NULL by caller. |
| [in] | cfg | Caller-supplied config; validated non-NULL by caller. |
Definition at line 264 of file ra8_spi_b_target.c.
References internal_spcmd_target(), k_ra8_spfcr_mask_spfrst, k_ra8_spsrc_mask_all, RA8_INTERNAL, r_spi_regs_t::SPCMD, r_spi_regs_t::SPCR2, r_spi_regs_t::SPCR3, r_spi_regs_t::SPDCR, r_spi_regs_t::SPDCR2, r_spi_regs_t::SPDECR, r_spi_regs_t::SPFCR, and r_spi_regs_t::SPSRC.
Referenced by ra8_spi_b_target_init().
|
static |
Build the SPCR value for target (peripheral) mode.
Sets SPE (enable) and MODFEN (mode fault detection) while leaving MSTR=0 (peripheral/target role), SCKASE=0 (controller-only feature), and all interrupt-enable bits clear (polling driver). See HUM Ch 43.2.4 "SPCR : SPI Control Register" p 2884 and HUM Ch 43.3.14 "SPI peripheral-mode operation" p 2912 for the register specification.
| (k_ra8_spcr_mask_spe | | k_ra8_spcr_mask_modfen) The only value ever returned: SPE and MODFEN set; MSTR and all interrupt-enable bits left clear. |
Definition at line 175 of file ra8_spi_b_target.c.
References k_ra8_spcr_mask_modfen, k_ra8_spcr_mask_spe, and RA8_INTERNAL.
Referenced by ra8_spi_b_target_init().
|
static |
Wait for a single SPSR flag to assert, with a bounded poll.
Delegates to ra8_hw_wait_flag_set32, a bounded polling loop (NASA P10 Rule 2) that spins up to k_spi_b_target_poll_limit iterations before returning k_ra8_err_hw_timeout. That loop is consulted by the host-test MMIO fault seam (ra8_fake_mmio_*): a test pre-staging SPSR with the awaited flag succeeds on the first poll (seam transparent), fail_wait drives the timeout leg, and satisfy_after(n) steps the loop's continuation branch for MC/DC. Both the success and timeout legs therefore run on host, rather than being compiled out behind an RA8_OFF_TARGET single-shot short-circuit (T1-01).
| [in] | reg | Pointer to the channel's SPI_B register block. |
| [in] | flag_mask | Single SPSR flag mask (e.g. k_ra8_spsr_mask_sprf). |
| k_ra8_ok | Flag asserted within the poll budget. |
| k_ra8_err_hw_timeout | Flag did not assert within the budget. |
Definition at line 140 of file ra8_spi_b_target.c.
References k_spi_b_target_poll_limit, ra8_hw_wait_flag_set32(), RA8_INTERNAL, and r_spi_regs_t::SPSR.
Referenced by ra8_spi_b_target_xfer().
|
nodiscard |
Initialise an SPI_B channel in target (peripheral) mode.
Configures the SPI_B peripheral to act as a target device: the external controller drives RSPCK and asserts SSL (CS); the MCU responds on CIPO and receives on COPI. Implementation lives in libs/ra8_hal/src/ra8_spi_b_target.c.
Register-level effect (HUM Ch 43.2.4 "SPCR" p 2884):
The baud_hz and pclka_hz fields of cfg are accepted but ignored – the bit-rate is determined by the external controller.
| [in] | channel | SPI channel (0 or 1). |
| [in] | cfg | Configuration descriptor (non-NULL). |
| k_ra8_ok | Channel configured in target mode; awaiting external controller frames. |
| k_ra8_err_null_ptr | cfg is NULL. |
| k_ra8_err_invalid_arg | channel is out of range. |
| k_ra8_err_hw_error | ra8_mstp_enable failed. |
Definition at line 301 of file ra8_spi_b_target.c.
References internal_target_program_regs(), internal_target_spcr(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_spi_b_channel_count, RA8_CHECK_NULL_PTR, ra8_log_info_val, ra8_mstp_enable(), RA8_RETURN_ON_ERROR, ra8_spi(), s_spi_mstp_table, s_tag, and r_spi_regs_t::SPCR.
|
nodiscard |
Exchange one byte as the SPI target in a polled blocking call.
Performs a full-duplex single-byte exchange in target (peripheral) role:
Under RA8_OFF_TARGET the SPSR wait reduces to a single-shot register read: pre-seed the register as shown below.
| [in] | channel | SPI channel (0 or 1). |
| [in] | tx | Byte to send on CIPO (Controller In Peripheral Out). |
| [out] | rx | Pointer to receive the COPI byte; may be NULL if the received byte is not needed. |
| k_ra8_ok | Frame exchange completed. |
| k_ra8_err_null_ptr | channel is out of range (ra8_spi() returned NULL). |
| k_ra8_err_hw_timeout | SPSR.SPTEF or SPSR.SPRF never asserted within k_spi_b_target_poll_limit iterations. |
Definition at line 332 of file ra8_spi_b_target.c.
References internal_target_wait_spsr(), k_ra8_ok, k_ra8_spsr_mask_sprf, k_ra8_spsr_mask_sptef, k_ra8_spsrc_mask_sprfc, k_ra8_spsrc_mask_sptefc, RA8_CHECK_NULL_PTR, ra8_spi(), s_tag, r_spi_regs_t::SPDR, and r_spi_regs_t::SPSRC.
|
static |
Channel-index -> MSTP id (HUM Ch 11.2.7 "MSTPCRB", p 444).
Matches the table in ra8_spi_b.c; this TU manages its own MSTP state rather than calling into the controller driver.
Definition at line 85 of file ra8_spi_b_target.c.
|
static |
Definition at line 68 of file ra8_spi_b_target.c.