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

I2C Bus Interface (IIC) controller driver – polling mode. More...

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

Go to the source code of this file.

Data Structures

struct  ra8_i2c_cfg_t
 Configuration descriptor for ra8_i2c_init. More...
struct  ra8_i2c_peripheral_cfg_t
 Configuration descriptor for ra8_i2c_peripheral_init. More...

Typedefs

typedef void(* ra8_i2c_peripheral_event_fn_t) (void *ctx, ra8_i2c_peripheral_event_t event)
 Address-match callback fired by ra8_i2c_peripheral_dispatch.

Enumerations

enum  ra8_i2c_speed_t : uint32_t {
  k_ra8_i2c_speed_standard = 100000U ,
  k_ra8_i2c_speed_fast = 400000U ,
  k_ra8_i2c_speed_fast_plus = 1000000U
}
 Supported bus speeds. More...
enum  ra8_i2c_err_mask_t : uint8_t {
  k_ra8_i2c_err_none = 0x00U ,
  k_ra8_i2c_err_arb_lost = 0x01U ,
  k_ra8_i2c_err_nack = 0x02U ,
  k_ra8_i2c_err_timeout = 0x04U
}
 Error-mask bits returned by ra8_i2c_get_errors. More...
enum  ra8_i2c_peripheral_slot_t : uint8_t {
  k_ra8_i2c_peripheral_slot_0 = 0U ,
  k_ra8_i2c_peripheral_slot_1 = 1U ,
  k_ra8_i2c_peripheral_slot_2 = 2U
}
 Which own-address register pair (SARLy/SARUy) holds the address. More...
enum  ra8_i2c_peripheral_event_t : uint8_t {
  k_ra8_i2c_peripheral_event_none = 0U ,
  k_ra8_i2c_peripheral_event_write = 1U ,
  k_ra8_i2c_peripheral_event_read = 2U ,
  k_ra8_i2c_peripheral_event_stop = 3U
}
 Outcome of ra8_i2c_peripheral_poll / ra8_i2c_peripheral_dispatch. More...

Functions

ra8_err_t ra8_i2c_init (uint8_t channel, const ra8_i2c_cfg_t *cfg)
 Initialise an IIC channel as a controller and bring the bus up.
ra8_err_t ra8_i2c_deinit (uint8_t channel)
 Tear down an IIC channel.
ra8_err_t ra8_i2c_set_clock (uint8_t channel, uint32_t bus_hz, uint32_t pclkb_hz)
 Update the bus clock without tearing the channel down.
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.
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.
ra8_err_t ra8_i2c_get_errors (uint8_t channel, uint8_t *out_mask)
 Read latched error flags from ICSR2 (AL / NACKF / TMOF).
ra8_err_t ra8_i2c_clear_errors (uint8_t channel)
 Clear latched error flags in ICSR2.
ra8_err_t ra8_i2c_peripheral_init (uint8_t channel, const ra8_i2c_peripheral_cfg_t *cfg)
 Arm an IIC channel to answer as an I2C target (peripheral).
ra8_err_t ra8_i2c_peripheral_deinit (uint8_t channel)
 Disarm own-address matching, returning the channel to controller use.
ra8_err_t ra8_i2c_peripheral_poll (uint8_t channel, ra8_i2c_peripheral_event_t *out_event)
 Wait (bounded) for a controller to address this target.
ra8_err_t ra8_i2c_peripheral_receive (uint8_t channel, uint8_t *buf, uint32_t capacity, uint32_t *out_received)
 Drain a controller-write transaction into buf (target receive).
ra8_err_t ra8_i2c_peripheral_transmit (uint8_t channel, const uint8_t *data, uint32_t len, uint32_t *out_sent)
 Answer a controller-read transaction from data (target transmit).
ra8_err_t ra8_i2c_peripheral_attach_handler (uint8_t channel, ra8_i2c_peripheral_event_fn_t fn, void *ctx)
 Attach (or detach) the address-match callback for a channel.
void ra8_i2c_peripheral_dispatch (uint8_t channel)
 Snapshot the latched target status and fire the attached callback.

Detailed Description

I2C Bus Interface (IIC) controller driver – polling mode.

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

Polling-mode controller driver for the RA8D2 RIIC peripheral (channels IIC0/IIC1/IIC2 at 0x4025_E000 + 0x0100 * n). This is the classic Renesas RIIC block described in HUM Ch 39 "I2C Bus Interface (IIC)" p 2367-2470, distinct from the I3C unified IP that ra8_i3c / ra8_i3c_i2c drive. The board's Grove / Pmod / mikroBUS / Arduino I2C bus and the U15 configuration-switch port expander live on IIC1 (P511/P512).

The driver supports both bus roles. The controller (initiator) surface mirrors FSP r_iic_master minus DTC / interrupt fast paths:

The target (peripheral) surface lets the RA8D2 answer a remote controller once one of its own-address slots matches. It mirrors FSP r_iic_slave minus the interrupt path (HUM Ch 39.3.5 "Peripheral Transmit Operation" p 2405 and Ch 39.3.6 "Peripheral Receive Operation" p 2408):

Since
0.1.0

Definition in file ra8_i2c.h.

Typedef Documentation

◆ ra8_i2c_peripheral_event_fn_t

typedef void(* ra8_i2c_peripheral_event_fn_t) (void *ctx, ra8_i2c_peripheral_event_t event)

Address-match callback fired by ra8_i2c_peripheral_dispatch.

Invoked once per ra8_i2c_peripheral_dispatch call when the latched RIIC status decodes to a target event: a controller addressed this device for a write (k_ra8_i2c_peripheral_event_write) or a read (k_ra8_i2c_peripheral_event_read), or a STOP ended the transaction (k_ra8_i2c_peripheral_event_stop). A write handler typically answers with ra8_i2c_peripheral_receive and a read handler with ra8_i2c_peripheral_transmit. Runs in the dispatcher's context – a RIIC ISR or a poll loop – so keep it short and non-blocking when wired to an ISR.

Parameters
[in]ctxOpaque context registered with ra8_i2c_peripheral_attach_handler.
[in]eventDecoded target event; never k_ra8_i2c_peripheral_event_none (dispatch drops that).
Note
Thread safety: runs in the dispatcher's context; not re-entrant.
See also
ra8_i2c_peripheral_attach_handler
ra8_i2c_peripheral_dispatch
Since
0.1.0

Definition at line 462 of file ra8_i2c.h.

Enumeration Type Documentation

◆ ra8_i2c_err_mask_t

enum ra8_i2c_err_mask_t : uint8_t

Error-mask bits returned by ra8_i2c_get_errors.

Decoded from ICSR2 (HUM Ch 39.2.10 p 2384). The values double as a bitmask so a single transfer can report multiple latched faults.

Enumerator
k_ra8_i2c_err_none 

No latched error.

k_ra8_i2c_err_arb_lost 

ICSR2.AL set (arbitration lost).

k_ra8_i2c_err_nack 

ICSR2.NACKF set (NACK received).

k_ra8_i2c_err_timeout 

ICSR2.TMOF set (bus timeout).

Definition at line 110 of file ra8_i2c.h.

◆ ra8_i2c_peripheral_event_t

Outcome of ra8_i2c_peripheral_poll / ra8_i2c_peripheral_dispatch.

Reported from the perspective of the remote controller's R/W# bit, decoded from the own-address detection flags (ICSR1) and the transmit/receive mode bit (ICCR2.TRS) that the hardware latches on the ninth SCL clock. poll only ever returns none / write / read; dispatch additionally reports stop when a bus STOP ended the transaction with no fresh match.

See also
ra8_i2c_peripheral_poll
ra8_i2c_peripheral_dispatch
Since
0.1.0
Enumerator
k_ra8_i2c_peripheral_event_none 

No own-address match observed.

k_ra8_i2c_peripheral_event_write 

Controller WRITE: call receive next.

k_ra8_i2c_peripheral_event_read 

Controller READ: call transmit next.

k_ra8_i2c_peripheral_event_stop 

STOP ended the transaction (idle).

Definition at line 431 of file ra8_i2c.h.

◆ ra8_i2c_peripheral_slot_t

enum ra8_i2c_peripheral_slot_t : uint8_t

Which own-address register pair (SARLy/SARUy) holds the address.

The RIIC block exposes three independent own-address comparators per channel. A target may answer on any one of them; this driver programmes a single slot per ra8_i2c_peripheral_init call. Each addresses one of the RIIC own-address comparators (the SARLy / SARUy register pairs), exposed here as an inclusive "own-address slot".

See also
ra8_i2c_peripheral_cfg_t
Since
0.1.0
Enumerator
k_ra8_i2c_peripheral_slot_0 

Own-address slot 0 (SARL0/SARU0).

k_ra8_i2c_peripheral_slot_1 

Own-address slot 1 (SARL1/SARU1).

k_ra8_i2c_peripheral_slot_2 

Own-address slot 2 (SARL2/SARU2).

Definition at line 410 of file ra8_i2c.h.

◆ ra8_i2c_speed_t

enum ra8_i2c_speed_t : uint32_t

Supported bus speeds.

Per HUM Ch 39.1 Table 39.1 "IIC specifications" p 2367: Fast-mode Plus is supported up to 1 Mbps.

Enumerator
k_ra8_i2c_speed_standard 

100 kHz Standard mode (Sm).

k_ra8_i2c_speed_fast 

400 kHz Fast mode (Fm).

k_ra8_i2c_speed_fast_plus 

1 MHz Fast-mode Plus (Fm+).

Definition at line 79 of file ra8_i2c.h.

Function Documentation

◆ ra8_i2c_clear_errors()

ra8_err_t ra8_i2c_clear_errors ( uint8_t channel)
nodiscard

Clear latched error flags in ICSR2.

Parameters
[in]channelChannel index.
Returns
ra8_err_t.
Return values
k_ra8_okAL / NACKF / TMOF W0C cleared.
k_ra8_err_invalid_argChannel out of range.
Precondition
Channel previously initialized.
Postcondition
ICSR2.AL, ICSR2.NACKF and ICSR2.TMOF read back zero.
Note
Thread safety: not thread-safe.
Since
0.1.0

< RA8 I2C error clear mask.

Definition at line 393 of file ra8_i2c_config.c.

References r_i2c_regs_t::ICSR2, k_ra8_err_invalid_arg, k_ra8_i2c_icsr2_tmof_pos, k_ra8_i2c_msk_icsr2_al, k_ra8_i2c_msk_icsr2_nackf, k_ra8_ok, and ra8_i2c_regs().

◆ ra8_i2c_deinit()

ra8_err_t ra8_i2c_deinit ( uint8_t channel)
nodiscard

Tear down an IIC 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
ICCR1.ICE cleared and the channel MSTP bit ref-released.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 338 of file ra8_i2c_config.c.

References r_i2c_regs_t::ICCR1, internal_i2c_mstp_id(), k_ra8_err_invalid_arg, ra8_i2c_regs(), ra8_mstp_disable(), and s_i2c_state.

◆ ra8_i2c_get_errors()

ra8_err_t ra8_i2c_get_errors ( uint8_t channel,
uint8_t * out_mask )
nodiscard

Read latched error flags from ICSR2 (AL / NACKF / TMOF).

Parameters
[in]channelChannel index.
[out]out_maskOR of k_ra8_i2c_err_* bits.
Returns
ra8_err_t.
Return values
k_ra8_okout_mask populated.
k_ra8_err_null_ptrout_mask is NULL.
k_ra8_err_invalid_argchannel out of range.
Precondition
Channel previously initialized.
Postcondition
*out_mask reflects the latched ICSR2 error bits.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 381 of file ra8_i2c_config.c.

References g_i2c_tag, r_i2c_regs_t::ICSR2, internal_i2c_decode_errors(), k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, and ra8_i2c_regs().

◆ ra8_i2c_init()

ra8_err_t ra8_i2c_init ( uint8_t channel,
const ra8_i2c_cfg_t * cfg )
nodiscard

Initialise an IIC channel as a controller and bring the bus up.

Mirrors the FSP r_iic_master open + HUM Ch 39.3.2 "Initial Settings" p 2395 bring-up: ungate the channel MSTP gate, hold the IIC reset (ICCR1.IICRST), program the bit rate (CKS / ICBRL / ICBRH), enable the function bits in ICFER (MALE / NACKE / SCLE plus FMPE for 1 MHz), then release the reset and set ICCR1.ICE.

Parameters
[in]channelChannel index (0, 1 or 2).
[in]cfgConfiguration descriptor (non-NULL).
Returns
ra8_err_t.
Return values
k_ra8_okChannel initialized, ICCR1.ICE = 1.
k_ra8_err_null_ptrcfg is NULL.
k_ra8_err_invalid_argchannel out of range or cfg->bus_hz / cfg->pclkb_hz zero.
Precondition
IRQs masked or single-threaded init context.
ra8_mstp_init has been called.
Postcondition
On success ICCR1.ICE is set and the channel is ready to service ra8_i2c_write / ra8_i2c_read.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 308 of file ra8_i2c_config.c.

References ra8_i2c_cfg_t::bus_hz, g_i2c_tag, internal_i2c_apply_init_regs(), internal_i2c_bitrate(), internal_i2c_mstp_id(), k_ra8_err_invalid_arg, k_ra8_i2c_speed_fast_plus, k_ra8_ok, ra8_i2c_cfg_t::pclkb_hz, RA8_CHECK_NULL_PTR, ra8_i2c_regs(), ra8_log_info_val, ra8_mstp_enable(), RA8_RETURN_ON_ERROR, and s_i2c_state.

Referenced by internal_io_expander_apply_mask().

◆ ra8_i2c_peripheral_attach_handler()

ra8_err_t ra8_i2c_peripheral_attach_handler ( uint8_t channel,
ra8_i2c_peripheral_event_fn_t fn,
void * ctx )
nodiscard

Attach (or detach) the address-match callback for a channel.

Stores fn and ctx in the channel's driver state so a later ra8_i2c_peripheral_dispatch can fire the callback when a controller addresses this target or a STOP ends a transaction. Pass fn == NULL to detach; dispatch then becomes a no-op for the channel. The handler is independent of ra8_i2c_peripheral_poll, which never consults it.

Parameters
[in]channelChannel index (0, 1 or 2).
[in]fnCallback to fire on a decoded event, or NULL to detach.
[in]ctxOpaque context passed back to fn (may be NULL).
Returns
ra8_err_t.
Return values
k_ra8_okHandler stored for the channel.
k_ra8_err_invalid_argchannel out of range.
Precondition
IRQs masked or single-threaded with respect to dispatch.
The channel index is one this driver owns.
Postcondition
The channel's handler equals fn and its context equals ctx.
No hardware register is touched.
Note
Thread safety: not thread-safe.
See also
ra8_i2c_peripheral_dispatch
Since
0.1.0

Definition at line 594 of file ra8_i2c_peripheral.c.

References k_ra8_err_invalid_arg, k_ra8_i2c_channel_count, k_ra8_ok, and s_i2c_state.

Referenced by riic_target_arm().

◆ ra8_i2c_peripheral_deinit()

ra8_err_t ra8_i2c_peripheral_deinit ( uint8_t channel)
nodiscard

Disarm own-address matching, returning the channel to controller use.

Parameters
[in]channelChannel index.
Returns
ra8_err_t.
Return values
k_ra8_okICSER cleared, WAIT released.
k_ra8_err_invalid_argchannel out of range.
k_ra8_err_not_initializedTarget role was not armed for this channel.
Precondition
Channel previously armed with ra8_i2c_peripheral_init.
IRQs masked or single-threaded context.
Postcondition
ICSER reads 0 and ICMR3.WAIT is clear.
The channel answers no own address; controller-role transfers resume.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 435 of file ra8_i2c_peripheral.c.

References r_i2c_regs_t::ICIER, r_i2c_regs_t::ICMR3, r_i2c_regs_t::ICSER, k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_i2c_msk_icmr3_wait, k_ra8_i2c_peripheral_icier_arm, k_ra8_ok, ra8_i2c_regs(), and s_i2c_state.

◆ ra8_i2c_peripheral_dispatch()

void ra8_i2c_peripheral_dispatch ( uint8_t channel)

Snapshot the latched target status and fire the attached callback.

Reads ICSR1 (own-address match flags), ICSR2 (STOP) and ICCR2 (TRS) once, classifies them into an ra8_i2c_peripheral_event_t (an own-address match decodes to write / read from TRS; otherwise a latched STOP decodes to stop), and – when the event is not none and a handler is attached – invokes the handler with the registered context. Read-only with respect to the bus: it clears no flags and queues no data, leaving the data-phase flag handling to ra8_i2c_peripheral_receive / ra8_i2c_peripheral_transmit the handler calls. Safe to call from the RIIC RXI / TXI / STPI ISR or a poll loop; a no-op when the channel is invalid, not armed, or has no handler.

Parameters
[in]channelChannel index (0, 1 or 2).
Precondition
The channel was armed with ra8_i2c_peripheral_init.
A handler may or may not be attached.
Postcondition
At most one handler invocation occurs per call.
No RIIC register is written (read-only snapshot).
Note
Thread safety: runs in the caller's context (ISR or poll); not re-entrant on one channel.
See also
ra8_i2c_peripheral_attach_handler
Since
0.1.0

Definition at line 605 of file ra8_i2c_peripheral.c.

References r_i2c_regs_t::ICCR2, r_i2c_regs_t::ICSR1, r_i2c_regs_t::ICSR2, internal_i2c_dispatch_event(), k_ra8_i2c_peripheral_event_none, ra8_i2c_regs(), and s_i2c_state.

Referenced by main().

◆ ra8_i2c_peripheral_init()

ra8_err_t ra8_i2c_peripheral_init ( uint8_t channel,
const ra8_i2c_peripheral_cfg_t * cfg )
nodiscard

Arm an IIC channel to answer as an I2C target (peripheral).

Programmes one own-address slot (SARLy = own_addr_7b << 1 in 7-bit format, SARUy = 0) and enables the matching ICSER.SARyE bit, plus ICSER.GCAE when general_call is set, so the hardware raises ICSR1.AASy / ICSR1.GCA on a matching address (HUM Ch 39.2.7 p 2380, Ch 39.2.9 p 2382, Ch 39.2.13 p 2390). When clock_stretch is set, ICMR3.WAIT is armed so SCL is held low between the ninth and first clocks until the byte is serviced. When irq_enable is set, ICIER's RIE / TIE / SPIE bits are armed so the RIIC RXI / TXI / STPI interrupts fire on an own-address match and a STOP; wire those vectors to ra8_i2c_peripheral_dispatch. The channel stays in peripheral mode (ICCR2.MST = 0) until a matching address arrives.

Parameters
[in]channelChannel index (0, 1 or 2).
[in]cfgConfiguration descriptor (non-NULL).
Returns
ra8_err_t.
Return values
k_ra8_okOwn-address slot armed.
k_ra8_err_null_ptrcfg is NULL or channel invalid.
k_ra8_err_invalid_argown_addr_7b > 0x7F or slot out of range.
Precondition
ra8_i2c_init has already brought the channel up (ICE = 1).
IRQs masked or single-threaded init context.
Postcondition
On success the channel answers cfg->own_addr_7b and is ready for ra8_i2c_peripheral_poll / ra8_i2c_peripheral_dispatch.
ICSER reflects the armed own-address / general-call enables.
Note
Thread safety: not thread-safe.
See also
ra8_i2c_peripheral_dispatch
Since
0.1.0

Definition at line 403 of file ra8_i2c_peripheral.c.

References ra8_i2c_peripheral_cfg_t::clock_stretch, g_i2c_tag, ra8_i2c_peripheral_cfg_t::general_call, r_i2c_regs_t::ICIER, r_i2c_regs_t::ICMR3, r_i2c_regs_t::ICSER, internal_i2c_target_icser_mask(), internal_i2c_target_set_addr(), ra8_i2c_peripheral_cfg_t::irq_enable, k_ra8_err_invalid_arg, k_ra8_i2c_msk_icmr3_wait, k_ra8_i2c_peripheral_addr_7b_max, k_ra8_i2c_peripheral_icier_arm, k_ra8_i2c_peripheral_slot_max, k_ra8_ok, ra8_i2c_peripheral_cfg_t::own_addr_7b, RA8_CHECK_NULL_PTR, ra8_i2c_regs(), s_i2c_state, and ra8_i2c_peripheral_cfg_t::slot.

Referenced by riic_target_arm().

◆ ra8_i2c_peripheral_poll()

ra8_err_t ra8_i2c_peripheral_poll ( uint8_t channel,
ra8_i2c_peripheral_event_t * out_event )
nodiscard

Wait (bounded) for a controller to address this target.

Spins on ICSR1 / ICSR2 until an own-address match or a STOP is observed, then classifies the transaction from ICSR1 (match flags) and ICCR2.TRS: write when the controller will send data (target receives), read when the controller will clock data out (target transmits). Returns none if the bounded spin elapses without a match.

State machine: IDLE --match,R/W=0--> (write) --match,R/W=1--> (read).

Parameters
[in]channelChannel index.
[out]out_eventDecoded event (non-NULL).
Returns
ra8_err_t.
Return values
k_ra8_ok*out_event populated (may be none).
k_ra8_err_null_ptrout_event NULL or channel invalid.
k_ra8_err_not_initializedTarget role not armed for this channel.
Precondition
Channel armed with ra8_i2c_peripheral_init.
out_event points to writable storage.
Postcondition
*out_event reflects the latched ICSR1 / ICCR2 state.
No bus state is mutated (read-only poll).
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 454 of file ra8_i2c_peripheral.c.

References g_i2c_tag, r_i2c_regs_t::ICCR2, r_i2c_regs_t::ICSR1, r_i2c_regs_t::ICSR2, internal_i2c_target_classify(), k_ra8_err_not_initialized, k_ra8_i2c_peripheral_event_none, k_ra8_i2c_peripheral_poll_limit, k_ra8_ok, priv_ra8_i2c_internal_peripheral_poll_done(), RA8_CHECK_NULL_PTR, ra8_i2c_regs(), and s_i2c_state.

◆ ra8_i2c_peripheral_receive()

ra8_err_t ra8_i2c_peripheral_receive ( uint8_t channel,
uint8_t * buf,
uint32_t capacity,
uint32_t * out_received )
nodiscard

Drain a controller-write transaction into buf (target receive).

Mirrors HUM Ch 39.3.6 "Peripheral Receive Operation" p 2408: dummy-read ICDRR to discard the matched address byte, then read each data byte from ICDRR as ICSR2.RDRF sets, stopping when ICSR2.STOP is detected or buf fills. Clears ICSR2.STOP before returning. Clock stretching (if armed) gives the loop time to read each byte before the controller clocks the next.

State machine: RX_ACTIVE --RDRF--> store byte ... --STOP|full--> IDLE.

Parameters
[in]channelChannel index.
[out]bufDestination buffer (non-NULL).
[in]capacityBuffer size in bytes (non-zero).
[out]out_receivedNumber of bytes stored (non-NULL).
Returns
ra8_err_t.
Return values
k_ra8_okBytes received (possibly zero) up to STOP.
k_ra8_err_null_ptrbuf / out_received NULL or channel invalid.
k_ra8_err_invalid_argcapacity is zero.
k_ra8_err_not_initializedTarget role not armed.
k_ra8_err_hw_timeoutNo byte arrived within the spin budget.
Precondition
Channel armed and ra8_i2c_peripheral_poll returned write.
buf has room for capacity bytes and out_received is writable.
Postcondition
*out_received <= capacity and ICSR2.STOP is cleared.
Bytes [0, *out_received) of buf hold the received payload.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 483 of file ra8_i2c_peripheral.c.

References g_i2c_tag, r_i2c_regs_t::ICDRR, r_i2c_regs_t::ICSR2, internal_i2c_target_wait(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_i2c_msk_icsr2_rdrf, k_ra8_i2c_msk_icsr2_stop, k_ra8_ok, priv_ra8_i2c_internal_target_drain_rx(), RA8_CHECK_NULL_PTR, ra8_i2c_regs(), and s_i2c_state.

Referenced by riic_target_on_event().

◆ ra8_i2c_peripheral_transmit()

ra8_err_t ra8_i2c_peripheral_transmit ( uint8_t channel,
const uint8_t * data,
uint32_t len,
uint32_t * out_sent )
nodiscard

Answer a controller-read transaction from data (target transmit).

Mirrors HUM Ch 39.3.5 "Peripheral Transmit Operation" p 2405: push each byte to ICDRT as ICSR2.TDRE sets, stopping when the controller NACKs the last byte it wants (ICSR2.NACKF) or the buffer is exhausted, then waits for TEND / NACKF, dummy-reads ICDRR to release SCL, and clears NACKF / STOP.

State machine: TX_ACTIVE --TDRE--> push byte ... --NACK|sent==len--> IDLE.

Parameters
[in]channelChannel index.
[in]dataSource buffer (non-NULL).
[in]lenBytes available to send (non-zero).
[out]out_sentNumber of bytes the controller accepted (non-NULL).
Returns
ra8_err_t.
Return values
k_ra8_okTransmit completed (controller NACK is a normal end-of-read, not an error).
k_ra8_err_null_ptrdata / out_sent NULL or channel invalid.
k_ra8_err_invalid_arglen is zero.
k_ra8_err_not_initializedTarget role not armed.
k_ra8_err_hw_timeoutTDRE never armed before any byte was sent.
Precondition
Channel armed and ra8_i2c_peripheral_poll returned read.
data holds len bytes and out_sent is writable.
Postcondition
*out_sent <= len and ICSR2.NACKF / STOP are cleared.
SCL is released (ICDRR dummy-read) so the bus is free for the next transaction.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 519 of file ra8_i2c_peripheral.c.

References g_i2c_tag, internal_i2c_target_fill_tx(), internal_i2c_target_finish_tx(), k_ra8_err_hw_timeout, k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_i2c_regs(), and s_i2c_state.

Referenced by riic_target_on_event().

◆ 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_set_clock()

ra8_err_t ra8_i2c_set_clock ( uint8_t channel,
uint32_t bus_hz,
uint32_t pclkb_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]pclkb_hzCurrent PCLKB frequency in Hz (non-zero).
Returns
ra8_err_t.
Return values
k_ra8_okCKS / ICBRL / ICBRH reprogrammed.
k_ra8_err_invalid_argChannel / clock out of range.
Precondition
Channel previously initialized.
Postcondition
ICMR1.CKS, ICBRL and ICBRH reflect the new divider.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 352 of file ra8_i2c_config.c.

References r_i2c_regs_t::ICBRH, r_i2c_regs_t::ICBRL, r_i2c_regs_t::ICMR1, internal_i2c_bitrate(), k_ra8_err_invalid_arg, k_ra8_i2c_cks_max, k_ra8_i2c_icmr1_cks_pos, k_ra8_ok, and ra8_i2c_regs().

◆ 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().