ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_crc.c
Go to the documentation of this file.
1
27
28#include "ra8_crc.h"
29
30#include <stdint.h>
31
32#include "ra8_attributes.h"
33#include "ra8_check.h"
34#include "ra8_crc_regs.h"
35#include "ra8_err.h"
36#include "ra8_log.h"
37#include "ra8_mstp.h"
38
39static const char* s_tag = "CRC";
40
42typedef enum : uint8_t {
45
56
75{
76 return (poly == k_ra8_crc_poly_32_ieee802_3) || (poly == k_ra8_crc_poly_32c_rev);
77}
78
93typedef enum : uint32_t {
94 k_ra8_crc_32bit_seed = 0xFFFFFFFFUL,
96
118RA8_INTERNAL static inline void internal_crc_feed_words(const uint8_t* data, uint32_t len)
119{
120 volatile r_crc_regs_t* reg = ra8_crc();
121 const uint32_t word_count = len >> 2U;
122 for (uint32_t i = 0U; i < word_count; i++) {
123 const uint32_t base = i << 2U;
124 const uint32_t packed = (uint32_t)data[base + 0U] | ((uint32_t)data[base + 1U] << 8U) |
125 ((uint32_t)data[base + 2U] << 16U) |
126 ((uint32_t)data[base + 3U] << k_crc_shift_byte3);
127 /* HUM Ch 48.2.3 "CRCDIR : CRC Data Input Register" p 3182 */
128 reg->CRCDIR = packed;
129 }
130}
131
149RA8_INTERNAL static inline void internal_crc_feed_bytes(const uint8_t* data, uint32_t len)
150{
151 volatile r_crc_regs_t* reg = ra8_crc();
152 for (uint32_t i = 0U; i < len; i++) {
153 /* HUM Ch 48.2.3 "CRCDIR_BY : CRC Data Input Register" p 3182 */
154 reg->CRCDIR_BY = data[i];
155 }
156}
157
159{
160 /* HUM Ch 11.2.8 "MSTPCRC : Module Stop Control Register C", p 446 */
162 /* GCOVR_EXCL_BR_START -- MSTP HW readback */
163 RA8_RETURN_ON_ERROR(mst_err, s_tag, "crc_init: mstp enable");
164 /* GCOVR_EXCL_BR_STOP */
165
166 volatile r_crc_regs_t* reg = ra8_crc();
167 const uint8_t crccr0 = (uint8_t)((uint8_t)poly | k_ra8_crccr0_dorclr);
168 /* HUM Ch 48.2.1 "CRCCR0 : CRC Control Register 0" p 3181.
169 * Mirror FSP `R_CRC_Open`: write GPS plus DORCLR=1 in a single
170 * store so any stale CRCDOR value from a prior session is cleared
171 * atomically with the polynomial select. LMS defaults to 0
172 * (LSB-first); use ra8_crc_set_bit_order() to change. */
173 reg->CRCCR0 = crccr0;
174 /* HUM Ch 48.2.2 "CRCCR1 : CRC Control Register 1" p 3182 */ /* snoop off. */
175 reg->CRCCR1 = 0U;
176 ra8_log_info_val(s_tag, "crc_init poly", (uint32_t)poly);
177 return k_ra8_ok;
178}
179
181{
182 volatile r_crc_regs_t* reg = ra8_crc();
183 /* HUM Ch 48.2.1 "CRCCR0 : CRC Control Register 0" p 3181 -- DORCLR
184 * is a write-only bit that clears CRCDOR and auto-clears itself on
185 * the real chip. We read-modify-write so the GPS/LMS bits are
186 * preserved. */
187 reg->CRCCR0 = (uint8_t)(reg->CRCCR0 | k_ra8_crccr0_dorclr);
188}
189
190ra8_err_t ra8_crc_compute(const uint8_t* data, uint32_t len, uint32_t* out_crc)
191{
192 RA8_CHECK_NULL_PTR(data, s_tag, "data must not be nullptr");
193 RA8_CHECK_NULL_PTR(out_crc, s_tag, "out_crc must not be nullptr");
194
195 volatile r_crc_regs_t* reg = ra8_crc();
196 /* HUM Ch 48.2.1 "CRCCR0 : CRC Control Register 0" p 3181 -- GPS lives
197 * in the low 3 bits of CRCCR0. */
199 const bool is_32_bit = internal_ra8_crc_is_32bit_poly(poly);
200
201 /* HUM Ch 48.2.4 "CRCDOR : CRC Data Output Register" p 3182 documents
202 * CRCDOR as a 32-bit read/write register; "Because its initial value
203 * is 0x00000000, rewrite the CRCDOR ... register to perform the
204 * calculations using a value other than the initial value." Standard
205 * CRC-32 / CRC-32C use init = 0xFFFFFFFF and xor-out = 0xFFFFFFFF; the
206 * hardware applies neither, so the driver pre-seeds CRCDOR and XORs
207 * the readback on the way out for the 32-bit polynomials. CRC-8 / 16
208 * / CCITT keep the chip's natural init = 0 (HUM example p 3185 shows
209 * the same flow). */
210 if (is_32_bit) {
211 /* HUM Ch 48.2.4 "CRCDOR : CRC Data Output Register" p 3182 -- pre-seed
212 * CRCDOR with the CRC-32 init value before clocking data through (see
213 * the decision comment above for the init / xor-out rationale). */
214 reg->CRCDOR = (uint32_t)k_ra8_crc_32bit_seed;
215 internal_crc_feed_words(data, len);
216 /* HUM Ch 48.2.4 "CRCDOR : CRC Data Output Register" p 3182 -- read the
217 * running result back and apply the CRC-32 xor-out. */
218 *out_crc = reg->CRCDOR ^ (uint32_t)k_ra8_crc_32bit_seed;
219 return k_ra8_ok;
220 }
221
222 internal_crc_feed_bytes(data, len);
223 /* HUM Ch 48.2.4 p 3182 -- the full 32-bit register holds the running
224 * result; lower bits mirror `CRCDOR_HA` / `CRCDOR_BY` aliases.
225 * Reading the wide register matches FSP `crc_calculated_value_get`
226 * and is a superset of the narrower aliases. */
227 *out_crc = reg->CRCDOR;
228 return k_ra8_ok;
229}
230
231/* =============================================================================
232 * full build-out
233 * =============================================================================
234 */
235
237{
238 volatile r_crc_regs_t* reg = ra8_crc();
239 /* HUM Ch 48.2.1 "CRCCR0 : CRC Control Register 0" p 3181 */
240 reg->CRCCR0 = 0U;
241 /* HUM Ch 48.2.2 "CRCCR1 : CRC Control Register 1" p 3182 */
242 reg->CRCCR1 = 0U;
244}
245
247{
248 volatile r_crc_regs_t* reg = ra8_crc();
249 /* HUM Ch 48.2.1 "CRCCR0 : CRC Control Register 0" p 3181 -- pulse
250 * DORCLR alongside the new GPS so the running result doesn't bleed
251 * into the next polynomial's calculation (mirrors FSP Open). */
252 reg->CRCCR0 = (uint8_t)((uint8_t)poly | k_ra8_crccr0_dorclr);
253 return k_ra8_ok;
254}
255
257{
258 RA8_CHECK_NULL_PTR(out_poly, s_tag, "out_poly must not be nullptr");
259 /* HUM Ch 48.2.1 "CRCCR0 : CRC Control Register 0" p 3181 */
260 *out_poly = ra8_crc()->CRCCR0;
261 return k_ra8_ok;
262}
263
265{
266 /* HUM Ch 48.2.1 "CRCCR0 : CRC Control Register 0" p 3181 */
267 ra8_crc()->CRCCR0 = 0U;
269}
270
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
static void internal_crc_feed_bytes(const uint8_t *data, uint32_t len)
Feed len bytes through the calculator via the 8-bit alias.
Definition ra8_crc.c:149
static bool internal_ra8_crc_is_32bit_poly(ra8_crc_poly_t poly)
Determine if a polynomial uses 32-bit data input.
Definition ra8_crc.c:74
ra8_err_t ra8_crc_exit_stop(void)
Exit MSTP-gated stop.
Definition ra8_crc.c:271
ra8_err_t ra8_crc_init(ra8_crc_poly_t poly)
Configure the CRC block for a given polynomial.
Definition ra8_crc.c:158
ra8_crccr0_bit_t
Bit positions inside CRCCR0 (HUM Ch 48.2.1 p 3181).
Definition ra8_crc.c:50
@ k_ra8_crccr0_dorclr_shift
CRCCR0.DORCLR bit position.
Definition ra8_crc.c:52
@ k_ra8_crccr0_gps_mask
CRCCR0.GPS[2:0] mask.
Definition ra8_crc.c:54
@ k_ra8_crccr0_dorclr
CRCCR0.DORCLR mask (write-only).
Definition ra8_crc.c:53
@ k_ra8_crccr0_lms_shift
CRCCR0.LMS bit position.
Definition ra8_crc.c:51
ra8_err_t ra8_crc_compute(const uint8_t *data, uint32_t len, uint32_t *out_crc)
Compute a CRC over a byte buffer.
Definition ra8_crc.c:190
crc_shift_t
Byte-3 shift for little-endian word assembly.
Definition ra8_crc.c:42
@ k_crc_shift_byte3
CRC shift byte3.
Definition ra8_crc.c:43
void ra8_crc_reset(void)
Clear the running CRC state.
Definition ra8_crc.c:180
static void internal_crc_feed_words(const uint8_t *data, uint32_t len)
Feed len bytes through the calculator as packed 32-bit words.
Definition ra8_crc.c:118
ra8_err_t ra8_crc_enter_stop(void)
Put CRC into MSTP-gated stop.
Definition ra8_crc.c:264
ra8_err_t ra8_crc_deinit(void)
Tear down the CRC block (disable + MSTP release).
Definition ra8_crc.c:236
ra8_err_t ra8_crc_get_status(uint8_t *out_poly)
Read the current polynomial selection (CRCCR0.GPS).
Definition ra8_crc.c:256
ra8_err_t ra8_crc_set_poly(ra8_crc_poly_t poly)
Change the CRC polynomial at runtime without a reset.
Definition ra8_crc.c:246
ra8_crc_seed_t
Standard init / xor-out value for IEEE-style 32-bit CRCs.
Definition ra8_crc.c:93
@ k_ra8_crc_32bit_seed
IEEE-802.3 / Castagnoli init = xor-out.
Definition ra8_crc.c:94
CRC hardware calculator driver header.
CRC calculator register layout for the Renesas RA8D2.
ra8_crc_poly_t
Polynomial selection values written to CRCCR0.GPS[2:0].
@ k_ra8_crc_poly_32_ieee802_3
GPS=100 CRC-32 (IEEE 802.3).
@ k_ra8_crc_poly_32c_rev
GPS=101 CRC-32C (Castagnoli, reflected).
static volatile r_crc_regs_t * ra8_crc(void)
Get pointer to the CRC peripheral register block.
Error Code Definitions for ra8-firmware.
@ 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
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info_val(tag, message, value)
RA8 log info val.
Definition ra8_log.h:366
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_crc
MSTPC1 CRC.
CRC peripheral register block.
volatile uint32_t CRCDOR
+0x08 Output Data (32-bit, CRC-32/32C).
volatile uint8_t CRCCR0
+0x00 Control Register 0 (GPS/LMS/DORCLR).
volatile uint8_t CRCDIR_BY
+0x04 Input Data (8-bit alias).
volatile uint32_t CRCDIR
+0x04 Input Data (32-bit, CRC-32/32C).
volatile uint8_t CRCCR1
+0x01 Control Register 1 (CRCSWR/CRCSEN).