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

I2C Bus Interface (IIC) bring-up, clock and error-status plane. More...

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

Go to the source code of this file.

Enumerations

enum  ra8_i2c_brate_t : uint32_t {
  k_ra8_i2c_br_field_max = 0x1FU ,
  k_ra8_i2c_br_reserved_hi = 0xE0U ,
  k_ra8_i2c_cks_max = 7U ,
  k_ra8_i2c_period_split = 2U
}
 Bit-rate divider field limits (HUM Ch 39.2.15 / 39.2.16). More...

Functions

static ra8_mstp_t internal_i2c_mstp_id (uint8_t channel)
 Map a channel index to its MSTP gate id.
static uint8_t internal_i2c_pick_cks (uint32_t *total)
 Pick the smallest CKS divider and divide *total to match.
static uint8_t internal_i2c_clamp_half (uint32_t total)
 Clamp one SCL half-period count to the 5-bit BR field.
static ra8_err_t internal_i2c_bitrate (uint32_t bus_hz, uint32_t pclkb_hz, uint8_t *out_cks, uint8_t *out_brh, uint8_t *out_brl)
 Compute the CKS divider and ICBRH/ICBRL half-period counts.
static uint8_t internal_i2c_decode_errors (uint8_t icsr2)
 Decode latched ICSR2 error bits into a k_ra8_i2c_err_* mask.
static void internal_i2c_apply_init_regs (volatile r_i2c_regs_t *reg, uint8_t cks, uint8_t brh, uint8_t brl, bool fast_plus)
 Apply the bring-up register sequence for an IIC channel.
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_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.

Detailed Description

I2C Bus Interface (IIC) bring-up, clock and error-status plane.

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

Configuration-plane half of the RA8D2 RIIC polling driver, split out of ra8_i2c.c to keep each translation unit under the file-size cap. Owns the init / deinit / bit-rate sequence (HUM Ch 39.3.2 "Initial Settings" p 2395), the runtime clock re-program (ra8_i2c_set_clock) and the error-status helpers (ra8_i2c_get_errors / ra8_i2c_clear_errors).

The data-transfer plane (start / write / read / stop / scan) lives in ra8_i2c.c. Both translation units share s_i2c_state and the log tag via ra8_i2c_internal.h.

Owns every write to the RIIC register block performed during channel bring-up and clock setup. See HUM Ch 39 "I2C Bus Interface (IIC)", p 2367-2470.

Since
0.1.0

Definition in file ra8_i2c_config.c.

Enumeration Type Documentation

◆ ra8_i2c_brate_t

enum ra8_i2c_brate_t : uint32_t

Bit-rate divider field limits (HUM Ch 39.2.15 / 39.2.16).

Enumerator
k_ra8_i2c_br_field_max 

ICBRL / ICBRH counter fields are 5 bits ([4:0]).

k_ra8_i2c_br_reserved_hi 

Upper 3 reserved bits of ICBRL / ICBRH read as 1.

k_ra8_i2c_cks_max 

CKS divider exponent ceiling (CKS[2:0] selects PCLKB / 2^CKS).

k_ra8_i2c_period_split 

Period split between SCL high and low halves.

Definition at line 43 of file ra8_i2c_config.c.

Function Documentation

◆ internal_i2c_apply_init_regs()

void internal_i2c_apply_init_regs ( volatile r_i2c_regs_t * reg,
uint8_t cks,
uint8_t brh,
uint8_t brl,
bool fast_plus )
static

Apply the bring-up register sequence for an IIC channel.

Follows HUM Ch 39.3.2 p 2395: hold IIC reset (ICCR1.IICRST with ICE = 0), enable internal reset (ICE = 1), program CKS / ICBRL / ICBRH and the ICFER function bits, then release the reset. FMPE is set for the Fast-mode Plus (>= 1 MHz) bus rate.

Parameters
[in]regChannel register block.
[in]cksCKS divider exponent.
[in]brhICBRH register value.
[in]brlICBRL register value.
[in]fast_plusTrue when the bus runs at Fast-mode Plus.
Precondition
reg is non-NULL.
Channel MSTP gate already ungated.
Postcondition
ICCR1.ICE is set and the channel is out of reset.
ICMR1.CKS, ICBRL, ICBRH and ICFER hold the programmed values.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 270 of file ra8_i2c_config.c.

References r_i2c_regs_t::ICBRH, r_i2c_regs_t::ICBRL, r_i2c_regs_t::ICCR1, r_i2c_regs_t::ICFER, r_i2c_regs_t::ICMR1, k_ra8_i2c_icmr1_cks_pos, k_ra8_i2c_msk_iccr1_ice, k_ra8_i2c_msk_iccr1_iicrst, k_ra8_i2c_msk_icfer_fmpe, k_ra8_i2c_msk_icfer_male, k_ra8_i2c_msk_icfer_nacke, k_ra8_i2c_msk_icfer_scle, and RA8_INTERNAL.

Referenced by ra8_i2c_init().

◆ internal_i2c_bitrate()

ra8_err_t internal_i2c_bitrate ( uint32_t bus_hz,
uint32_t pclkb_hz,
uint8_t * out_cks,
uint8_t * out_brh,
uint8_t * out_brl )
static

Compute the CKS divider and ICBRH/ICBRL half-period counts.

The RIIC internal reference clock is IICphi = PCLKB / 2^CKS (HUM Ch 39.2.3 p 2374). One SCL bit period is (BRH + 1) + (BRL + 1) IICphi cycles for the SCLE=0 / NFE=0 transfer-rate expression (HUM Ch 39.2.16 expression (1) p 2392). Delegates the CKS search and field clamp to internal_i2c_pick_cks / internal_i2c_clamp_half.

Parameters
[in]bus_hzTarget bus clock (non-zero).
[in]pclkb_hzPCLKB frequency (non-zero).
[out]out_cksCKS exponent [0..7].
[out]out_brhICBRH register value (5-bit count + reserved hi).
[out]out_brlICBRL register value (5-bit count + reserved hi).
Returns
ra8_err_t.
Return values
k_ra8_okDivider computed.
k_ra8_err_invalid_argA clock argument was zero.
Precondition
out_cks and out_brh are non-NULL.
bus_hz and pclkb_hz are non-zero.
Postcondition
On success *out_cks <= 7 and the BR fields are clamped.
On error no output is written.
Note
Thread safety: pure; thread-safe.
Since
0.1.0

Definition at line 183 of file ra8_i2c_config.c.

References g_i2c_tag, internal_i2c_clamp_half(), internal_i2c_pick_cks(), k_ra8_err_invalid_arg, k_ra8_i2c_br_reserved_hi, k_ra8_ok, priv_ra8_i2c_internal_clk_invalid(), RA8_CHECK_NULL_PTR, and RA8_INTERNAL.

Referenced by ra8_i2c_init(), and ra8_i2c_set_clock().

◆ internal_i2c_clamp_half()

uint8_t internal_i2c_clamp_half ( uint32_t total)
static

Clamp one SCL half-period count to the 5-bit BR field.

Splits total evenly between the SCL high and low halves, subtracts the +1 the hardware adds, and clamps to k_ra8_i2c_br_field_max.

Parameters
[in]totalDivided bit-period cycle count.
Returns
The 5-bit half-period field value.
Return values
0The divided period collapsed to a single cycle.
Precondition
total is the output of internal_i2c_pick_cks.
None.
Postcondition
Return value is in [0, k_ra8_i2c_br_field_max].
No state is mutated.
Note
Thread safety: pure; thread-safe.
Since
0.1.0

Definition at line 143 of file ra8_i2c_config.c.

References k_ra8_i2c_br_field_max, k_ra8_i2c_period_split, and RA8_INTERNAL.

Referenced by internal_i2c_bitrate().

◆ internal_i2c_decode_errors()

uint8_t internal_i2c_decode_errors ( uint8_t icsr2)
static

Decode latched ICSR2 error bits into a k_ra8_i2c_err_* mask.

Tests the AL, NACKF and TMOF flags independently and ORs the matching k_ra8_i2c_err_* bit into the result so a caller sees every latched fault in a single mask.

Parameters
[in]icsr2Snapshot of ICSR2.
Returns
OR of k_ra8_i2c_err_* bits.
Return values
k_ra8_i2c_err_noneNo fault bit set.
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 227 of file ra8_i2c_config.c.

References k_ra8_i2c_err_arb_lost, k_ra8_i2c_err_nack, k_ra8_i2c_err_none, k_ra8_i2c_err_timeout, k_ra8_i2c_icsr2_tmof_pos, k_ra8_i2c_msk_icsr2_al, k_ra8_i2c_msk_icsr2_nackf, and RA8_INTERNAL.

Referenced by ra8_i2c_get_errors().

◆ internal_i2c_mstp_id()

ra8_mstp_t internal_i2c_mstp_id ( uint8_t channel)
static

Map a channel index to its MSTP gate id.

IIC0 = MSTPB9, IIC1 = MSTPB8, IIC2 = MSTPB7 per HUM Ch 11.2.7 "MSTPCRB" p 444, encoded in ra8_mstp_regs.h.

Parameters
[in]channelChannel index (already range-checked by caller).
Returns
The matching k_ra8_mstp_iicN enum value.
Return values
k_ra8_mstp_iic0channel is 0.
k_ra8_mstp_iic1channel is 1.
k_ra8_mstp_iic2channel is 2 (or any other value, defensively).
Precondition
channel is 0, 1 or 2.
Caller resolved a non-NULL register pointer for channel.
Postcondition
Return value is one of the three IIC MSTP ids.
No global state is mutated.
Note
Thread safety: pure mapping, no state.
Since
0.1.0

Definition at line 74 of file ra8_i2c_config.c.

References k_ra8_mstp_iic0, k_ra8_mstp_iic1, k_ra8_mstp_iic2, and RA8_INTERNAL.

Referenced by ra8_i2c_deinit(), and ra8_i2c_init().

◆ internal_i2c_pick_cks()

uint8_t internal_i2c_pick_cks ( uint32_t * total)
static

Pick the smallest CKS divider and divide *total to match.

Repeatedly halves the candidate bit-period cycle count until a single SCL half-period fits inside the 5-bit ICBRL/ICBRH field, returning the CKS exponent used. The loop is bounded by k_ra8_i2c_cks_max + 1 iterations (NASA P10 Rule 2).

Parameters
[in,out]totalOn entry the full PCLKB / bus_hz cycle count; on return divided by 2^CKS.
Returns
The chosen CKS exponent, clamped to [0, k_ra8_i2c_cks_max].
Return values
0The full period already fits the field.
Precondition
total is non-NULL.
*total was derived from non-zero clocks.
Postcondition
*total reflects the divided cycle count.
Return value is in [0, k_ra8_i2c_cks_max].
Note
Thread safety: pure on the supplied pointer; thread-safe.
Since
0.1.0

Definition at line 107 of file ra8_i2c_config.c.

References k_ra8_i2c_br_field_max, k_ra8_i2c_cks_max, k_ra8_i2c_period_split, and RA8_INTERNAL.

Referenced by internal_i2c_bitrate().

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