ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_cac.c
Go to the documentation of this file.
1
37
38#include <stdint.h>
39#include <stdio.h>
40
41#include "board_periph_block.h"
43
45typedef enum : uint64_t {
46 k_cac_base = 0x40202400UL,
47 k_cac_span = 0x10UL,
48 k_cac_off_cacr0 = 0x00UL,
49 k_cac_off_caicr = 0x03UL,
50 k_cac_off_castr = 0x04UL,
55
66
68typedef enum : uint32_t {
71
73typedef struct {
74 uint8_t cacr0;
75 uint8_t castr;
76 uint16_t caulvr;
77 uint16_t callvr;
78 uint16_t cacntbr;
79 uint32_t meas;
81
83
93{
94 /* Report the midpoint of the firmware's programmed window: in-band by
95 * construction, so FERRF stays clear and the measurement reads healthy. */
96 s_cac.cacntbr = (uint16_t)(((uint32_t)s_cac.callvr + (uint32_t)s_cac.caulvr) / 2U);
97 s_cac.castr = (uint8_t)k_cac_castr_mendf; /* MENDF set; FERRF / OVFF clear. */
98 s_cac.meas++;
99}
100
110{
111 s_cac = (cac_state_t){};
112}
113
127RA8_INTERNAL static uint64_t internal_cac_read(uc_engine* uc, uint64_t addr, unsigned size)
128{
129 (void)uc;
130 (void)size;
131 const uint64_t off = addr - (uint64_t)k_cac_base;
132 if (off == (uint64_t)k_cac_off_cacr0) {
133 return s_cac.cacr0;
134 }
135 if (off == (uint64_t)k_cac_off_castr) {
136 return s_cac.castr;
137 }
138 if (off == (uint64_t)k_cac_off_caulvr) {
139 return s_cac.caulvr;
140 }
141 if (off == (uint64_t)k_cac_off_callvr) {
142 return s_cac.callvr;
143 }
144 if (off == (uint64_t)k_cac_off_cacntbr) {
145 return s_cac.cacntbr;
146 }
147 return 0U;
148}
149
162RA8_INTERNAL static void
163internal_cac_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
164{
165 (void)uc;
166 (void)size;
167 const uint64_t off = addr - (uint64_t)k_cac_base;
168 if (off == (uint64_t)k_cac_off_cacr0) {
169 s_cac.cacr0 = (uint8_t)value;
170 if (((uint8_t)value & (uint8_t)k_cac_cacr0_cfme) != 0U) {
171 internal_cac_measure(); /* CFME=1 starts a measurement; it completes at once. */
172 }
173 } else if (off == (uint64_t)k_cac_off_caicr) {
174 /* CAICR clear bits are write-1-to-clear of the matching CASTR flags. */
175 if (((uint8_t)value & (uint8_t)k_cac_caicr_ferrfcl) != 0U) {
176 s_cac.castr &= (uint8_t)~(uint8_t)k_cac_castr_ferrf;
177 }
178 if (((uint8_t)value & (uint8_t)k_cac_caicr_mendfcl) != 0U) {
179 s_cac.castr &= (uint8_t)~(uint8_t)k_cac_castr_mendf;
180 }
181 if (((uint8_t)value & (uint8_t)k_cac_caicr_ovffcl) != 0U) {
182 s_cac.castr &= (uint8_t)~(uint8_t)k_cac_castr_ovff;
183 }
184 } else if (off == (uint64_t)k_cac_off_caulvr) {
185 s_cac.caulvr = (uint16_t)value;
186 } else if (off == (uint64_t)k_cac_off_callvr) {
187 s_cac.callvr = (uint16_t)value;
188 }
189}
190
200{
201 if (s_cac.meas == 0U) {
202 return; /* Untouched: stay quiet. */
203 }
204 (void)priv_emu_io_errf(" CAC : measurements=%u count=%u window=[%u,%u]\n",
205 s_cac.meas,
206 (unsigned)s_cac.cacntbr,
207 (unsigned)s_cac.callvr,
208 (unsigned)s_cac.caulvr);
209}
210
213 .base = (uint64_t)k_cac_base,
214 .span = (uint64_t)k_cac_span,
215 .order = (uint32_t)k_cac_block_order,
216 .read = internal_cac_read,
218 .tick = nullptr,
219 .reset = internal_cac_reset,
220 .report = internal_cac_report,
221 .name = "CAC",
222};
223
225[[gnu::constructor]] RA8_INTERNAL static void internal_cac_block_register(void)
226{
228}
Decentralized peripheral-block registry for the board emulator core.
void board_periph_register_block(const board_periph_block_t *block)
Register a peripheral block's descriptor with the core registry.
static cac_state_t s_cac
static RA8_INTERNAL uint64_t internal_cac_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the CAC window.
static RA8_INTERNAL void internal_cac_block_register(void)
Register the CAC block before main (host constructor).
cac_field_t
CACR0 / CASTR / CAICR field masks (ra8_cac.c).
@ k_cac_cacr0_cfme
CACR0.CFME measurement enable (bit 0).
@ k_cac_castr_ovff
CASTR.OVFF counter-overflow (bit 2).
@ k_cac_caicr_ferrfcl
CAICR.FERRFCL clear FERRF (bit 4).
@ k_cac_caicr_ovffcl
CAICR.OVFFCL clear OVFF (bit 6).
@ k_cac_castr_mendf
CASTR.MENDF measurement-end (bit 1).
@ k_cac_caicr_mendfcl
CAICR.MENDFCL clear MENDF (bit 5).
@ k_cac_castr_ferrf
CASTR.FERRF frequency-error (bit 0).
static RA8_INTERNAL void internal_cac_report(void)
End-of-run CAC section: measurements + last count and window.
cac_order_t
Per-tick order slot for the CAC block (relative order only).
@ k_cac_block_order
After the DRW block; report order.
static RA8_INTERNAL void internal_cac_measure(void)
Complete one measurement: latch an in-window count and set MENDF.
static const board_periph_block_t s_k_cac_block
CAC block descriptor (self-registered with the core).
static RA8_INTERNAL void internal_cac_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the CAC window.
static RA8_INTERNAL void internal_cac_reset(void)
Reset the CAC model to power-on state.
cac_geom_t
CAC block geometry (ra8_cac_regs.h, r_cac_regs_t).
@ k_cac_span
Covers CACR0..CACNTBR.
@ k_cac_off_cacntbr
CACNTBR counter buffer (16b).
@ k_cac_off_cacr0
CACR0 control 0 (CFME).
@ k_cac_off_castr
CASTR status (MENDF/FERRF/OVFF).
@ k_cac_base
CAC register base (HUM Ch 10.2).
@ k_cac_off_callvr
CALLVR lower limit (16b).
@ k_cac_off_caulvr
CAULVR upper limit (16b).
@ k_cac_off_caicr
CAICR interrupt / flag-clear.
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
-proof
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
A modelled peripheral block's self-description for the core registry.
CAC register state.
uint8_t cacr0
CACR0 shadow (CFME).
uint8_t castr
CASTR status flags.
uint32_t meas
Measurements completed (for report).
uint16_t callvr
Lower window limit.
uint16_t caulvr
Upper window limit.
uint16_t cacntbr
Latched edge count.