ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_crc.c
Go to the documentation of this file.
1
30
31#include <stdint.h>
32#include <stdio.h>
33
34#include "board_periph_block.h"
36
38typedef enum : uint32_t {
39 k_u32_all = 0xFFFFFFFFU,
40 k_u16_mask = 0xFFFFU,
41 k_byte_mask = 0xFFU,
42} crc_lit_t;
43
45typedef enum : uint64_t {
46 k_crc_base = 0x40310000UL,
47 k_crc_span = 0x20UL,
48 k_crc_off_cr0 = 0x00UL,
49 k_crc_off_cr1 = 0x01UL,
50 k_crc_off_dir = 0x04UL,
51 k_crc_off_dor = 0x08UL,
52} crc_map_t;
53
55typedef enum : uint32_t {
57 k_crc_dorclr = 0x80U,
59
61typedef enum : uint32_t {
67} crc_gps_t;
68
70typedef enum : uint32_t {
71 k_crc_poly_16_refl = 0x0000A001U,
72 k_crc_poly_32_refl = 0xEDB88320U,
73 k_crc_poly_32c_refl = 0x82F63B78U,
75
77typedef enum : uint32_t {
78 k_crc_poly_8_fwd = 0x00000007U,
79 k_crc_poly_ccitt_fwd = 0x00001021U,
81
83typedef enum : uint32_t {
86
88typedef struct {
89 uint8_t cr0;
90 uint8_t cr1;
91 uint32_t dor;
92 uint32_t bytes;
94
96
110RA8_INTERNAL static uint32_t internal_crc_step_reflected(uint32_t crc, uint8_t byte, uint32_t poly)
111{
112 crc ^= (uint32_t)byte;
113 for (uint32_t i = 0U; i < 8U; i++) {
114 crc = ((crc & 1U) != 0U) ? ((crc >> 1) ^ poly) : (crc >> 1);
115 }
116 return crc;
117}
118
133RA8_INTERNAL static uint32_t
134internal_crc_step_forward(uint32_t crc, uint8_t byte, uint32_t poly, uint32_t width)
135{
136 const uint32_t top = 1U << (width - 1U);
137 const uint32_t msk = (width >= 32U) ? (uint32_t)k_u32_all : ((1U << width) - 1U);
138 crc ^= (uint32_t)byte << (width - 8U);
139 for (uint32_t i = 0U; i < 8U; i++) {
140 const bool set = (crc & top) != 0U;
141 crc = (crc << 1) & msk;
142 if (set) {
143 crc ^= poly;
144 }
145 }
146 return crc & msk;
147}
148
158RA8_INTERNAL static void internal_crc_fold_byte(uint8_t byte)
159{
160 switch ((uint32_t)(s_crc.cr0 & (uint8_t)k_crc_gps_mask)) {
161 case (uint32_t)k_crc_gps_8:
162 s_crc.dor = internal_crc_step_forward(s_crc.dor, byte, (uint32_t)k_crc_poly_8_fwd, 8U);
163 break;
164 case (uint32_t)k_crc_gps_16:
165 s_crc.dor = internal_crc_step_reflected(s_crc.dor, byte, (uint32_t)k_crc_poly_16_refl);
166 break;
167 case (uint32_t)k_crc_gps_ccitt:
168 s_crc.dor = internal_crc_step_forward(s_crc.dor, byte, (uint32_t)k_crc_poly_ccitt_fwd, 16U);
169 break;
170 case (uint32_t)k_crc_gps_32:
171 s_crc.dor = internal_crc_step_reflected(s_crc.dor, byte, (uint32_t)k_crc_poly_32_refl);
172 break;
173 case (uint32_t)k_crc_gps_32c:
175 break;
176 default:
177 break; /* GPS=0: no calculation. */
178 }
179 s_crc.bytes++;
180}
181
191{
192 s_crc.cr0 = 0U;
193 s_crc.cr1 = 0U;
194 s_crc.dor = 0U;
195 s_crc.bytes = 0U;
196}
197
211RA8_INTERNAL static uint64_t internal_crc_read(uc_engine* uc, uint64_t addr, unsigned size)
212{
213 (void)uc;
214 (void)size;
215 const uint64_t off = addr - (uint64_t)k_crc_base;
216 if (off == (uint64_t)k_crc_off_cr0) {
217 return s_crc.cr0;
218 }
219 if (off == (uint64_t)k_crc_off_cr1) {
220 return s_crc.cr1;
221 }
222 if ((off >= (uint64_t)k_crc_off_dor) && (off < (uint64_t)k_crc_off_dor + 4UL)) {
223 /* CRCDOR and its 16/8-bit aliases share +0x08; serve the low bytes. */
224 const uint32_t shift = (uint32_t)(off - (uint64_t)k_crc_off_dor) * 8U;
225 return (uint64_t)(s_crc.dor >> shift);
226 }
227 return 0U;
228}
229
242RA8_INTERNAL static void
243internal_crc_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
244{
245 (void)uc;
246 const uint64_t off = addr - (uint64_t)k_crc_base;
247 if (off == (uint64_t)k_crc_off_cr0) {
248 s_crc.cr0 = (uint8_t)value;
249 if (((uint8_t)value & (uint8_t)k_crc_dorclr) != 0U) {
250 s_crc.dor = 0U; /* DORCLR clears the running remainder. */
251 }
252 return;
253 }
254 if (off == (uint64_t)k_crc_off_cr1) {
255 s_crc.cr1 = (uint8_t)value;
256 return;
257 }
258 if (off == (uint64_t)k_crc_off_dir) {
259 /* Fold each byte of the access LSB-first: a 32-bit word feed (CRC-32/32C)
260 * delivers four bytes in the order ra8_crc's word packing produces, an
261 * 8-bit feed (CRC-8/16/CCITT) delivers one. */
262 unsigned n = size;
263 if (size > 4U) {
264 n = 4U;
265 } else if (size == 0U) {
266 n = 1U;
267 }
268 for (unsigned i = 0U; i < n; i++) {
269 internal_crc_fold_byte((uint8_t)((value >> (8U * i)) & (uint32_t)k_byte_mask));
270 }
271 return;
272 }
273 if ((off >= (uint64_t)k_crc_off_dor) && (off < (uint64_t)k_crc_off_dor + 4UL)) {
274 /* Seed / overwrite CRCDOR (driver pre-seeds 0xFFFFFFFF for CRC-32/32C). */
275 if (size >= 4U) {
276 s_crc.dor = (uint32_t)value;
277 } else {
278 const uint32_t shift = (uint32_t)(off - (uint64_t)k_crc_off_dor) * 8U;
279 const uint32_t mask = ((size == 2U) ? (uint32_t)k_u16_mask : (uint32_t)k_byte_mask) << shift;
280 s_crc.dor = (s_crc.dor & ~mask) | (((uint32_t)value << shift) & mask);
281 }
282 }
283}
284
294{
295 if (s_crc.bytes == 0U) {
296 return; /* Untouched: stay quiet. */
297 }
298 (void)priv_emu_io_errf(" CRC : GPS=%u CRCDOR=0x%08X bytes=%u\n",
299 (unsigned)(s_crc.cr0 & (uint8_t)k_crc_gps_mask),
300 s_crc.dor,
301 s_crc.bytes);
302}
303
306 .base = (uint32_t)k_crc_base,
307 .span = (uint32_t)k_crc_span,
308 .order = (uint32_t)k_crc_block_order,
309 .read = internal_crc_read,
311 .tick = nullptr,
312 .reset = internal_crc_reset,
313 .report = internal_crc_report,
314 .name = "CRC",
315};
316
318[[gnu::constructor]] RA8_INTERNAL static void internal_crc_block_register(void)
319{
321}
@ k_u16_mask
16-bit field.
Definition board_net.c:70
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.
crc_gps_t
GPS polynomial encodings (CRCCR0.GPS).
@ k_crc_gps_ccitt
CRC-CCITT (X^16+X^12+X^5+1).
@ k_crc_gps_16
CRC-16 (X^16+X^15+X^2+1).
@ k_crc_gps_8
CRC-8 (X^8+X^2+X+1).
@ k_crc_gps_32c
CRC-32C (Castagnoli).
@ k_crc_gps_32
CRC-32 (IEEE 802.3).
static RA8_INTERNAL void internal_crc_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the CRC window.
static RA8_INTERNAL void internal_crc_block_register(void)
Register the CRC block before main (host constructor).
static RA8_INTERNAL uint32_t internal_crc_step_reflected(uint32_t crc, uint8_t byte, uint32_t poly)
Fold one byte into a reflected (LSB-first) CRC of any width.
crc_map_t
CRC block geometry (ra8_crc_regs.h).
@ k_crc_off_dor
CRCDOR result (32b).
@ k_crc_off_cr0
CRCCR0 (GPS/LMS/DORCLR), 8b.
@ k_crc_base
CRC base (HUM Ch 48).
@ k_crc_span
Register window.
@ k_crc_off_dir
CRCDIR / CRCDIR_BY data in.
@ k_crc_off_cr1
CRCCR1 (snoop), 8b.
static RA8_INTERNAL void internal_crc_fold_byte(uint8_t byte)
Fold one input byte into CRCDOR using the CRCCR0.GPS polynomial.
static RA8_INTERNAL void internal_crc_report(void)
End-of-run CRC section: last result + bytes folded.
static RA8_INTERNAL void internal_crc_reset(void)
Reset the CRC unit to power-on state.
static RA8_INTERNAL uint64_t internal_crc_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the CRC window.
crc_poly_refl_t
Reflected (LSB-first) polynomials for the reflected GPS modes.
@ k_crc_poly_16_refl
Reflected 0x8005.
@ k_crc_poly_32c_refl
Reflected 0x1EDC6F41.
@ k_crc_poly_32_refl
Reflected 0x04C11DB7.
crc_order_t
Per-tick order slot for the CRC block (relative order only).
@ k_crc_block_order
After the existing blocks; report order.
crc_lit_t
Bit-width masks for the CRC unit model.
@ k_u32_all
32-bit all-ones.
static const board_periph_block_t s_k_crc_block
CRC block descriptor (self-registered with the core).
crc_poly_fwd_t
MSB-first polynomials for the non-reflected GPS modes.
@ k_crc_poly_ccitt_fwd
CRC-CCITT.
@ k_crc_poly_8_fwd
CRC-8 X^8+X^2+X+1.
crc_cr0_field_t
CRCCR0 fields (ra8_crc_regs.h).
@ k_crc_gps_mask
GPS[2:0] polynomial select.
@ k_crc_dorclr
DORCLR: clear CRCDOR (bit 7).
static crc_state_t s_crc
static RA8_INTERNAL uint32_t internal_crc_step_forward(uint32_t crc, uint8_t byte, uint32_t poly, uint32_t width)
Fold one byte into an MSB-first CRC of width bits.
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).
@ k_byte_mask
Byte mask.
A modelled peripheral block's self-description for the core registry.
CRC register state.
uint32_t dor
CRCDOR running remainder.
uint8_t cr0
CRCCR0 shadow (GPS/LMS/DORCLR).
uint8_t cr1
CRCCR1 shadow.
uint32_t bytes
Bytes folded since reset.