ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_cac.c
Go to the documentation of this file.
1
19
20#include "ra8_cac.h"
21
22#include <stdint.h>
23
24#include "ra8_attributes.h"
25#include "ra8_cac_regs.h"
26#include "ra8_check.h"
27#include "ra8_err.h"
28#include "ra8_hw_err.h"
29#include "ra8_log.h"
30#include "ra8_mstp.h"
31
32static const char* s_tag = "CAC";
33
40
55
64
83RA8_INTERNAL static inline void internal_cac_wait_cfme(volatile r_cac_regs_t* reg, uint8_t expect)
84{
85 for (uint32_t i = 0U; i < k_ra8_cac_cfme_settle_iters; i++) {
86#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
87 /* HUM Ch 10.2.1 "CACR0 : CAC Control Register 0" p 421 */
88 const bool settled = ra8_fake_mmio_poll(&reg->CACR0, i, reg->CACR0 == expect);
89#else
90 /* HUM Ch 10.2.1 "CACR0 : CAC Control Register 0" p 421 */
91 const bool settled = reg->CACR0 == expect;
92#endif
93 if (settled) {
94 return;
95 }
96 }
97}
98
99ra8_err_t ra8_cac_init(uint16_t upper, uint16_t lower)
100{
101 /* HUM Ch 11.2.8 "MSTPCRC : Module Stop Control Register C", p 446 */
103 RA8_RETURN_ON_ERROR(mst_err, s_tag, "cac_init: mstp enable");
104
105 volatile r_cac_regs_t* reg = ra8_cac();
106 /* HUM Ch 10.2.1 "CACR0 : CAC Control Register 0" p 421 -- CFME must be
107 * cleared before CACR1/CACR2/limits are programmed (FSP r_cac.c
108 * r_cac_hw_configure() does the same, then waits on CACR0 readback). */
109 reg->CACR0 = 0U;
110 internal_cac_wait_cfme(reg, 0U);
111 /* HUM Ch 10.2.4 "CAICR" p 424 */ /* clear all stale W1C status flags. */
113 /* HUM Ch 10.2.2 "CACR1 : CAC Control Register 1" p 422 */
114 reg->CACR1 = 0U;
115 /* HUM Ch 10.2.3 "CACR2 : CAC Control Register 2" p 423 */
116 reg->CACR2 = 0U;
117 /* HUM Ch 10.2.6 "CAULVR : CAC Upper Limit Value Register" p 426 */
118 reg->CAULVR = upper;
119 /* HUM Ch 10.2.7 "CALLVR : CAC Lower Limit Value Register" p 426 */
120 reg->CALLVR = lower;
121 ra8_log_info(s_tag, "cac_init");
122 return k_ra8_ok;
123}
124
125ra8_err_t ra8_cac_measure(uint16_t* out_count)
126{
127 RA8_CHECK_NULL_PTR(out_count, s_tag, "out_count must not be nullptr");
128 volatile r_cac_regs_t* reg = ra8_cac();
129
130 /* HUM Ch 10.2.1 "CACR0 : CAC Control Register 0" p 421 -- CFME=1 starts
131 * a measurement; CASTR.MENDF asserts when the window completes. FSP
132 * r_cac.c R_CAC_StartMeasurement() reads CACR0 back to confirm CFME
133 * propagation before relying on the result. */
134 const uint8_t cfme_set = (uint8_t)(1U << k_ra8_cacr0_cfme);
135 reg->CACR0 = cfme_set;
136 internal_cac_wait_cfme(reg, cfme_set);
137
138 for (uint32_t i = 0U; i < k_ra8_cac_poll_limit; i++) {
139 /* HUM Ch 10.2.5 "CASTR : CAC Status Register" p 425 */
140 if ((reg->CASTR & (uint8_t)(1U << k_ra8_castr_mendf)) != 0U) {
141 /* HUM Ch 10.2.8 "CACNTBR : CAC Counter Buffer Register" p 426 */
142 *out_count = reg->CACNTBR;
143 reg->CACR0 = 0U;
144 internal_cac_wait_cfme(reg, 0U);
145 return k_ra8_ok;
146 }
147 }
148 reg->CACR0 = 0U;
149 internal_cac_wait_cfme(reg, 0U);
151}
152
153/* =============================================================================
154 * full build-out
155 * =============================================================================
156 */
157
162typedef struct {
164 void* ctx;
166
168
170{
171 volatile r_cac_regs_t* reg = ra8_cac();
172 /* HUM Ch 10.2.1 "CACR0" p 421 -- stop measurement; FSP R_CAC_Close()
173 * confirms CFME cleared before powering down via MSTP. */
174 reg->CACR0 = 0U;
175 internal_cac_wait_cfme(reg, 0U);
176 reg->CACR1 = 0U;
177 reg->CACR2 = 0U;
178 reg->CAICR = 0U;
179 s_cac_state.fn = nullptr;
180 s_cac_state.ctx = nullptr;
182}
183
185{
186 RA8_CHECK_NULL_PTR(out_mask, s_tag, "out_mask must not be nullptr");
187 *out_mask = (uint8_t)(ra8_cac()->CASTR & k_ra8_cac_status_mask_all);
188 return k_ra8_ok;
189}
190
192{
193 volatile r_cac_regs_t* reg = ra8_cac();
194 /* HUM Ch 10.2.4 "CAICR : CAC Interrupt Control Register" p 424 -- the
195 * write-1-to-clear bits are FERRFCL=bit4, MENDFCL=bit5, OVFFCL=bit6,
196 * which sit `k_ra8_cac_castr_to_caicr_shift` (= 4) bits above the
197 * matching CASTR FERRF/MENDF/OVFF flags. Cross-verified against FSP
198 * r_cac.c CAC_PRV_CAICR_FERRFCL_OFFSET=4 / MENDFCL=5 / OVFFCL=6. */
199 const uint8_t castr_bits = (uint8_t)(mask & k_ra8_cac_status_mask_all);
200 const uint8_t caicr_clr = (uint8_t)(castr_bits << (uint8_t)k_ra8_cac_castr_to_caicr_shift);
201 reg->CAICR = caicr_clr;
202 return k_ra8_ok;
203}
204
206{
207 s_cac_state.fn = fn;
208 s_cac_state.ctx = ctx;
209 return k_ra8_ok;
210}
211
213{
214 volatile r_cac_regs_t* reg = ra8_cac();
215 const uint8_t mask = (uint8_t)(reg->CASTR & k_ra8_cac_status_mask_all);
216 /* HUM Ch 10.2.4 "CAICR" p 424 -- write 1 to FERRFCL/MENDFCL/OVFFCL
217 * (bits 4/5/6) to clear the matching CASTR flag, mirroring the FSP
218 * ISR pattern `R_CAC->CAICR |= CAC_PRV_CAICR_*FCL_MASK`. */
219 reg->CAICR = (uint8_t)(mask << (uint8_t)k_ra8_cac_castr_to_caicr_shift);
220 const ra8_cac_event_fn_t fn = s_cac_state.fn;
221 void* const ctx = s_cac_state.ctx;
222 if (fn != nullptr) {
223 fn(ctx, mask);
224 }
225}
226
228{
229 volatile r_cac_regs_t* reg = ra8_cac();
230 /* HUM Ch 10.2.1 "CACR0" p 421 */ /* stop measurement before MSTP gate. */
231 reg->CACR0 = 0U;
232 internal_cac_wait_cfme(reg, 0U);
234}
235
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).
ra8_cac_bit_t
Definition ra8_cac.c:34
@ k_ra8_castr_mendf
Measurement end flag (CASTR bit 1).
Definition ra8_cac.c:37
@ k_ra8_cacr0_cfme
CFME: clock frequency measurement en.
Definition ra8_cac.c:35
@ k_ra8_castr_ovff
Counter overflow flag (CASTR bit 2).
Definition ra8_cac.c:38
@ k_ra8_castr_ferrf
Frequency error flag (CASTR bit 0).
Definition ra8_cac.c:36
ra8_err_t ra8_cac_init(uint16_t upper, uint16_t lower)
Programme CAC with upper + lower bounds on measured cycles.
Definition ra8_cac.c:99
ra8_cac_bits_w43_t
Combined CASTR status mask for FERRF | MENDF | OVFF.
Definition ra8_cac.c:60
@ k_ra8_cac_status_mask_all
RA8 cac status mask all.
Definition ra8_cac.c:61
static void internal_cac_wait_cfme(volatile r_cac_regs_t *reg, uint8_t expect)
Bounded busy-spin until CACR0 reads back expect.
Definition ra8_cac.c:83
ra8_err_t ra8_cac_exit_stop(void)
Exit MSTP-gated stop.
Definition ra8_cac.c:236
static ra8_cac_state_t s_cac_state
Definition ra8_cac.c:167
ra8_err_t ra8_cac_deinit(void)
Tear down the CAC (disable + MSTP release).
Definition ra8_cac.c:169
ra8_err_t ra8_cac_clear_status(uint8_t mask)
Clear the CASTR flag bits via CAICR.
Definition ra8_cac.c:191
void ra8_cac_dispatch(void)
Dispatch CAC events – snapshot + fire callback.
Definition ra8_cac.c:212
ra8_err_t ra8_cac_attach_handler(ra8_cac_event_fn_t fn, void *ctx)
Attach a callback for CAC events.
Definition ra8_cac.c:205
ra8_cac_misc_t
Miscellaneous shifts and bounded-spin budgets.
Definition ra8_cac.c:50
@ k_ra8_cac_castr_to_caicr_shift
CASTR -> CAICR.
Definition ra8_cac.c:51
@ k_ra8_cac_poll_limit
Bounded MENDF poll budget.
Definition ra8_cac.c:53
@ k_ra8_cac_cfme_settle_iters
Bounded settle on CACR0 write-back.
Definition ra8_cac.c:52
ra8_err_t ra8_cac_measure(uint16_t *out_count)
Kick off a CAC measurement and wait for completion.
Definition ra8_cac.c:125
ra8_err_t ra8_cac_get_status(uint8_t *out_mask)
Read the CASTR flag bits.
Definition ra8_cac.c:184
ra8_err_t ra8_cac_enter_stop(void)
Put CAC into MSTP-gated stop.
Definition ra8_cac.c:227
Clock Accuracy Check driver.
void(* ra8_cac_event_fn_t)(void *ctx, uint8_t status_mask)
CAC event callback.
Definition ra8_cac.h:68
@ k_ra8_cac_status_ferrf
Frequency error (CASTR bit 0).
Definition ra8_cac.h:59
@ k_ra8_cac_status_mendf
Measurement end (CASTR bit 1).
Definition ra8_cac.h:60
@ k_ra8_cac_status_ovff
Counter overflow (CASTR bit 2).
Definition ra8_cac.h:61
Clock Accuracy Check (CAC) register layout for the Renesas RA8D2.
static volatile r_cac_regs_t * ra8_cac(void)
Get pointer to the CAC block.
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_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.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
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
@ k_ra8_mstp_cac
MSTPC0 CAC.
volatile uint16_t CALLVR
+0x08 Lower Limit.
volatile uint8_t CACR0
+0x00 Control 0.
volatile uint16_t CAULVR
+0x06 Upper Limit.
volatile uint8_t CAICR
+0x03 Int Control.
volatile uint16_t CACNTBR
+0x0A Counter Buf.
volatile uint8_t CASTR
+0x04 Status.
volatile uint8_t CACR2
+0x02 Control 2.
volatile uint8_t CACR1
+0x01 Control 1.
Driver-wide runtime state.
Definition ra8_cac.c:162
void * ctx
Ctx.
Definition ra8_cac.c:164
ra8_cac_event_fn_t fn
Fn.
Definition ra8_cac.c:163