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

I2C Bus Interface (IIC) controller driver implementation. More...

#include "ra8_i2c.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_hw_err.h"
#include "ra8_i2c_internal.h"
#include "ra8_i2c_regs.h"
Include dependency graph for ra8_i2c.c:

Go to the source code of this file.

Enumerations

enum  ra8_i2c_internal_t : uint32_t {
  k_ra8_i2c_poll_limit = 200000U ,
  k_ra8_i2c_addr_shift = 1U ,
  k_ra8_i2c_addr_rw_write = 0U ,
  k_ra8_i2c_addr_rw_read = 1U
}
 Implementation constants – spin budgets and addressing helpers. More...
enum  ra8_i2c_rx_phase_t : uint32_t {
  k_ra8_i2c_rx_short_len = 2U ,
  k_ra8_i2c_rx_single_len = 1U ,
  k_ra8_i2c_rx_remain_wait = 3U ,
  k_ra8_i2c_rx_remain_nack = 2U ,
  k_ra8_i2c_rx_remain_stop = 1U
}
 Controller-receive end-of-frame boundaries (HUM Ch 39.3.4 p 2400). More...

Functions

bool priv_ra8_i2c_internal_clk_invalid (uint32_t bus_hz, uint32_t pclkb_hz)
 Pure predicate: either clock argument is zero.
static ra8_err_t internal_i2c_wait_icsr2 (volatile const r_i2c_regs_t *reg, uint8_t mask)
 Wait for a flag in ICSR2 to set, with a bounded spin budget.
static ra8_err_t internal_i2c_status_from_icsr2 (uint8_t icsr2)
 Map latched ICSR2 error bits to a high-level status code.
static void internal_i2c_clear_status (volatile r_i2c_regs_t *reg)
 Clear the START / STOP / NACK status flags ahead of a transfer.
static void internal_i2c_start (volatile r_i2c_regs_t *reg)
 Issue a START condition (HUM Ch 39.3.3 step 2 p 2396).
static void internal_i2c_restart (volatile r_i2c_regs_t *reg)
 Issue a repeated-START condition (HUM Ch 39.11 p 2434).
static void internal_i2c_wait_bus_free (volatile const r_i2c_regs_t *reg)
 Spin (bounded) until the bus is free (ICCR2.BBSY clears).
static void internal_i2c_stop_request (volatile r_i2c_regs_t *reg)
 Request a STOP condition without waiting for it to complete.
static void internal_i2c_stop (volatile r_i2c_regs_t *reg)
 Issue a STOP condition and wait for the bus to be released.
static void internal_i2c_set_nack (volatile r_i2c_regs_t *reg)
 Set ICMR3.ACKBT (transmit NACK) under ACKWP write-enable.
static void internal_i2c_open_phase (volatile r_i2c_regs_t *reg, bool bus_held)
 Issue START or RESTART based on whether the bus is held.
static ra8_err_t internal_i2c_busy_gate (volatile const r_i2c_regs_t *reg, bool bus_held)
 Bus-busy gate: reject a fresh transaction while BBSY is set, unless the channel currently holds the bus for a restart.
static ra8_err_t internal_i2c_send_address (volatile r_i2c_regs_t *reg, uint8_t address_byte)
 Transmit one address byte (HUM Ch 39.3.3 step 3 p 2396).
static ra8_err_t internal_i2c_drain_tx (volatile r_i2c_regs_t *reg, const uint8_t *data, uint32_t len)
 Push len bytes from data into ICDRT.
static ra8_err_t internal_i2c_finish_tx (volatile r_i2c_regs_t *reg, uint8_t channel, ra8_err_t err, bool send_stop)
 Finish a write: wait for TEND, then STOP or hold the bus.
ra8_err_t ra8_i2c_write (uint8_t channel, uint8_t peripheral_7b, const uint8_t *data, uint32_t len, bool send_stop)
 Polling write of len bytes to a 7-bit peripheral address.
static ra8_err_t internal_i2c_drain_rx (volatile r_i2c_regs_t *reg, uint8_t *out, uint32_t len)
 Drain len bytes from ICDRR into out (controller receive).
ra8_err_t ra8_i2c_read (uint8_t channel, uint8_t peripheral_7b, uint8_t *data, uint32_t len)
 Polling read of len bytes from a 7-bit peripheral.
ra8_err_t ra8_i2c_transfer (uint8_t channel, uint8_t peripheral_7b, const uint8_t *wr, uint32_t wr_len, uint8_t *rd, uint32_t rd_len)
 Combined write-then-RESTART-then-read in one bus transaction.
ra8_err_t ra8_i2c_scan (uint8_t channel, uint8_t peripheral_7b, bool *out_acked)
 Probe whether a 7-bit peripheral address ACKs.

Variables

const char *const g_i2c_tag = "I2C"
 Log tag for this driver, shared with ra8_i2c_config.c.
ra8_i2c_state_t s_i2c_state [k_ra8_i2c_channel_count]
 Per-channel state table indexed by channel.

Detailed Description

I2C Bus Interface (IIC) controller driver implementation.

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

Polling-mode controller driver for the RA8D2 RIIC peripheral (channels IIC0/IIC1/IIC2). Mirrors the public init / start / write / read / stop flow from FSP r_iic_master and HUM Ch 39.3 "Operation" (p 2394-2410) collapsed into synchronous helpers – no DTC fast path, no interrupt path, no peripheral (responder) mode.

The state machine implemented here is a synchronous reduction of the interrupt-driven flow described in HUM Ch 39.3.3 / 39.3.4:

* Write (send_stop = true):
*     IDLE --START--> ADDR_TX --TDRE--> DATA_TX --TEND--STOP--> IDLE
*
* Write (send_stop = false):
*     IDLE --START--> ADDR_TX --TDRE--> DATA_TX --TEND--hold--> (chain)
*
* Read:
*     IDLE --START--> ADDR_TX(R) --RDRF--> DATA_RX --NACK last byte-->
*     STOP --> IDLE
*
* Combined transfer:
*     IDLE --START--> ADDR_TX --DATA_TX--RESTART--> ADDR_TX(R) -->
*     DATA_RX --NACK last byte--> STOP --> IDLE
* 

Owns every write to the RIIC register block. See HUM Ch 39 "I2C Bus Interface (IIC)", p 2367-2470.

Since
0.1.0

Definition in file ra8_i2c.c.

Enumeration Type Documentation

◆ ra8_i2c_internal_t

enum ra8_i2c_internal_t : uint32_t

Implementation constants – spin budgets and addressing helpers.

Enumerator
k_ra8_i2c_poll_limit 

Generic spin budget for status-flag polls.

~200k iterations keeps the worst-case stall under a few ms at the slowest PCLKB.

k_ra8_i2c_addr_shift 

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

k_ra8_i2c_addr_rw_write 

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

k_ra8_i2c_addr_rw_read 

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

Definition at line 71 of file ra8_i2c.c.

◆ ra8_i2c_rx_phase_t

enum ra8_i2c_rx_phase_t : uint32_t

Controller-receive end-of-frame boundaries (HUM Ch 39.3.4 p 2400).

Drive the WAIT / NACK / STOP arming as the byte countdown approaches the final byte, mirroring the FSP r_iic_master RXI handler.

Enumerator
k_ra8_i2c_rx_short_len 

len <= this: arm WAIT in the dummy phase.

k_ra8_i2c_rx_single_len 

len == this: NACK in the dummy phase.

k_ra8_i2c_rx_remain_wait 

bytes-remaining == this: arm WAIT.

k_ra8_i2c_rx_remain_nack 

bytes-remaining == this: NACK final byte.

k_ra8_i2c_rx_remain_stop 

bytes-remaining == this: request STOP.

Definition at line 90 of file ra8_i2c.c.

Function Documentation

◆ internal_i2c_busy_gate()

ra8_err_t internal_i2c_busy_gate ( volatile const r_i2c_regs_t * reg,
bool bus_held )
static

Bus-busy gate: reject a fresh transaction while BBSY is set, unless the channel currently holds the bus for a restart.

A held bus (mid-RESTART) always proceeds; otherwise the gate reads ICCR2.BBSY and accepts only when the bus is free.

Parameters
[in]regChannel register block.
[in]bus_heldTrue when a prior call left the bus held.
Returns
k_ra8_ok when a transaction may proceed, else k_ra8_err_busy.
Return values
k_ra8_okBus is held or free.
k_ra8_err_busyBus is busy and not held by this controller.
Precondition
reg is non-NULL.
Channel previously initialized.
Postcondition
No register write occurs.
No driver state is mutated.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 448 of file ra8_i2c.c.

References r_i2c_regs_t::ICCR2, k_ra8_err_busy, k_ra8_i2c_msk_iccr2_bbsy, k_ra8_ok, and RA8_INTERNAL.

Referenced by ra8_i2c_read(), ra8_i2c_scan(), and ra8_i2c_write().

◆ internal_i2c_clear_status()

void internal_i2c_clear_status ( volatile r_i2c_regs_t * reg)
static

Clear the START / STOP / NACK status flags ahead of a transfer.

Writes 0 to the W0C condition-detect and fault flags (START, STOP, NACKF, AL) so the next transaction observes fresh edges. TDRE / TEND / RDRF are left untouched.

Parameters
[in]regChannel register block.
Precondition
reg is non-NULL.
Channel previously initialized.
Postcondition
ICSR2.START / STOP / NACKF / AL read back zero.
ICSR2.TDRE / TEND / RDRF are preserved.
Note
Thread safety: not thread-safe.
Since
0.1.0

< RA8 I2C status clear mask.

Definition at line 222 of file ra8_i2c.c.

References r_i2c_regs_t::ICSR2, k_ra8_i2c_icsr2_start_pos, k_ra8_i2c_msk_icsr2_al, k_ra8_i2c_msk_icsr2_nackf, k_ra8_i2c_msk_icsr2_stop, and RA8_INTERNAL.

Referenced by internal_i2c_finish_tx(), ra8_i2c_read(), ra8_i2c_scan(), and ra8_i2c_write().

◆ internal_i2c_drain_rx()

ra8_err_t internal_i2c_drain_rx ( volatile r_i2c_regs_t * reg,
uint8_t * out,
uint32_t len )
static

Drain len bytes from ICDRR into out (controller receive).

Mirrors the FSP r_iic_master RXI sequence / HUM Ch 39.3.4 p 2400. After the address-phase RDRF, WAIT (for 1-2 byte reads) and NACK (for a 1-byte read) are armed before the dummy ICDRR read that starts the data clock. Per received byte, the end-of-frame controls are armed by the bytes-remaining countdown: WAIT at remain==3, NACK at remain==2, and a STOP request at remain==1. The STOP must be a request only – it physically fires after the final ICDRR read and the WAIT clear, so waiting for BBSY before reading the last byte would deadlock.

Parameters
[in]regChannel register block.
[out]outDestination buffer.
[in]lenByte count (non-zero).
Returns
k_ra8_ok once all bytes drained, else timeout status.
Return values
k_ra8_okAll bytes drained and STOP completed.
k_ra8_err_hw_timeoutRDRF never set within the spin budget.
Precondition
reg and out are non-NULL and len is non-zero.
The read address byte was acknowledged.
Postcondition
STOP has fired, the bus is free, and ICMR3 WAIT/ACKBT are clear.
ICMR3.WAIT and ICMR3.ACKBT read back zero for the next transfer.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 640 of file ra8_i2c.c.

References r_i2c_regs_t::ICDRR, r_i2c_regs_t::ICMR3, internal_i2c_set_nack(), internal_i2c_stop_request(), internal_i2c_wait_bus_free(), internal_i2c_wait_icsr2(), k_ra8_i2c_msk_icmr3_ackbt, k_ra8_i2c_msk_icmr3_wait, k_ra8_i2c_msk_icsr2_rdrf, k_ra8_i2c_rx_remain_nack, k_ra8_i2c_rx_remain_stop, k_ra8_i2c_rx_remain_wait, k_ra8_i2c_rx_short_len, k_ra8_i2c_rx_single_len, and k_ra8_ok.

Referenced by ra8_i2c_read().

◆ internal_i2c_drain_tx()

ra8_err_t internal_i2c_drain_tx ( volatile r_i2c_regs_t * reg,
const uint8_t * data,
uint32_t len )
static

Push len bytes from data into ICDRT.

Each iteration waits for ICSR2.TDRE, bails on NACK, then writes one byte. Mirrors HUM Ch 39.3.3 step 4 p 2396.

Parameters
[in]regChannel register block.
[in]dataSend buffer.
[in]lenByte count.
Returns
k_ra8_ok once every byte is queued, else timeout / NACK.
Return values
k_ra8_okAll bytes queued.
k_ra8_err_hw_timeoutTDRE never re-armed within the spin budget.
k_ra8_err_nackICSR2.NACKF latched mid-payload.
Precondition
reg and data are non-NULL.
The address byte was already acknowledged.
Postcondition
Either all bytes were queued or an error path stopped early.
No STOP is issued by this helper.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 518 of file ra8_i2c.c.

References r_i2c_regs_t::ICDRT, r_i2c_regs_t::ICSR2, internal_i2c_wait_icsr2(), k_ra8_err_nack, k_ra8_i2c_msk_icsr2_nackf, k_ra8_i2c_msk_icsr2_tdre, and k_ra8_ok.

Referenced by ra8_i2c_write().

◆ internal_i2c_finish_tx()

ra8_err_t internal_i2c_finish_tx ( volatile r_i2c_regs_t * reg,
uint8_t channel,
ra8_err_t err,
bool send_stop )
static

Finish a write: wait for TEND, then STOP or hold the bus.

On a clean data phase the helper waits for ICSR2.TEND, then either issues STOP and clears bus_held (send_stop or any error) or records bus_held so a chained call injects a RESTART.

Parameters
[in]regChannel register block.
[in]channelChannel index.
[in]errResult of the data phase.
[in]send_stopTrue to issue STOP, false to hold for a restart.
Returns
The propagated err (TEND timeout overrides k_ra8_ok).
Return values
k_ra8_okData phase + TEND succeeded.
k_ra8_err_hw_timeoutTEND never set within the spin budget.
otherThe incoming data-phase err is propagated.
Precondition
reg is non-NULL and channel is in range.
The data phase has completed (success or fault).
Postcondition
On STOP the bus is released; otherwise bus_held is recorded.
s_i2c_state[channel].bus_held reflects the new bus ownership.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 562 of file ra8_i2c.c.

References internal_i2c_clear_status(), internal_i2c_stop(), internal_i2c_wait_icsr2(), k_ra8_i2c_msk_icsr2_tend, k_ra8_ok, and s_i2c_state.

Referenced by ra8_i2c_write().

◆ internal_i2c_open_phase()

void internal_i2c_open_phase ( volatile r_i2c_regs_t * reg,
bool bus_held )
static

Issue START or RESTART based on whether the bus is held.

Dispatches to internal_i2c_restart when the channel already holds the bus from a prior send_stop = false write, otherwise issues a fresh START.

Parameters
[in]regChannel register block.
[in]bus_heldTrue to inject a repeated-START.
Precondition
reg is non-NULL.
Channel previously initialized.
Postcondition
Exactly one of ICCR2.ST / ICCR2.RS is requested.
No data register is touched.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 417 of file ra8_i2c.c.

References internal_i2c_restart(), internal_i2c_start(), and RA8_INTERNAL.

Referenced by ra8_i2c_read(), and ra8_i2c_write().

◆ internal_i2c_restart()

void internal_i2c_restart ( volatile r_i2c_regs_t * reg)
static

Issue a repeated-START condition (HUM Ch 39.11 p 2434).

Sets ICCR2.RS; the hardware issues the restart while BBSY = 1 and MST = 1, keeping the bus held without an intervening STOP.

Parameters
[in]regChannel register block.
Precondition
reg is non-NULL and the bus is held by this controller.
Channel previously initialized.
Postcondition
ICCR2.RS is set; hardware issues a restart on the held bus.
No other register is modified.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 272 of file ra8_i2c.c.

References r_i2c_regs_t::ICCR2, k_ra8_i2c_msk_iccr2_rs, k_ra8_i2c_poll_limit, and RA8_INTERNAL.

Referenced by internal_i2c_open_phase().

◆ internal_i2c_send_address()

ra8_err_t internal_i2c_send_address ( volatile r_i2c_regs_t * reg,
uint8_t address_byte )
static

Transmit one address byte (HUM Ch 39.3.3 step 3 p 2396).

Waits for ICSR2.TDRE, writes the pre-shifted address byte to ICDRT, then maps the freshly latched ICSR2 status so an immediate address-phase NACK is reported.

Parameters
[in]regChannel register block.
[in]address_bytePre-shifted 7-bit address with R/W bit.
Returns
k_ra8_ok once TDRE re-arms, else timeout / NACK status.
Return values
k_ra8_okAddress queued, no fault latched.
k_ra8_err_hw_timeoutTDRE never set within the spin budget.
k_ra8_err_nackICSR2.NACKF latched after the write.
k_ra8_err_hw_errorICSR2.AL latched (arbitration lost).
Precondition
reg is non-NULL.
A START / RESTART was issued before this call.
Postcondition
The address byte was written to ICDRT.
On NACK the latched ICSR2.NACKF is reflected in the return.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 481 of file ra8_i2c.c.

References r_i2c_regs_t::ICDRT, r_i2c_regs_t::ICSR2, internal_i2c_status_from_icsr2(), internal_i2c_wait_icsr2(), k_ra8_i2c_msk_icsr2_tdre, k_ra8_ok, and RA8_INTERNAL.

Referenced by ra8_i2c_read(), ra8_i2c_scan(), and ra8_i2c_write().

◆ internal_i2c_set_nack()

void internal_i2c_set_nack ( volatile r_i2c_regs_t * reg)
static

Set ICMR3.ACKBT (transmit NACK) under ACKWP write-enable.

ACKBT is write-protected by ACKWP; per HUM Ch 39.2.5 Note 1 the write-enable, the ACKBT set, and the write-disable must be separate register writes. Used by the receive path to NACK the final byte so the peripheral stops driving the bus.

Parameters
[in]regChannel register block.
Precondition
reg is non-NULL.
The controller is in controller-receive.
Postcondition
ICMR3.ACKBT is set; ACKWP is left clear (write-protected again).
The next received byte will be answered with a NACK.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 391 of file ra8_i2c.c.

References r_i2c_regs_t::ICMR3, k_ra8_i2c_msk_icmr3_ackbt, k_ra8_i2c_msk_icmr3_ackwp, and RA8_INTERNAL.

Referenced by internal_i2c_drain_rx().

◆ internal_i2c_start()

void internal_i2c_start ( volatile r_i2c_regs_t * reg)
static

Issue a START condition (HUM Ch 39.3.3 step 2 p 2396).

Sets ICCR2.ST; the hardware issues the START once BBSY is clear and automatically transitions to controller-transmit mode.

Parameters
[in]regChannel register block.
Precondition
reg is non-NULL and the bus is free.
Channel previously initialized.
Postcondition
ICCR2.ST is set; hardware issues a START when BBSY clears.
No other register is modified.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 250 of file ra8_i2c.c.

References r_i2c_regs_t::ICCR2, k_ra8_i2c_msk_iccr2_st, and RA8_INTERNAL.

Referenced by internal_i2c_open_phase(), and ra8_i2c_scan().

◆ internal_i2c_status_from_icsr2()

ra8_err_t internal_i2c_status_from_icsr2 ( uint8_t icsr2)
static

Map latched ICSR2 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]icsr2Snapshot of ICSR2.
Returns
ra8_err_t mapped from the highest-priority latched fault.
Return values
k_ra8_okNo fault latched.
k_ra8_err_nackICSR2.NACKF set.
k_ra8_err_hw_errorICSR2.AL set (arbitration lost).
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on the input snapshot.
Note
Thread safety: pure; thread-safe.
Since
0.1.0

Definition at line 194 of file ra8_i2c.c.

References k_ra8_err_hw_error, k_ra8_err_nack, k_ra8_i2c_msk_icsr2_al, k_ra8_i2c_msk_icsr2_nackf, k_ra8_ok, and RA8_INTERNAL.

Referenced by internal_i2c_send_address(), and ra8_i2c_read().

◆ internal_i2c_stop()

void internal_i2c_stop ( volatile r_i2c_regs_t * reg)
static

Issue a STOP condition and wait for the bus to be released.

Requests the STOP then spins until BBSY clears. Used by the transmit path, where the STOP fires immediately after TEND; returning before BBSY clears lets the next START race a busy bus and fail with k_ra8_err_busy.

Parameters
[in]regChannel register block.
Precondition
reg is non-NULL.
Channel previously initialized.
Postcondition
Hardware has issued a STOP and BBSY is observed clear.
The bus is idle and ready for the next START.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 368 of file ra8_i2c.c.

References internal_i2c_stop_request(), internal_i2c_wait_bus_free(), and RA8_INTERNAL.

Referenced by internal_i2c_finish_tx(), ra8_i2c_read(), ra8_i2c_scan(), and ra8_i2c_write().

◆ internal_i2c_stop_request()

void internal_i2c_stop_request ( volatile r_i2c_regs_t * reg)
static

Request a STOP condition without waiting for it to complete.

Clears the prior ICSR2.STOP flag (W0C) so the next transaction sees a fresh edge, then sets ICCR2.SP to request the STOP. The receive path must use this form: during a controller read the STOP only actually fires after the final ICDRR read and the WAIT clear (HUM Ch 39.3.4 step 7), so waiting for BBSY here would deadlock before the last byte is read.

Parameters
[in]regChannel register block.
Precondition
reg is non-NULL.
Channel previously initialized.
Postcondition
ICCR2.SP is set; the STOP fires once preconditions are met.
ICSR2.STOP is cleared so the next STOP edge is detectable.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 343 of file ra8_i2c.c.

References r_i2c_regs_t::ICCR2, r_i2c_regs_t::ICSR2, k_ra8_i2c_msk_iccr2_sp, k_ra8_i2c_msk_icsr2_stop, and RA8_INTERNAL.

Referenced by internal_i2c_drain_rx(), and internal_i2c_stop().

◆ internal_i2c_wait_bus_free()

void internal_i2c_wait_bus_free ( volatile const r_i2c_regs_t * reg)
static

Spin (bounded) until the bus is free (ICCR2.BBSY clears).

BBSY – not the ICSR2.STOP flag – is what the next transaction's busy gate checks, and it clears a few cycles after the STOP edge. Waiting on it before returning keeps a following START from racing a busy bus (k_ra8_err_busy).

Parameters
[in]regChannel register block.
Precondition
reg is non-NULL.
A STOP has been requested (or the bus is otherwise idle).
Postcondition
BBSY is observed clear, or the bounded poll expired.
No register is modified (read-only spin).
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 314 of file ra8_i2c.c.

References r_i2c_regs_t::ICCR2, k_ra8_i2c_msk_iccr2_bbsy, k_ra8_i2c_poll_limit, and RA8_INTERNAL.

Referenced by internal_i2c_drain_rx(), and internal_i2c_stop().

◆ internal_i2c_wait_icsr2()

ra8_err_t internal_i2c_wait_icsr2 ( volatile const r_i2c_regs_t * reg,
uint8_t mask )
static

Wait for a flag in ICSR2 to set, with a bounded spin budget.

Spins up to k_ra8_i2c_poll_limit iterations reading ICSR2 and returning success the moment the masked flag is observed set. The fixed bound satisfies NASA P10 Rule 2.

Parameters
[in]regChannel register block.
[in]maskBit mask to test against ICSR2.
Returns
ra8_err_t outcome of the poll.
Return values
k_ra8_okMasked flag observed set.
k_ra8_err_hw_timeoutSpin budget exhausted before the flag set.
Precondition
reg is non-NULL.
mask is a non-zero single- or multi-bit mask.
Postcondition
On success the masked flag was observed set.
On timeout no register write occurs.
Note
Thread safety: not thread-safe (reads a single channel).
Since
0.1.0

Definition at line 155 of file ra8_i2c.c.

References r_i2c_regs_t::ICSR2, k_ra8_err_hw_timeout, k_ra8_i2c_poll_limit, k_ra8_ok, and RA8_INTERNAL.

Referenced by internal_i2c_drain_rx(), internal_i2c_drain_tx(), internal_i2c_finish_tx(), internal_i2c_send_address(), and ra8_i2c_scan().

◆ priv_ra8_i2c_internal_clk_invalid()

bool priv_ra8_i2c_internal_clk_invalid ( uint32_t bus_hz,
uint32_t pclkb_hz )

Pure predicate: either clock argument is zero.

Promoted so the OR decision can be driven under MC/DC.

Parameters
[in]bus_hzTarget bus clock.
[in]pclkb_hzReference PCLKB clock.
Returns
Boolean reject predicate.
Return values
trueAt least one clock is zero (invalid).
falseBoth clocks are non-zero.
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 114 of file ra8_i2c.c.

Referenced by internal_i2c_bitrate().

◆ ra8_i2c_read()

ra8_err_t ra8_i2c_read ( uint8_t channel,
uint8_t peripheral_7b,
uint8_t * data,
uint32_t len )
nodiscard

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

Mirrors HUM Ch 39.3.4 "Controller Receive Operation" p 2400:

  1. Reject the call if the bus is busy and no repeated-START is held.
  2. Issue a START (or RESTART when the bus is already held).
  3. Write (peripheral_7b << 1) | 1 to ICDRT, then drop to receive mode once the address byte is acknowledged.
  4. Dummy-read ICDRR to begin clocking, then drain len bytes from ICDRR; the second-to-last byte arms ICMR3.WAIT and the last byte is NACKed via ICMR3.ACKBT (paired with ACKWP).
  5. Issue STOP and release the bus.

State machine: IDLE -> ADDR_TX -> DATA_RX -> STOP -> IDLE.

Parameters
[in]channelChannel index.
[in]peripheral_7b7-bit peripheral address.
[out]dataDestination buffer (non-NULL).
[in]lenByte count (non-zero).
Returns
ra8_err_t.
Return values
k_ra8_okTransfer succeeded.
k_ra8_err_null_ptrdata NULL or channel invalid.
k_ra8_err_invalid_arglen is zero.
k_ra8_err_busyBus busy at entry.
k_ra8_err_hw_timeoutRDRF / TEND poll timed out.
k_ra8_err_nackPeripheral NACKed the address byte.
k_ra8_err_hw_errorArbitration lost.
Precondition
Channel previously initialized.
Postcondition
STOP issued and the bus released.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 688 of file ra8_i2c.c.

References g_i2c_tag, r_i2c_regs_t::ICSR2, internal_i2c_busy_gate(), internal_i2c_clear_status(), internal_i2c_drain_rx(), internal_i2c_open_phase(), internal_i2c_send_address(), internal_i2c_status_from_icsr2(), internal_i2c_stop(), k_ra8_err_invalid_arg, k_ra8_i2c_addr_rw_read, k_ra8_i2c_addr_shift, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_i2c_regs(), and s_i2c_state.

Referenced by internal_riic_read(), and ra8_i2c_transfer().

◆ ra8_i2c_scan()

ra8_err_t ra8_i2c_scan ( uint8_t channel,
uint8_t peripheral_7b,
bool * out_acked )
nodiscard

Probe whether a 7-bit peripheral address ACKs.

Issues START, writes the address byte, waits for the ACK / NACK status (ICSR2.TEND / NACKF), and issues STOP. Equivalent to a single i2cdetect sweep entry.

Parameters
[in]channelChannel index.
[in]peripheral_7b7-bit peripheral address.
[out]out_ackedSet to true on ACK, false on NACK.
Returns
ra8_err_t.
Return values
k_ra8_okProbe completed (ACK or NACK).
k_ra8_err_null_ptrout_acked NULL or channel invalid.
k_ra8_err_busyBus busy at entry.
k_ra8_err_hw_timeoutStatus poll timed out.
Precondition
Channel previously initialized.
Postcondition
Bus is released.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 762 of file ra8_i2c.c.

References g_i2c_tag, r_i2c_regs_t::ICSR2, internal_i2c_busy_gate(), internal_i2c_clear_status(), internal_i2c_send_address(), internal_i2c_start(), internal_i2c_stop(), internal_i2c_wait_icsr2(), k_ra8_err_nack, k_ra8_i2c_addr_rw_write, k_ra8_i2c_addr_shift, k_ra8_i2c_msk_icsr2_nackf, k_ra8_i2c_msk_icsr2_tend, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_i2c_regs(), and s_i2c_state.

Referenced by cam_bus_scan(), and main().

◆ ra8_i2c_transfer()

ra8_err_t ra8_i2c_transfer ( uint8_t channel,
uint8_t peripheral_7b,
const uint8_t * wr,
uint32_t wr_len,
uint8_t * rd,
uint32_t rd_len )
nodiscard

Combined write-then-RESTART-then-read in one bus transaction.

Convenience wrapper for the common "address a register, read its contents" pattern. Internally invokes ra8_i2c_write(..., send_stop = false) followed by ra8_i2c_read. If wr_len is zero the write phase is skipped (degenerates to a plain read); if rd_len is zero the read phase is skipped (degenerates to a plain write with STOP).

State machine: IDLE -> ADDR_TX -> DATA_TX -> RESTART -> ADDR_TX(read) -> DATA_RX -> STOP.

Parameters
[in]channelChannel index.
[in]peripheral_7b7-bit peripheral address.
[in]wrBytes to send first (NULL only when wr_len 0).
[in]wr_lenNumber of bytes to send.
[out]rdDestination buffer (NULL only when rd_len 0).
[in]rd_lenNumber of bytes to read.
Returns
ra8_err_t.
Return values
k_ra8_okTransfer succeeded; STOP issued.
k_ra8_err_null_ptrwr/rd NULL with non-zero len, or channel invalid.
k_ra8_err_invalid_argBoth wr_len and rd_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.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 726 of file ra8_i2c.c.

References k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, ra8_i2c_read(), ra8_i2c_regs(), and ra8_i2c_write().

Referenced by cam_bus_scan(), internal_riic_transfer(), and ra8_board_camera_sccb_read_reg().

◆ ra8_i2c_write()

ra8_err_t ra8_i2c_write ( uint8_t channel,
uint8_t peripheral_7b,
const uint8_t * data,
uint32_t len,
bool send_stop )
nodiscard

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

Mirrors HUM Ch 39.3.3 "Controller Transmit Operation" p 2396:

  1. Reject the call if the bus is busy (ICCR2.BBSY == 1) and no repeated-START is in progress.
  2. Issue a START (or RESTART when the bus is already held).
  3. Write (peripheral_7b << 1) | 0 to ICDRT (controller transmit).
  4. Push each payload byte into ICDRT once ICSR2.TDRE sets, bailing on NACK (ICSR2.NACKF).
  5. Wait for ICSR2.TEND, then either issue STOP (send_stop) or hold the bus for a chained read / write.

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

Parameters
[in]channelChannel index.
[in]peripheral_7b7-bit peripheral address.
[in]dataBuffer to send (non-NULL when len > 0).
[in]lenByte count.
[in]send_stopWhen true, issue STOP and release the bus; when false, hold the bus so the next call injects a repeated-START.
Returns
ra8_err_t.
Return values
k_ra8_okTransfer succeeded.
k_ra8_err_null_ptrdata NULL with non-zero len or channel invalid.
k_ra8_err_busyBus busy at entry.
k_ra8_err_hw_timeoutTDRE / TEND 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 send_stop: STOP issued, bus free.
On k_ra8_ok and not send_stop: bus held; next call must be on the same channel.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 579 of file ra8_i2c.c.

References g_i2c_tag, internal_i2c_busy_gate(), internal_i2c_clear_status(), internal_i2c_drain_tx(), internal_i2c_finish_tx(), internal_i2c_open_phase(), internal_i2c_send_address(), internal_i2c_stop(), k_ra8_i2c_addr_rw_write, k_ra8_i2c_addr_shift, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_i2c_regs(), and s_i2c_state.

Referenced by internal_io_expander_write_reg(), internal_riic_write(), ra8_board_camera_sccb_write_reg(), and ra8_i2c_transfer().

Variable Documentation

◆ g_i2c_tag

const char* const g_i2c_tag = "I2C"

Log tag for this driver, shared with ra8_i2c_config.c.

Log tag shared by the I2C transfer and configuration planes.

Owning definition for the g_i2c_tag symbol declared extern in ra8_i2c_internal.h; both I2C translation units log under "I2C".

Note
Read-only string pointer; not mutated after static init.
Since
0.1.0

Defined once in ra8_i2c.c (the data-transfer translation unit) and consumed by both ra8_i2c.c and ra8_i2c_config.c so the two halves of the split driver log under the same "I2C" tag.

Note
Read-only string pointer; not mutated after static init.
Since
0.1.0

Definition at line 65 of file ra8_i2c.c.

Referenced by internal_i2c_bitrate(), ra8_i2c_get_errors(), ra8_i2c_init(), ra8_i2c_peripheral_init(), ra8_i2c_peripheral_poll(), ra8_i2c_peripheral_receive(), ra8_i2c_peripheral_transmit(), ra8_i2c_read(), ra8_i2c_scan(), and ra8_i2c_write().

◆ s_i2c_state

Per-channel state table indexed by channel.

Owning definition for the s_i2c_state array declared extern in ra8_i2c_internal.h so the bring-up plane in ra8_i2c_config.c and the transfer plane here observe identical bus-ownership state.

Warning
Mutated only by the driver under the not-thread-safe contract.
Since
0.1.0

Defined once in ra8_i2c.c and shared with ra8_i2c_config.c so the bring-up and transfer planes observe the same bus-ownership state.

Warning
Mutated only by the driver under the not-thread-safe contract.
See also
ra8_i2c_state_t
Since
0.1.0

Definition at line 132 of file ra8_i2c.c.

Referenced by internal_i2c_finish_tx(), ra8_i2c_deinit(), ra8_i2c_init(), ra8_i2c_peripheral_attach_handler(), ra8_i2c_peripheral_deinit(), ra8_i2c_peripheral_dispatch(), ra8_i2c_peripheral_init(), ra8_i2c_peripheral_poll(), ra8_i2c_peripheral_receive(), ra8_i2c_peripheral_transmit(), ra8_i2c_read(), ra8_i2c_scan(), and ra8_i2c_write().