ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_i3c_i2c_control.c
Go to the documentation of this file.
1
33
34#include <stdint.h>
35
36#include "ra8_attributes.h"
37#include "ra8_check.h"
38#include "ra8_err.h"
39#include "ra8_hw_err.h"
40#include "ra8_i3c_i2c.h"
42#include "ra8_i3c_i2c_regs.h"
43
45static const char* s_tag = "IIC_B";
46
61
79RA8_INTERNAL static uint8_t internal_i3c_i2c_decode_errors(uint32_t bst)
80{
81 uint8_t mask = k_ra8_i3c_i2c_err_none;
82 if ((bst & k_ra8_i3c_i2c_msk_bst_alf) != 0U) {
84 }
85 if ((bst & k_ra8_i3c_i2c_msk_bst_nackdf) != 0U) {
87 }
88 if ((bst & k_ra8_i3c_i2c_msk_bst_todf) != 0U) {
90 }
91 return mask;
92}
93
94/* =============================================================================
95 * Abort -- cancel an in-flight transaction.
96 * =============================================================================
97 */
98
100{
101 volatile r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
102 if (reg == nullptr) {
104 }
105 /* Mask interrupts before tearing down (mirrors FSP
106 * controller abort-sequence helper).
107 * HUM Ch 40.2.48 "BIE", p 2495 / Ch 40.2.52 "NTIE" p 2504. */
108 reg->BIE = 0U;
109 reg->NTIE = 0U;
110
113 s_iic_b_state[channel].bus_held = false;
114 return k_ra8_ok;
115}
116
117/* =============================================================================
118 * Bus probe -- single-byte address-only transaction.
119 * =============================================================================
120 */
121
122ra8_err_t ra8_i3c_i2c_scan(uint8_t channel, uint8_t target_7b, bool* out_acked)
123{
124 volatile r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
125 RA8_CHECK_NULL_PTR(reg, s_tag, "iic_b_scan: channel");
126 RA8_CHECK_NULL_PTR(out_acked, s_tag, "iic_b_scan: out_acked");
127
128 *out_acked = false;
131
132 const uint8_t address_byte = (uint8_t)(((uint32_t)target_7b << k_ra8_i3c_i2c_ctrl_addr_shift) |
134 ra8_err_t err = priv_i3c_i2c_send_address(reg, address_byte);
135 if (err != k_ra8_ok) {
137 return err;
138 }
139
140 /* Wait for either TENDF (peripheral ACKed the address) or NACKDF. */
142 for (uint32_t i = 0U; i < k_ra8_i3c_i2c_ctrl_poll_limit; i++) {
143 const uint32_t bst = reg->BST;
144 const bool transfer_done =
146#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
147 /* HUM Ch 40.2.46 "BST : Bus Status Register" p 2490 */
148 const bool observed = ra8_fake_mmio_poll(&reg->BST, i, transfer_done);
149#else
150 const bool observed = transfer_done;
151#endif
152 if (observed) {
153 *out_acked = (bst & k_ra8_i3c_i2c_msk_bst_nackdf) == 0U;
154 err = k_ra8_ok;
155 break;
156 }
157 }
158
159 /* Stop is best-effort -- record the outcome of the probe regardless. */
162 return err;
163}
164
165/* =============================================================================
166 * Status helpers.
167 * =============================================================================
168 */
169
170ra8_err_t ra8_i3c_i2c_get_errors(uint8_t channel, uint8_t* out_mask)
171{
172 RA8_CHECK_NULL_PTR(out_mask, s_tag, "iic_b_get_errors: out_mask");
173 volatile const r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
174 if (reg == nullptr) {
176 }
177 *out_mask = internal_i3c_i2c_decode_errors(reg->BST);
178 return k_ra8_ok;
179}
180
182{
183 volatile r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
184 if (reg == nullptr) {
186 }
187 /* HUM Ch 40.2.46 "BST : Bus Status Register" p 2490 */
188 enum : uint32_t {
189 k_ra8_i3c_i2c_err_clear_mask = k_ra8_i3c_i2c_msk_bst_alf | k_ra8_i3c_i2c_msk_bst_nackdf |
191 };
192 reg->BST = reg->BST & ~k_ra8_i3c_i2c_err_clear_mask;
193 return k_ra8_ok;
194}
195
196/* =============================================================================
197 * Interrupt handler attach + ERI dispatch.
198 * =============================================================================
199 */
200
202{
203 volatile r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
204 if (reg == nullptr) {
206 }
207 s_iic_b_state[channel].cb = fn;
208 s_iic_b_state[channel].ctx = ctx;
209
210 /* Toggle the interrupt sources used by the polling driver as a
211 * single group when (de)attaching a handler. Per-bit tuning lands
212 * when the first interrupt-mode consumer arrives. */
213 if (fn != nullptr) {
214 /* HUM Ch 40.2.48 "BIE : Bus Interrupt Enable Register" p 2495 */
217 /* HUM Ch 40.2.52 "NTIE : Normal Transfer Interrupt Enable" p 2504 */
219 } else {
220 /* HUM Ch 40.2.48 "BIE : Bus Interrupt Enable Register" p 2495 */
221 reg->BIE = 0U;
222 /* HUM Ch 40.2.52 "NTIE : Normal Transfer Interrupt Enable" p 2504 */
223 reg->NTIE = 0U;
224 }
225 return k_ra8_ok;
226}
227
228void ra8_i3c_i2c_dispatch_eri(uint8_t channel)
229{
230 if ((uint16_t)channel >= k_ra8_i3c_i2c_channel_count) {
231 return;
232 }
233 uint8_t mask = 0U;
234 (void)ra8_i3c_i2c_get_errors(channel, &mask);
235 (void)ra8_i3c_i2c_clear_errors(channel);
236 const ra8_i3c_i2c_complete_fn_t cb = s_iic_b_state[channel].cb;
237 if (priv_i3c_i2c_should_dispatch(mask, (const void*)cb)) {
238 cb(s_iic_b_state[channel].ctx, mask);
239 }
240}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Bounded wait-flag primitives for RA8D2 HAL drivers.
void priv_i3c_i2c_start(volatile r_i3c_i2c_regs_t *reg)
Issue a START condition.
bool priv_i3c_i2c_should_dispatch(uint8_t mask, const void *cb)
Pure dispatch-callback predicate – see header for full contract.
Definition ra8_i3c_i2c.c:96
ra8_i3c_i2c_state_t s_iic_b_state[k_ra8_i3c_i2c_channel_count]
Per-channel state table indexed by channel.
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.
void priv_i3c_i2c_stop(volatile r_i3c_i2c_regs_t *reg)
Issue a STOP condition.
IIC_B (I3C unified IP, I2C-only mode) controller driver.
@ k_ra8_i3c_i2c_err_timeout
BST.TODF set.
Definition ra8_i3c_i2c.h:90
@ k_ra8_i3c_i2c_err_nack
BST.NACKDF set.
Definition ra8_i3c_i2c.h:89
@ k_ra8_i3c_i2c_err_none
No latched error.
Definition ra8_i3c_i2c.h:87
@ k_ra8_i3c_i2c_err_arb_lost
BST.ALF set.
Definition ra8_i3c_i2c.h:88
void(* ra8_i3c_i2c_complete_fn_t)(void *ctx, uint8_t err_mask)
Transfer-complete / error callback signature.
ra8_err_t ra8_i3c_i2c_abort(uint8_t channel)
Cancel any in-flight transaction and return the channel to idle.
internal_i3c_i2c_control_t
Implementation constants for the control-plane TU.
@ k_ra8_i3c_i2c_ctrl_poll_limit
Generic spin budget for status-flag polls.
@ k_ra8_i3c_i2c_ctrl_addr_shift
Shift count to convert a 7-bit address into the on-the-wire byte.
@ k_ra8_i3c_i2c_ctrl_addr_rw_write
R/W bit value for a write transaction (0 in LSB).
ra8_err_t ra8_i3c_i2c_get_errors(uint8_t channel, uint8_t *out_mask)
Read latched error flags from BST (AL / NACKDF / TODF).
static uint8_t internal_i3c_i2c_decode_errors(uint32_t bst)
Decode latched BST error bits into a k_ra8_i3c_i2c_err_* mask.
ra8_err_t ra8_i3c_i2c_attach_handler(uint8_t channel, ra8_i3c_i2c_complete_fn_t fn, void *ctx)
Attach a completion / error callback for the channel.
ra8_err_t ra8_i3c_i2c_clear_errors(uint8_t channel)
Clear latched error flags in BST.
void ra8_i3c_i2c_dispatch_eri(uint8_t channel)
Dispatch the bus-error IRQ source.
ra8_err_t ra8_i3c_i2c_scan(uint8_t channel, uint8_t target_7b, bool *out_acked)
Probe whether a 7-bit address ACKs.
Test-access surface for ra8_i3c_i2c internal helpers (MC/DC).
IIC_B (I3C-based I2C) register layout for the Renesas RA8D2.
@ k_ra8_i3c_i2c_channel_count
HUM Ch 40.1.1, p 2445.
static volatile r_i3c_i2c_regs_t * i3c_i2c_regs(uint8_t channel)
Get a pointer to the IIC_B / I3C channel channel.
@ k_ra8_i3c_i2c_msk_bie_nackdie
HUM 40.2 BIE.NACKDIE, p 2484.
@ k_ra8_i3c_i2c_msk_bie_tendie
HUM 40.2 BIE.TENDIE, p 2484.
@ k_ra8_i3c_i2c_msk_ntie_tdbeie0
HUM 40.2 NTIE.TDBEIE0, p 2488.
@ k_ra8_i3c_i2c_msk_bst_nackdf
HUM 40.2 BST.NACKDF, p 2482.
@ k_ra8_i3c_i2c_msk_bie_alie
HUM 40.2 BIE.ALIE, p 2484.
@ k_ra8_i3c_i2c_msk_bst_tendf
HUM 40.2 BST.TENDF, p 2482.
@ k_ra8_i3c_i2c_msk_bst_alf
HUM 40.2 BST.ALF, p 2482.
@ k_ra8_i3c_i2c_msk_bst_todf
HUM 40.2 BST.TODF, p 2482.
@ k_ra8_i3c_i2c_msk_ntie_rdbfie0
HUM 40.2 NTIE.RDBFIE0, p 2488.
@ k_ra8_i3c_i2c_msk_bie_todie
HUM 40.2 BIE.TODIE, p 2484.
Memory-mapped register block for one IIC_B / I3C channel.
volatile uint32_t BST
+0x1D0 Bus Status (HUM 40.2, p 2482).
volatile uint32_t NTIE
+0x1E8 Normal Xfer Interrupt Enable (HUM 40.2, p 2488).
volatile uint32_t BIE
+0x1D8 Bus Interrupt Enable (HUM 40.2, p 2484).