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

IIC_B (I3C unified IP) controller driver implementation. More...

#include "ra8_i3c_i2c.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_hw_err.h"
#include "ra8_i3c_i2c_internal.h"
#include "ra8_i3c_i2c_regs.h"
#include "ra8_log.h"
#include "ra8_mstp.h"
Include dependency graph for ra8_i3c_i2c.c:

Go to the source code of this file.

Enumerations

enum  internal_i3c_i2c_t : uint32_t {
  k_ra8_i3c_i2c_poll_limit = 200000U ,
  k_ra8_i3c_i2c_addr_shift = 1U ,
  k_ra8_i3c_i2c_addr_rw_write = 0U ,
  k_ra8_i3c_i2c_addr_rw_read = 1U ,
  k_ra8_i3c_i2c_byte_mask = 0xFFU
}
 Implementation constants – spin budgets, addressing helpers. More...

Functions

bool priv_i3c_i2c_len_buf_invalid (uint32_t len, const void *buf)
 Pure len/buf reject predicate – see header for full contract.
bool priv_i3c_i2c_should_dispatch (uint8_t mask, const void *cb)
 Pure dispatch-callback predicate – see header for full contract.
static uint8_t internal_i3c_i2c_half_period (uint32_t bus_hz, uint32_t pclka_hz)
 Compute STDBR.SBRLO / SBRHO half-period count from PCLKA.
static ra8_err_t internal_i3c_i2c_wait_ntst (volatile r_i3c_i2c_regs_t *reg, uint32_t mask)
 Wait for a flag in NTST to set.
static ra8_err_t internal_i3c_i2c_reset (volatile r_i3c_i2c_regs_t *reg)
 Pulse-reset the I3C peripheral via RSTCTL.RI3CRST.
void priv_i3c_i2c_start (volatile r_i3c_i2c_regs_t *reg)
 Issue a START condition.
static void internal_i3c_i2c_restart (volatile r_i3c_i2c_regs_t *reg)
 Issue a repeated-START (Sr) condition.
void priv_i3c_i2c_stop (volatile r_i3c_i2c_regs_t *reg)
 Issue a STOP condition.
void priv_i3c_i2c_clear_bst (volatile r_i3c_i2c_regs_t *reg)
 Clear all latched bus-status flags ahead of a new transaction.
ra8_err_t priv_i3c_i2c_send_address (volatile r_i3c_i2c_regs_t *reg, uint8_t address_byte)
 Send a single address byte and wait for TDBEF0 to be ready for the next slot.
static ra8_err_t internal_i3c_i2c_status_from_bst (uint32_t bst)
 Map the latched BST error bits to a high-level status code.
static bool internal_i3c_i2c_bus_free (volatile const r_i3c_i2c_regs_t *reg)
 True when the bus is free as reported by BCST.BFREF.
static void internal_i3c_i2c_apply_init_regs (volatile r_i3c_i2c_regs_t *reg, const ra8_i3c_i2c_cfg_t *cfg)
 Apply the post-reset register defaults for an IIC_B channel.
static ra8_err_t internal_i3c_i2c_block_bringup (volatile r_i3c_i2c_regs_t *reg)
 Bring the IIC_B block up: MSTP release, CECTL clock, reset, and switch the I3C IP into I2C single-buffer mode (PRTMD=1).
ra8_err_t ra8_i3c_i2c_init (uint8_t channel, const ra8_i3c_i2c_cfg_t *cfg)
 Initialise the IIC_B channel and bring the bus up.
ra8_err_t ra8_i3c_i2c_deinit (uint8_t channel)
 Tear down the IIC_B channel.
ra8_err_t ra8_i3c_i2c_set_clock (uint8_t channel, uint32_t bus_hz, uint32_t pclka_hz)
 Update the bus clock without tearing the channel down.
static void internal_i3c_i2c_open_phase (volatile r_i3c_i2c_regs_t *reg, bool bus_held)
 Issue START or RESTART based on whether the bus is currently held by a previous restart=true call.
static ra8_err_t internal_i3c_i2c_drain_tx (volatile r_i3c_i2c_regs_t *reg, const uint8_t *data, uint32_t len)
 Push len bytes from data into NTDTBP0.
static void internal_i3c_i2c_finalize (volatile r_i3c_i2c_regs_t *reg, uint8_t channel, ra8_err_t err, bool restart)
 Decide STOP vs hold and update channel state accordingly.
static ra8_err_t internal_i3c_i2c_busy_gate (volatile const r_i3c_i2c_regs_t *reg, bool bus_held)
 Bus-busy gate: rejects new transactions while BCST.BFREF is clear, unless the channel is in a held-bus restart state.
ra8_err_t ra8_i3c_i2c_write (uint8_t channel, uint8_t target_7b, const uint8_t *data, uint32_t len, bool restart)
 Polling write of len bytes to a 7-bit target address.
static ra8_err_t internal_i3c_i2c_drain_rx (volatile r_i3c_i2c_regs_t *reg, uint8_t *out, uint32_t len)
 Drain len bytes from NTDTBP0 into out.
static ra8_err_t internal_i3c_i2c_rx_phase (volatile r_i3c_i2c_regs_t *reg, uint8_t *buf, uint32_t len)
 Run the data phase of an RX transaction (dummy-read + drain).
ra8_err_t ra8_i3c_i2c_read (uint8_t channel, uint8_t target_7b, uint8_t *buf, uint32_t len, bool restart)
 Polling read of len bytes from a 7-bit target.
ra8_err_t ra8_i3c_i2c_transfer (uint8_t channel, uint8_t target_7b, const uint8_t *tx, uint32_t tx_len, uint8_t *rx, uint32_t rx_len)
 Combined write-then-RESTART-then-read in a single bus transaction.

Variables

static const char * s_tag = "IIC_B"
 Log tag for this driver's transaction-engine TU.
ra8_i3c_i2c_state_t s_iic_b_state [k_ra8_i3c_i2c_channel_count]
 Per-channel state table indexed by channel.

Detailed Description

IIC_B (I3C unified IP) controller driver implementation.

Tag
[Ring 3 / HAL] {World: NS}

Polling-mode controller driver for the RA8D2 I3C peripheral operated in I2C compatibility mode (HUM Ch 40 "I3C Bus Interface (I3C)", p 2445-2701); IIC_B is the HUM/FSP name for this mode, not a stale alias. Mirrors the public init / start / write / read / stop flow from FSP's r_iic_b_master (file r_iic_b_master.c) collapsed into synchronous helpers – no DTC fast path, no IBI / HDR support, just enough to exchange bytes with a 7-bit-addressed peripheral.

The state machine implemented here is a synchronous reduction of FSP's interrupt-driven flow:

* Write (restart = false):
*     IDLE --START--> ADDR_TX --TDBEF0--> DATA_TX --STOP--> IDLE
*
* Write (restart = true):
*     IDLE --START--> ADDR_TX --TDBEF0--> DATA_TX --hold--> (caller chains)
*
* Read (restart = false):
*     IDLE --START--> ADDR_TX --RDBFF0--> DATA_RX --NACK on last
*     byte--> STOP --> IDLE
*
* Read (restart = true):
*     IDLE --START--> ADDR_TX --RDBFF0--> DATA_RX --NACK on last
*     byte--> hold --> (caller chains)
*
* Combined transfer:
*     IDLE --START--> ADDR_TX --TDBEF0--> DATA_TX --RESTART-->
*     ADDR_TX(read) --RDBFF0--> DATA_RX --NACK on last byte--> STOP --> IDLE
* 

Owns every write to the I3C register block. See HUM Ch 40 "I3C Bus Interface (I3C)", p 2445-2701.

Definition in file ra8_i3c_i2c.c.

Enumeration Type Documentation

◆ internal_i3c_i2c_t

enum internal_i3c_i2c_t : uint32_t

Implementation constants – spin budgets, addressing helpers.

Enumerator
k_ra8_i3c_i2c_poll_limit 

Generic spin budget for status-flag polls.

~200k iters keeps the worst-case stall under ~5ms at 250MHz with the load/branch pair the compiler emits for the wait helpers.

k_ra8_i3c_i2c_addr_shift 

Shift count to convert a 7-bit address into the on-the-wire byte.

k_ra8_i3c_i2c_addr_rw_write 

R/W bit value for a write transaction (0 in LSB).

k_ra8_i3c_i2c_addr_rw_read 

R/W bit value for a read transaction (1 in LSB).

k_ra8_i3c_i2c_byte_mask 

8-bit byte mask for narrowing 32-bit reads from NTDTBP0.

Definition at line 108 of file ra8_i3c_i2c.c.

Function Documentation

◆ internal_i3c_i2c_apply_init_regs()

void internal_i3c_i2c_apply_init_regs ( volatile r_i3c_i2c_regs_t * reg,
const ra8_i3c_i2c_cfg_t * cfg )
static

Apply the post-reset register defaults for an IIC_B channel.

Mirrors the second half of FSP's controller-open sequence: STDBR / BFCTL / ACKCTL / SCSTRCTL get stamped with the bring-up values, then BCTL.BUSE = 1 attaches the bus pads.

Parameters
[in]regSee header declaration for direction and constraints.
[in]cfgSee header declaration for direction and constraints.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 472 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::ACKCTL, r_i3c_i2c_regs_t::BCTL, r_i3c_i2c_regs_t::BFCTL, ra8_i3c_i2c_cfg_t::bus_hz, internal_i3c_i2c_half_period(), k_ra8_i3c_i2c_msk_ackctl_acktwp, k_ra8_i3c_i2c_msk_bctl_buse, k_ra8_i3c_i2c_msk_bfctl_fmpe, k_ra8_i3c_i2c_msk_bfctl_male, k_ra8_i3c_i2c_msk_bfctl_nale, k_ra8_i3c_i2c_msk_bfctl_scsyne, k_ra8_i3c_i2c_speed_fast_plus, k_ra8_i3c_i2c_stdbr_sbrho_pos, k_ra8_i3c_i2c_stdbr_sbrlo_pos, ra8_i3c_i2c_cfg_t::pclka_hz, RA8_INTERNAL, r_i3c_i2c_regs_t::REFCKCTL, r_i3c_i2c_regs_t::SCSTRCTL, and r_i3c_i2c_regs_t::STDBR.

Referenced by ra8_i3c_i2c_init().

◆ internal_i3c_i2c_block_bringup()

ra8_err_t internal_i3c_i2c_block_bringup ( volatile r_i3c_i2c_regs_t * reg)
static

Bring the IIC_B block up: MSTP release, CECTL clock, reset, and switch the I3C IP into I2C single-buffer mode (PRTMD=1).

Extracted from ra8_i3c_i2c_init to stay under the NASA Rule 4 + clang-tidy readability-function-size thresholds. Step ordering is fixed by HUM Ch 11.2.7 p 444 + Ch 40.2.92 p 2543 + Ch 40.2.1 p 2449: MSTP -> CECTL.CLKE -> BCTL clear -> RSTCTL reset -> PRTS.

Parameters
[in,out]regIIC_B register block (already resolved by the caller from the channel index).
Returns
ra8_err_t outcome of the chain.
Return values
k_ra8_okBlock clocked, reset, PRTMD=1 latched.
otherUnderlying MSTP / reset step failed.
Precondition
reg != nullptr.
Caller has validated the channel index.
Postcondition
On success the IIC_B IP is ready for internal_i3c_i2c_apply_init_regs to programme bus timing.
On error the partial side effects (MSTP enabled, CECTL written) remain – caller treats this as init-failed and does not consume the channel.
Note
Not thread-safe; serialise iic_b bring-up at a higher layer.
Since
0.1.0

Definition at line 530 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::BCTL, r_i3c_i2c_regs_t::CECTL, internal_i3c_i2c_reset(), k_ra8_i3c_i2c_msk_cectl_clke, k_ra8_i3c_i2c_msk_prts_prtmd, k_ra8_mstp_i3c, k_ra8_mstp_iic0, k_ra8_ok, r_i3c_i2c_regs_t::PRTS, RA8_INTERNAL, ra8_mstp_enable(), RA8_RETURN_ON_ERROR, and s_tag.

Referenced by ra8_i3c_i2c_init().

◆ internal_i3c_i2c_bus_free()

bool internal_i3c_i2c_bus_free ( volatile const r_i3c_i2c_regs_t * reg)
static

True when the bus is free as reported by BCST.BFREF.

HUM Ch 40.2.58 "BCST : Bus Condition Status Register" p 2512: BFREF is 1 when the bus is in the free state. FSP gates new controller transactions on this flag (see FSP's controller-run path around its bus-free wait block).

Parameters
[in]regSee header declaration for direction and constraints.
Returns
ra8_err_t error code (or void if the signature returns void).
Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 445 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::BCST, k_ra8_i3c_i2c_msk_bcst_bfref, and RA8_INTERNAL.

Referenced by internal_i3c_i2c_busy_gate().

◆ internal_i3c_i2c_busy_gate()

ra8_err_t internal_i3c_i2c_busy_gate ( volatile const r_i3c_i2c_regs_t * reg,
bool bus_held )
static

Bus-busy gate: rejects new transactions while BCST.BFREF is clear, unless the channel is in a held-bus restart state.

See the matching header declaration for the full contract; this site adds no behaviour beyond what the public API documents.

Parameters
[in]regSee header declaration for direction and constraints.
[in]bus_heldSee header declaration for direction and constraints.
Returns
ra8_err_t error code (or void if the signature returns void).
Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 743 of file ra8_i3c_i2c.c.

References internal_i3c_i2c_bus_free(), k_ra8_err_busy, k_ra8_ok, and RA8_INTERNAL.

Referenced by ra8_i3c_i2c_read(), and ra8_i3c_i2c_write().

◆ internal_i3c_i2c_drain_rx()

ra8_err_t internal_i3c_i2c_drain_rx ( volatile r_i3c_i2c_regs_t * reg,
uint8_t * out,
uint32_t len )
static

Drain len bytes from NTDTBP0 into out.

Helper for ra8_i3c_i2c_read. Mirrors FSP's controller RXI data path: each iteration waits for RDBFF0 then reads NTDTBP0. On the final byte the controller is primed to NACK (via ACKCTL.ACKT paired with ACKTWP) so the peripheral releases SDA when STOP issues.

Parameters
[in]regSee header declaration for direction and constraints.
[in]outSee header declaration for direction and constraints.
[in]lenSee header declaration for direction and constraints.
Returns
ra8_err_t error code (or void if the signature returns void).
Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 817 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::ACKCTL, internal_i3c_i2c_wait_ntst(), k_ra8_i3c_i2c_byte_mask, k_ra8_i3c_i2c_msk_ackctl_ackt, k_ra8_i3c_i2c_msk_ackctl_acktwp, k_ra8_i3c_i2c_msk_ntst_rdbff0, k_ra8_ok, and r_i3c_i2c_regs_t::NTDTBP0.

Referenced by internal_i3c_i2c_rx_phase().

◆ internal_i3c_i2c_drain_tx()

ra8_err_t internal_i3c_i2c_drain_tx ( volatile r_i3c_i2c_regs_t * reg,
const uint8_t * data,
uint32_t len )
static

Push len bytes from data into NTDTBP0.

TX-side counterpart to internal_i3c_i2c_drain_rx. Each iteration waits for TDBEF0 then writes one byte; bails out early on NACK mid-payload (FSP TXI ERI fast-path).

Parameters
[in]regSee header declaration for direction and constraints.
[in]dataSee header declaration for direction and constraints.
[in]lenSee header declaration for direction and constraints.
Returns
ra8_err_t error code (or void if the signature returns void).
Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 674 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::BST, internal_i3c_i2c_wait_ntst(), k_ra8_i3c_i2c_msk_bst_nackdf, k_ra8_i3c_i2c_msk_ntst_tdbef0, k_ra8_ok, and r_i3c_i2c_regs_t::NTDTBP0.

Referenced by ra8_i3c_i2c_write().

◆ internal_i3c_i2c_finalize()

void internal_i3c_i2c_finalize ( volatile r_i3c_i2c_regs_t * reg,
uint8_t channel,
ra8_err_t err,
bool restart )
static

Decide STOP vs hold and update channel state accordingly.

Common tail of write/read: if the data phase failed or the caller did not request restart, issue STOP and clear bus_held. Otherwise leave the bus held for the next chained call.

Parameters
[in]regSee header declaration for direction and constraints.
[in]channelSee header declaration for direction and constraints.
[in]errSee header declaration for direction and constraints.
[in]restartSee header declaration for direction and constraints.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 710 of file ra8_i3c_i2c.c.

References k_ra8_ok, priv_i3c_i2c_clear_bst(), priv_i3c_i2c_stop(), RA8_INTERNAL, and s_iic_b_state.

Referenced by ra8_i3c_i2c_read(), and ra8_i3c_i2c_write().

◆ internal_i3c_i2c_half_period()

uint8_t internal_i3c_i2c_half_period ( uint32_t bus_hz,
uint32_t pclka_hz )
static

Compute STDBR.SBRLO / SBRHO half-period count from PCLKA.

IIC_B clocks SCL by counting reference-clock cycles for the low and high halves of the bit period. With REFCKCTL.IREFCKS = 0 the reference clock is PCLKA. The full bit period is therefore (SBRLO + 1) + (SBRHO + 1) PCLKA cycles. We split it 50/50 so each half is round(pclka_hz / (2 * bus_hz)) - 1.

Result is clamped to 8 bits to fit the SBRLO/SBRHO fields per HUM Ch 40.2.15 "STDBR : Standard Bit Rate Register", p 2463.

Parameters
[in]bus_hzTarget bus clock (non-zero).
[in]pclka_hzPCLKA frequency (non-zero).
Returns
One half-period count, [0, 0xFF].
Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

< RA8 I3C I2C period split.

< RA8 I3C I2C maximum field.

Definition at line 160 of file ra8_i3c_i2c.c.

References RA8_INTERNAL.

Referenced by internal_i3c_i2c_apply_init_regs(), and ra8_i3c_i2c_set_clock().

◆ internal_i3c_i2c_open_phase()

void internal_i3c_i2c_open_phase ( volatile r_i3c_i2c_regs_t * reg,
bool bus_held )
static

Issue START or RESTART based on whether the bus is currently held by a previous restart=true call.

See the matching header declaration for the full contract; this site adds no behaviour beyond what the public API documents.

Parameters
[in]regSee header declaration for direction and constraints.
[in]bus_heldSee header declaration for direction and constraints.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 643 of file ra8_i3c_i2c.c.

References internal_i3c_i2c_restart(), priv_i3c_i2c_start(), and RA8_INTERNAL.

Referenced by ra8_i3c_i2c_read(), and ra8_i3c_i2c_write().

◆ internal_i3c_i2c_reset()

ra8_err_t internal_i3c_i2c_reset ( volatile r_i3c_i2c_regs_t * reg)
static

Pulse-reset the I3C peripheral via RSTCTL.RI3CRST.

On real silicon RSTCTL.RI3CRST self-clears once the internal reset completes. We follow the FSP sequence (write the bit, poll until it clears) but additionally write zero before polling so that the host-mode fake – which has no auto-clear behaviour – exits the loop cleanly. In production the explicit zero-write hits while the hardware is still draining the reset and is harmless.

HUM Ch 40.2.4 "RSTCTL : Reset Control Register" p 2451

Parameters
[in]regSee header declaration for direction and constraints.
Returns
ra8_err_t error code (or void if the signature returns void).
Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 242 of file ra8_i3c_i2c.c.

References k_ra8_err_hw_timeout, k_ra8_i3c_i2c_msk_rstctl_ri3crst, k_ra8_i3c_i2c_poll_limit, k_ra8_ok, RA8_INTERNAL, and r_i3c_i2c_regs_t::RSTCTL.

Referenced by internal_i3c_i2c_block_bringup().

◆ internal_i3c_i2c_restart()

void internal_i3c_i2c_restart ( volatile r_i3c_i2c_regs_t * reg)
static

Issue a repeated-START (Sr) condition.

HUM Ch 40.2.32 "CNDCTL : Condition Control Register" p 2479 – Sr differs from S in that it is gated by the prior transfer not having issued STOP. The polling driver achieves that by leaving STOP off when the caller passes restart=true to write/read.

Parameters
[in]regSee header declaration for direction and constraints.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 300 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::CNDCTL, k_ra8_i3c_i2c_msk_cndctl_srcnd, and RA8_INTERNAL.

Referenced by internal_i3c_i2c_open_phase().

◆ internal_i3c_i2c_rx_phase()

ra8_err_t internal_i3c_i2c_rx_phase ( volatile r_i3c_i2c_regs_t * reg,
uint8_t * buf,
uint32_t len )
static

Run the data phase of an RX transaction (dummy-read + drain).

Mirrors FSP's controller RXI handler: the first RDBFF0 fires before NTDTBP0 holds real payload, so the first read is dropped to clock the first data byte into the buffer. ACKCTL is then restored to its default (ACK every byte) for the next transaction.

Returns
ra8_err_t error code (or void if the signature returns void).
Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0
Parameters
[in]regSee header declaration for direction and constraints.
[in]bufSee header declaration for direction and constraints.
[in]lenSee header declaration for direction and constraints.

Definition at line 863 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::ACKCTL, internal_i3c_i2c_drain_rx(), internal_i3c_i2c_wait_ntst(), k_ra8_i3c_i2c_msk_ackctl_acktwp, k_ra8_i3c_i2c_msk_ntst_rdbff0, k_ra8_ok, and r_i3c_i2c_regs_t::NTDTBP0.

Referenced by ra8_i3c_i2c_read().

◆ internal_i3c_i2c_status_from_bst()

ra8_err_t internal_i3c_i2c_status_from_bst ( uint32_t bst)
static

Map the latched BST error bits to a high-level status code.

NACK and arbitration-loss carry distinct codes so a caller can distinguish "peripheral declined" from "another controller won the bus".

Parameters
[in]bstSee header declaration for direction and constraints.
Returns
ra8_err_t error code (or void if the signature returns void).
Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 411 of file ra8_i3c_i2c.c.

References k_ra8_err_hw_error, k_ra8_err_hw_timeout, k_ra8_err_nack, k_ra8_i3c_i2c_msk_bst_alf, k_ra8_i3c_i2c_msk_bst_nackdf, k_ra8_i3c_i2c_msk_bst_todf, k_ra8_ok, and RA8_INTERNAL.

Referenced by ra8_i3c_i2c_read(), and ra8_i3c_i2c_write().

◆ internal_i3c_i2c_wait_ntst()

ra8_err_t internal_i3c_i2c_wait_ntst ( volatile r_i3c_i2c_regs_t * reg,
uint32_t mask )
static

Wait for a flag in NTST to set.

Parameters
[in]regChannel register block.
[in]maskBit mask to test against NTST.
Returns
k_ra8_ok on flag set, k_ra8_err_hw_timeout otherwise.

See the matching header declaration for the full contract; this site adds no behaviour beyond what the public API documents.

Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 201 of file ra8_i3c_i2c.c.

References k_ra8_err_hw_timeout, k_ra8_i3c_i2c_poll_limit, k_ra8_ok, r_i3c_i2c_regs_t::NTST, and RA8_INTERNAL.

Referenced by internal_i3c_i2c_drain_rx(), internal_i3c_i2c_drain_tx(), internal_i3c_i2c_rx_phase(), and priv_i3c_i2c_send_address().

◆ priv_i3c_i2c_clear_bst()

void priv_i3c_i2c_clear_bst ( volatile r_i3c_i2c_regs_t * reg)

Clear all latched bus-status flags ahead of a new transaction.

See the matching header declaration for the full contract; this site adds no behaviour beyond what the public API documents.

Parameters
[in]regSee header declaration for direction and constraints.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

< RA8 I3C I2C bst clear mask.

Definition at line 347 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::BST, k_ra8_i3c_i2c_msk_bst_alf, k_ra8_i3c_i2c_msk_bst_nackdf, k_ra8_i3c_i2c_msk_bst_spcnddf, k_ra8_i3c_i2c_msk_bst_stcnddf, k_ra8_i3c_i2c_msk_bst_tendf, and k_ra8_i3c_i2c_msk_bst_todf.

Referenced by internal_i3c_i2c_finalize(), ra8_i3c_i2c_abort(), ra8_i3c_i2c_read(), ra8_i3c_i2c_scan(), and ra8_i3c_i2c_write().

◆ priv_i3c_i2c_len_buf_invalid()

bool priv_i3c_i2c_len_buf_invalid ( uint32_t len,
const void * buf )

Pure len/buf reject predicate – see header for full contract.

Pure predicate: non-zero length AND a NULL buffer pointer.

Promoted helper so the line-976 AND can be driven under MC/DC.

Parameters
[in]lenLength in bytes.
[in]bufBuffer pointer.
Returns
Boolean reject predicate.
Return values
trueCaller returns null-ptr error.
falseCombination is OK.
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 76 of file ra8_i3c_i2c.c.

Referenced by ra8_i3c_i2c_transfer().

◆ priv_i3c_i2c_send_address()

ra8_err_t priv_i3c_i2c_send_address ( volatile r_i3c_i2c_regs_t * reg,
uint8_t address_byte )

Send a single address byte and wait for TDBEF0 to be ready for the next slot.

Send a single address byte and wait for TDBEF0 readiness.

Parameters
[in]regChannel registers.
[in]address_bytePre-shifted address with R/W bit.
Returns
ra8_err_t – forwards timeout / NACK detection.

See the matching header declaration for the full contract; this site adds no behaviour beyond what the public API documents.

Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 380 of file ra8_i3c_i2c.c.

References internal_i3c_i2c_wait_ntst(), k_ra8_i3c_i2c_msk_ntst_tdbef0, k_ra8_ok, and r_i3c_i2c_regs_t::NTDTBP0.

Referenced by ra8_i3c_i2c_read(), ra8_i3c_i2c_scan(), and ra8_i3c_i2c_write().

◆ priv_i3c_i2c_should_dispatch()

bool priv_i3c_i2c_should_dispatch ( uint8_t mask,
const void * cb )

Pure dispatch-callback predicate – see header for full contract.

Pure predicate: non-zero error mask AND a non-NULL callback.

Promoted helper so the line-1235 AND can be driven under MC/DC.

Parameters
[in]maskBitmask of pending error sources.
[in]cbCallback pointer.
Returns
Boolean predicate.
Return values
trueCaller invokes cb.
falseSkip callback.
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 96 of file ra8_i3c_i2c.c.

Referenced by ra8_i3c_i2c_dispatch_eri().

◆ priv_i3c_i2c_start()

void priv_i3c_i2c_start ( volatile r_i3c_i2c_regs_t * reg)

Issue a START condition.

Issue a START condition on the given channel registers.

See the matching header declaration for the full contract; this site adds no behaviour beyond what the public API documents.

Parameters
[in]regSee header declaration for direction and constraints.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 277 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::CNDCTL, and k_ra8_i3c_i2c_msk_cndctl_stcnd.

Referenced by internal_i3c_i2c_open_phase(), and ra8_i3c_i2c_scan().

◆ priv_i3c_i2c_stop()

void priv_i3c_i2c_stop ( volatile r_i3c_i2c_regs_t * reg)

Issue a STOP condition.

Issue a STOP condition and clear the prior STOP-detect flag.

Mirrors FSP's stop-on-completion path (its RXI read + TEI end handlers). SPCNDDF is left for the ERI dispatcher to observe; the polling helpers don't gate on it because the synchronous flow is already past the data phase by the time we get here.

HUM Ch 40.2.32 "CNDCTL : Condition Control Register" p 2479

Parameters
[in]regSee header declaration for direction and constraints.
Precondition
Driver state has been initialized by the matching *_init.
Caller has validated all pointer parameters.
Postcondition
Side effects are limited to those documented in the header.
No global state is modified on the error path.
Note
Thread safety: see the header declaration.
Since
0.1.0

Definition at line 325 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::BST, r_i3c_i2c_regs_t::CNDCTL, k_ra8_i3c_i2c_msk_bst_spcnddf, and k_ra8_i3c_i2c_msk_cndctl_spcnd.

Referenced by internal_i3c_i2c_finalize(), ra8_i3c_i2c_abort(), ra8_i3c_i2c_read(), ra8_i3c_i2c_scan(), and ra8_i3c_i2c_write().

◆ ra8_i3c_i2c_deinit()

ra8_err_t ra8_i3c_i2c_deinit ( uint8_t channel)
nodiscard

Tear down the IIC_B channel.

Parameters
[in]channelChannel index.
Returns
ra8_err_t.
Return values
k_ra8_okChannel torn down, MSTP gated.
k_ra8_err_invalid_argchannel out of range.
Precondition
Caller is not in the middle of a transfer.
Postcondition
BCTL.BUSE cleared and I3C MSTP bit ref-released.
Since
0.1.0

Definition at line 588 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::BCTL, r_i3c_i2c_regs_t::CECTL, i3c_i2c_regs(), k_ra8_err_invalid_arg, k_ra8_mstp_i3c, ra8_mstp_disable(), and s_iic_b_state.

Referenced by ra8_i3c_deinit().

◆ ra8_i3c_i2c_init()

ra8_err_t ra8_i3c_i2c_init ( uint8_t channel,
const ra8_i3c_i2c_cfg_t * cfg )
nodiscard

Initialise the IIC_B channel and bring the bus up.

Parameters
[in]channelChannel index (only 0 is valid on RA8D2).
[in]cfgConfiguration descriptor.
Returns
ra8_err_t.
Return values
k_ra8_okChannel initialized, BCTL.BUSE = 1.
k_ra8_err_null_ptrcfg is NULL.
k_ra8_err_invalid_argchannel out of range or cfg->bus_hz zero.
k_ra8_err_hw_timeoutRSTCTL.RI3CRST didn't self-clear.
Precondition
IRQs masked or single-threaded init context.
ra8_mstp_init has been called.
Postcondition
On success BCTL.BUSE is set and the channel is ready to service ra8_i3c_i2c_write / ra8_i3c_i2c_read.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 563 of file ra8_i3c_i2c.c.

References ra8_i3c_i2c_cfg_t::bus_hz, i3c_i2c_regs(), internal_i3c_i2c_apply_init_regs(), internal_i3c_i2c_block_bringup(), k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_info_val, RA8_RETURN_ON_ERROR, s_iic_b_state, and s_tag.

Referenced by ra8_i3c_init().

◆ ra8_i3c_i2c_read()

ra8_err_t ra8_i3c_i2c_read ( uint8_t channel,
uint8_t target_7b,
uint8_t * buf,
uint32_t len,
bool restart )
nodiscard

Polling read of len bytes from a 7-bit target.

Mirrors FSP's R_IIC_B_MASTER_Read minus DTC:

  1. Reject the call if the bus is busy (BCST.BFREF == 0) AND no repeated-START is in progress (i.e. caller did not hold the bus via a prior ra8_i3c_i2c_write(..., restart=true)).
  2. Issue a START (or RESTART when the bus is already held).
  3. Send (target_7b << 1) | 1 as the address byte.
  4. Drain len bytes from NTDTBP0; ACK every byte except the last, which is NACKed via ACKCTL.ACKT (paired with ACKTWP).
  5. Issue a STOP unless restart == true.

State machine: IDLE -> ADDR_TX -> DATA_RX -> { STOP | hold for RESTART } -> IDLE.

Parameters
[in]channelChannel index.
[in]target_7b7-bit peripheral address.
[out]bufDestination buffer (non-NULL).
[in]lenByte count (non-zero).
[in]restartWhen true, suppress the trailing STOP.
Returns
ra8_err_t.
Return values
k_ra8_okTransfer succeeded.
k_ra8_err_null_ptrbuf is NULL or channel invalid.
k_ra8_err_invalid_arglen is zero.
k_ra8_err_busyBus busy at entry.
k_ra8_err_hw_timeoutRDBFF0 / TENDF poll timed out.
k_ra8_err_nackPeripheral NACKed the address byte.
k_ra8_err_hw_errorArbitration lost.
Precondition
Channel previously initialized.
Postcondition
BST status flags cleared.
Since
0.1.0

Definition at line 875 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::BST, i3c_i2c_regs(), internal_i3c_i2c_busy_gate(), internal_i3c_i2c_finalize(), internal_i3c_i2c_open_phase(), internal_i3c_i2c_rx_phase(), internal_i3c_i2c_status_from_bst(), k_ra8_err_invalid_arg, k_ra8_i3c_i2c_addr_rw_read, k_ra8_i3c_i2c_addr_shift, k_ra8_ok, priv_i3c_i2c_clear_bst(), priv_i3c_i2c_send_address(), priv_i3c_i2c_stop(), RA8_CHECK_NULL_PTR, s_iic_b_state, and s_tag.

Referenced by ra8_i3c_i2c_transfer(), and ra8_i3c_read().

◆ ra8_i3c_i2c_set_clock()

ra8_err_t ra8_i3c_i2c_set_clock ( uint8_t channel,
uint32_t bus_hz,
uint32_t pclka_hz )
nodiscard

Update the bus clock without tearing the channel down.

Parameters
[in]channelChannel index.
[in]bus_hzNew bus clock in Hz (non-zero).
[in]pclka_hzCurrent PCLKA frequency in Hz.
Returns
ra8_err_t.
Return values
k_ra8_okSTDBR programmed.
k_ra8_err_invalid_argChannel / clock out of range.
Precondition
Channel previously initialized.
Postcondition
STDBR.SBRLO / SBRHO reflect the new divider.
Since
0.1.0

Definition at line 606 of file ra8_i3c_i2c.c.

References i3c_i2c_regs(), internal_i3c_i2c_half_period(), k_ra8_err_invalid_arg, k_ra8_i3c_i2c_stdbr_sbrho_pos, k_ra8_i3c_i2c_stdbr_sbrlo_pos, k_ra8_ok, and r_i3c_i2c_regs_t::STDBR.

Referenced by ra8_i3c_set_clock().

◆ ra8_i3c_i2c_transfer()

ra8_err_t ra8_i3c_i2c_transfer ( uint8_t channel,
uint8_t target_7b,
const uint8_t * tx,
uint32_t tx_len,
uint8_t * rx,
uint32_t rx_len )
nodiscard

Combined write-then-RESTART-then-read in a single bus transaction.

Convenience wrapper for the most common I2C pattern: write a register address, then read its contents back from the same target. Internally invokes ra8_i3c_i2c_write(..., restart=true) followed by ra8_i3c_i2c_read(..., restart=false). State machine:

IDLE -> ADDR_TX -> DATA_TX -> RESTART -> ADDR_TX(read) -> DATA_RX -> STOP -> IDLE

If either tx_len or rx_len is zero the corresponding phase is skipped (e.g. tx_len = 0 degenerates to a plain read).

Parameters
[in]channelChannel index.
[in]target_7b7-bit peripheral address.
[in]txBytes to send first (e.g. register address). May be NULL only when tx_len == 0.
[in]tx_lenNumber of bytes to send.
[out]rxDestination buffer for the read phase. May be NULL only when rx_len == 0.
[in]rx_lenNumber of bytes to read.
Returns
ra8_err_t.
Return values
k_ra8_okTransfer succeeded; STOP issued.
k_ra8_err_null_ptrtx/rx NULL with non-zero len, or channel invalid.
k_ra8_err_invalid_argBoth tx_len and rx_len are zero.
k_ra8_err_busyBus busy at entry.
k_ra8_err_nackPeripheral NACKed.
k_ra8_err_hw_timeoutPoll timed out.
Precondition
Channel previously initialized.
Postcondition
Bus is released regardless of outcome.
Since
0.1.0

Definition at line 916 of file ra8_i3c_i2c.c.

References i3c_i2c_regs(), k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, priv_i3c_i2c_len_buf_invalid(), ra8_i3c_i2c_read(), and ra8_i3c_i2c_write().

Referenced by ra8_i3c_transfer().

◆ ra8_i3c_i2c_write()

ra8_err_t ra8_i3c_i2c_write ( uint8_t channel,
uint8_t target_7b,
const uint8_t * data,
uint32_t len,
bool restart )
nodiscard

Polling write of len bytes to a 7-bit target address.

Mirrors FSP's R_IIC_B_MASTER_Write flow without the DTC fast path:

  1. Reject the call if the bus is busy (BCST.BFREF == 0).
  2. Issue a START condition.
  3. Send (target_7b << 1) | 0 as the address byte.
  4. Push each payload byte into NTDTBP0 once NTST.TDBEF0 sets.
  5. If restart == false issue a STOP; otherwise leave the bus held and return – the caller is expected to follow this call immediately with another ra8_i3c_i2c_write / ra8_i3c_i2c_read that will inject a repeated-START rather than a fresh START.

State machine: IDLE -> ADDR_TX -> DATA_TX -> { STOP | hold for RESTART } -> IDLE.

On NACK or arbitration loss the transaction is aborted (STOP issued unconditionally) and the matching error code is returned.

Parameters
[in]channelChannel index.
[in]target_7b7-bit peripheral address.
[in]dataBuffer to send (must be non-NULL even when len is zero).
[in]lenByte count.
[in]restartWhen true, suppress the trailing STOP and keep the bus held so the next call (typically a read) issues a repeated-START. When false, STOP is issued and the bus is released.
Returns
ra8_err_t.
Return values
k_ra8_okTransfer succeeded.
k_ra8_err_null_ptrdata is NULL or channel invalid.
k_ra8_err_busyBus busy at entry (BCST.BFREF clear).
k_ra8_err_hw_timeoutTDBEF0 / TENDF poll timed out.
k_ra8_err_nackPeripheral NACKed; STOP was issued.
k_ra8_err_hw_errorArbitration lost; STOP was issued.
Precondition
Channel previously initialized.
Postcondition
On k_ra8_ok and restart == false: STOP issued, bus free.
On k_ra8_ok and restart == true: bus held by controller; next call must be on the same channel/target.
Since
0.1.0

Definition at line 752 of file ra8_i3c_i2c.c.

References r_i3c_i2c_regs_t::BST, i3c_i2c_regs(), internal_i3c_i2c_busy_gate(), internal_i3c_i2c_drain_tx(), internal_i3c_i2c_finalize(), internal_i3c_i2c_open_phase(), internal_i3c_i2c_status_from_bst(), k_ra8_i3c_i2c_addr_rw_write, k_ra8_i3c_i2c_addr_shift, k_ra8_ok, priv_i3c_i2c_clear_bst(), priv_i3c_i2c_send_address(), priv_i3c_i2c_stop(), RA8_CHECK_NULL_PTR, s_iic_b_state, and s_tag.

Referenced by ra8_i3c_i2c_transfer(), and ra8_i3c_write().

Variable Documentation

◆ s_iic_b_state

Per-channel state table indexed by channel.

The ra8_i3c_i2c_state_t type and the matching extern declaration live in ra8_i3c_i2c_internal.h so the control-plane TU (ra8_i3c_i2c_control.c) can share this single definition.

Defined in ra8_i3c_i2c.c; the control-plane TU (abort / scan / attach_handler / dispatch_eri) reads and updates the held-bus and callback fields through this extern declaration.

Note
Not thread-safe; serialise channel access at a higher layer.
Warning
Owned by ra8_i3c_i2c.c; do not define elsewhere.
Since
0.1.0

Definition at line 132 of file ra8_i3c_i2c.c.

Referenced by internal_i3c_i2c_finalize(), ra8_i3c_i2c_abort(), ra8_i3c_i2c_attach_handler(), ra8_i3c_i2c_deinit(), ra8_i3c_i2c_dispatch_eri(), ra8_i3c_i2c_init(), ra8_i3c_i2c_read(), and ra8_i3c_i2c_write().

◆ s_tag

const char* s_tag = "IIC_B"
static

Log tag for this driver's transaction-engine TU.

Definition at line 102 of file ra8_i3c_i2c.c.