ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_i3c_i2c_peripheral.c
Go to the documentation of this file.
1
29
31
32#include <stdint.h>
33
34#include "ra8_attributes.h"
35#include "ra8_check.h"
36#include "ra8_err.h"
37#include "ra8_i3c_i2c_regs.h"
38#include "ra8_log.h"
39#include "ra8_mstp.h"
40#include "ra8_mstp_regs.h"
41
42static const char* s_tag = "IICBP";
43
52
64
84 uint32_t mask)
85{
86 for (uint32_t i = 0U; i < k_ra8_i3c_i2c_peripheral_spin_budget; ++i) {
87 if ((reg->NTST & mask) == mask) {
88 return k_ra8_ok;
89 }
90 }
92}
93
95{
96 RA8_CHECK_NULL_PTR(cfg, s_tag, "ra8_i3c_i2c_peripheral_open: cfg null");
97 volatile r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
98 if (reg == nullptr) {
99 ra8_log_error(s_tag, "ra8_i3c_i2c_peripheral_open: channel out of range");
101 }
104 }
105
106 /* HUM Ch 11.2.7 "MSTPCRB : Module Stop Control Register B", p 445 -- the R_I3C
107 * block is clock-gated OFF at reset; cancel its module-stop (MSTPB4) before the
108 * first responder register write or the peripheral never sees the bus. Omitting
109 * this ran clean in ra8_emulator yet was inert on silicon until #405 modelled the
110 * gate, which surfaced the miss here (the controller path already ungated). The
111 * writes are guarded so a failed ungate does not touch a still-gated block, and
112 * the outcome is returned from the single exit below (no extra return path). */
114 if (mst_err == k_ra8_ok) {
115 reg->RSTCTL = 0U;
119 ra8_log_info_val(s_tag, "ra8_i3c_i2c_peripheral_open ch", (uint32_t)channel);
120 }
121 return mst_err;
122}
123
125{
126 volatile r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
127 if (reg == nullptr) {
129 }
130 reg->BCTL = 0U;
131 reg->MSDVAD = 0U;
132 reg->SVCTL = 0U;
133 /* Release the I3C module-stop reference taken in peripheral_open (ref-counted;
134 * HUM Ch 11.2.7 "MSTPCRB : Module Stop Control Register B", p 445). */
136}
137
138ra8_err_t ra8_i3c_i2c_peripheral_send(uint8_t channel, const uint8_t* data, uint32_t len)
139{
140 volatile r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
141 if (reg == nullptr) {
143 }
144 if ((len > 0U) && (data == nullptr)) {
145 ra8_log_error(s_tag, "ra8_i3c_i2c_peripheral_send: data null");
146 return k_ra8_err_null_ptr;
147 }
148 for (uint32_t i = 0U; i < len; ++i) {
150 s_tag,
151 "ra8_i3c_i2c_peripheral_send: TDBEF0 wait");
152 reg->NTDTBP0 = (uint32_t)data[i];
153 }
154 return k_ra8_ok;
155}
156
157ra8_err_t ra8_i3c_i2c_peripheral_receive(uint8_t channel, uint8_t* buf, uint32_t len)
158{
159 volatile const r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
160 if (reg == nullptr) {
162 }
163 if ((len > 0U) && (buf == nullptr)) {
164 ra8_log_error(s_tag, "ra8_i3c_i2c_peripheral_receive: buf null");
165 return k_ra8_err_null_ptr;
166 }
167 for (uint32_t i = 0U; i < len; ++i) {
169 s_tag,
170 "ra8_i3c_i2c_peripheral_receive: RDBFF0 wait");
171 buf[i] = (uint8_t)(reg->NTDTBP0 & k_ra8_i3c_i2c_peripheral_byte_mask);
172 }
173 return k_ra8_ok;
174}
175
176ra8_err_t ra8_i3c_i2c_peripheral_status(uint8_t channel, uint8_t* out_mask)
177{
178 RA8_CHECK_NULL_PTR(out_mask, s_tag, "ra8_i3c_i2c_peripheral_status: out_mask null");
179 volatile const r_i3c_i2c_regs_t* reg = i3c_i2c_regs(channel);
180 if (reg == nullptr) {
182 }
183 const uint32_t ntst = reg->NTST;
184 const uint32_t bst = reg->BST;
185 uint8_t mask = 0U;
186 if ((ntst & k_ra8_i3c_i2c_peripheral_msk_ntst_rdbff0) != 0U) {
188 }
189 if ((ntst & k_ra8_i3c_i2c_peripheral_msk_ntst_tdbef0) != 0U) {
191 }
192 if ((bst & k_ra8_i3c_i2c_msk_bst_spcnddf) != 0U) {
194 }
195 if ((bst & k_ra8_i3c_i2c_msk_bst_nackdf) != 0U) {
197 }
198 if (reg->MSDVAD != 0U) {
200 }
201 *out_mask = mask;
202 return k_ra8_ok;
203}
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_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#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
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
static ra8_err_t internal_wait_ntst(volatile const r_i3c_i2c_regs_t *reg, uint32_t mask)
Bounded wait until mask bits set in NTST.
ra8_err_t ra8_i3c_i2c_peripheral_status(uint8_t channel, uint8_t *out_mask)
Read latched peripheral-side status mask.
ra8_i3c_i2c_peripheral_bits_t
Local register-bit positions / masks used by this driver.
@ k_ra8_i3c_i2c_peripheral_msk_ntst_rdbff0
NTST.RDBFF0.
@ k_ra8_i3c_i2c_peripheral_byte_mask
NTDTBP0 low-byte mask.
@ k_ra8_i3c_i2c_peripheral_msk_ntst_tdbef0
NTST.TDBEF0.
@ k_ra8_i3c_i2c_peripheral_msk_svctl_gcae
SVCTL.GCAE.
@ k_ra8_i3c_i2c_peripheral_msdvad_shift_dvad
Address shifted left 1.
ra8_err_t ra8_i3c_i2c_peripheral_send(uint8_t channel, const uint8_t *data, uint32_t len)
Push len bytes into NTDTBP0 in response to a controller-read.
ra8_err_t ra8_i3c_i2c_peripheral_open(uint8_t channel, const ra8_i3c_i2c_peripheral_cfg_t *cfg)
Open a channel as an IIC_B peripheral.
ra8_i3c_i2c_peripheral_internal_t
Internal tunables.
@ k_ra8_i3c_i2c_peripheral_spin_budget
Bounded poll iterations.
@ k_ra8_i3c_i2c_peripheral_max_addr_7b
7-bit address ceiling.
ra8_err_t ra8_i3c_i2c_peripheral_receive(uint8_t channel, uint8_t *buf, uint32_t len)
Drain len bytes from NTDTBP0 after a controller-write.
ra8_err_t ra8_i3c_i2c_peripheral_close(uint8_t channel)
Close the peripheral channel.
IIC_B (I3C in I2C-only mode) peripheral driver – mirrors FSP r_iic_b_peripheral.
@ k_ra8_i3c_i2c_peripheral_status_nack
BST.NACKDF set.
@ k_ra8_i3c_i2c_peripheral_status_stop
BST.SPCNDDF set.
@ k_ra8_i3c_i2c_peripheral_status_tx_empty
NTST.TDBEF0 set.
@ k_ra8_i3c_i2c_peripheral_status_rx_full
NTST.RDBFF0 set.
@ k_ra8_i3c_i2c_peripheral_status_aas
Address matched.
IIC_B (I3C-based I2C) register layout for the Renesas RA8D2.
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_bst_nackdf
HUM 40.2 BST.NACKDF, p 2482.
@ k_ra8_i3c_i2c_msk_bst_spcnddf
HUM 40.2 BST.SPCNDDF, p 2482.
@ k_ra8_i3c_i2c_msk_bctl_buse
HUM 40.2 BCTL.BUSE, p 2454.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info_val(tag, message, value)
RA8 log info val.
Definition ra8_log.h:366
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_enable(ra8_mstp_t id)
Reference-counted "ungate this peripheral" request.
Definition ra8_mstp.c:343
ra8_err_t ra8_mstp_disable(ra8_mstp_t id)
Reference-counted "gate this peripheral" request.
Definition ra8_mstp.c:382
Module Stop Control (MSTP) register layout for the Renesas RA8D2.
@ k_ra8_mstp_i3c
MSTPB4 I3C.
Memory-mapped register block for one IIC_B / I3C channel.
volatile uint32_t NTST
+0x1E0 Normal Transfer Status (HUM 40.2, p 2486).
volatile uint32_t BST
+0x1D0 Bus Status (HUM 40.2, p 2482).
volatile uint32_t BCTL
+0x014 Bus Control (HUM 40.2, p 2454).
volatile uint32_t MSDVAD
+0x018 Controller Device Address (HUM 40.2, p 2455).
volatile uint32_t RSTCTL
+0x020 Reset Control (HUM 40.2, p 2456).
volatile uint32_t SVCTL
+0x064 Peripheral Control (HUM 40.2, p 2461).
volatile uint32_t NTDTBP0
+0x158 Normal Tx/Rx Data Buffer 0 (HUM 40.2, p 2476).
Configuration descriptor for ra8_i3c_i2c_peripheral_open.
uint8_t general_call
Non-zero -> answer general-call address.
uint8_t peripheral_addr_7b
7-bit own address.