ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_canfd_frame.c
Go to the documentation of this file.
1
35
36#include <stdint.h>
37
38#include "ra8_attributes.h"
39#include "ra8_canfd.h"
40#include "ra8_canfd_regs.h"
41#include "ra8_check.h"
42#include "ra8_err.h"
43#include "ra8_hw_err.h"
44
45static const char* s_tag = "CANFD";
46
58typedef enum : uint32_t {
61
70
90{
91 if (frame->dlc > k_ra8_canfd_dlc_max) {
93 }
94 if (frame->is_extended == 0U) {
95 if ((frame->id & ~k_ra8_canfd_id_std_mask) != 0U) {
97 }
98 } else {
99 if ((frame->id & ~k_ra8_canfd_id_ext_mask) != 0U) {
101 }
102 }
103 if ((frame->is_brs != 0U) && (frame->is_fd == 0U)) {
105 }
106 return k_ra8_ok;
107}
108
125static void internal_write_tx_data(volatile r_canfd_t* reg, const ra8_canfd_frame_t* frame)
126{
127 for (uint8_t b = 0U; b < k_ra8_canfd_data_bytes_max; b++) {
128 reg->CFDTM[k_ra8_canfd_tx_mb_default].DF[b] = frame->data[b];
129 }
130}
131
150static uint32_t internal_tx_id(const ra8_canfd_frame_t* frame)
151{
152 const uint32_t masked = (frame->is_extended != 0U) ? (frame->id & k_ra8_canfd_id_ext_mask)
153 : (frame->id & k_ra8_canfd_id_std_mask);
154 return (frame->is_extended != 0U) ? (masked | k_ra8_canfd_id_ide) : masked;
155}
156
176static uint32_t internal_tx_fdctr(const ra8_canfd_frame_t* frame)
177{
178 uint32_t w = 0U;
179 if (frame->is_fd != 0U) {
181 }
182 if (frame->is_brs != 0U) {
184 }
185 return w;
186}
187
216static void internal_wait_tx_complete(volatile r_canfd_t* reg)
217{
218 enum : uint8_t { k_ra8_tmsts_tmtrf_done = 0x04U };
219 for (uint32_t i = 0U; i < k_ra8_canfd_tx_spin; i++) {
220#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
221 if (ra8_fake_mmio_wait_eval(
223 i,
224 ((reg->CFDTMSTS[k_ra8_canfd_tx_mb_default] & k_ra8_tmsts_tmtrf_done) != 0U))) {
225 break;
226 }
227#else
228 if ((reg->CFDTMSTS[k_ra8_canfd_tx_mb_default] & k_ra8_tmsts_tmtrf_done) != 0U) {
229 break;
230 }
231#endif
232 }
233}
234
235ra8_err_t ra8_canfd_transmit(uint8_t channel, const ra8_canfd_frame_t* frame)
236{
237 volatile r_canfd_t* reg = ra8_canfd(channel);
238 RA8_CHECK_NULL_PTR(reg, s_tag, "channel out of range");
239 RA8_CHECK_NULL_PTR(frame, s_tag, "frame must not be nullptr");
240
241 const ra8_err_t v = internal_validate_frame(frame);
242 if (v != k_ra8_ok) {
243 return v;
244 }
245
246 /* Clear the previous transmission's TMTRF before asserting TXREQ:
247 * HUM Ch 41 "CFDTMSTSj.TMTRF" p ~2756 says TMTR is only honored when
248 * TMTRF is 00b. After the first successful TX the chip leaves
249 * TMTRF=10b ("transmission successful") and silently drops every
250 * subsequent TXREQ -- the symptom is the first round-trip working
251 * and every later one returning no_data. */
253
254 /* HUM Ch 41 p 2806 "CFDTMID/CFDTMPTR/CFDTMFDCTR/CFDTMDF" +
255 * FSP r_canfd.c line ~668..684. */
258 << (uint32_t)k_ra8_canfd_ptr_shift_dlc;
260 internal_write_tx_data(reg, frame);
261
262 /* HUM Ch 41 p 2810 "CFDTMC" -- single-byte transmit-request register.
263 * FSP r_canfd.c line ~724: `p_reg->CFDTMC[idx] = 1`. */
265
267 return k_ra8_ok;
268}
269
286static void internal_read_rx_data(volatile r_canfd_t* reg, ra8_canfd_frame_t* out)
287{
288 for (uint8_t b = 0U; b < k_ra8_canfd_data_bytes_max; b++) {
289 out->data[b] = reg->CFDRF[k_ra8_canfd_rx_fifo_default].DF[b];
290 }
291}
292
311static void internal_decode_rx_header(uint32_t id_word,
312 uint32_t ptr_word,
313 uint32_t fdsts_word,
315{
316 const uint8_t is_ext = (uint8_t)(((id_word & k_ra8_canfd_id_ide) != 0U) ? 1U : 0U);
317 out->is_extended = is_ext;
318 out->id =
319 (is_ext != 0U) ? (id_word & k_ra8_canfd_id_ext_mask) : (id_word & k_ra8_canfd_id_std_mask);
320 out->dlc =
321 (uint8_t)((ptr_word >> (uint32_t)k_ra8_canfd_ptr_shift_dlc) & k_ra8_canfd_ptr_mask_dlc);
322 out->is_fd = ((fdsts_word & k_ra8_canfd_fd_fdf) != 0U) ? 1U : 0U;
323 out->is_brs = ((fdsts_word & k_ra8_canfd_fd_brs) != 0U) ? 1U : 0U;
324}
325
327{
328 volatile r_canfd_t* reg = ra8_canfd(channel);
329 RA8_CHECK_NULL_PTR(reg, s_tag, "channel out of range");
330 RA8_CHECK_NULL_PTR(out_frame, s_tag, "out_frame must not be nullptr");
331
332 /* HUM Ch 41 "CFDRFSTSn.RFEMP" p 2754 */ /* "CFDRFSTSn.RFEMP" -- empty flag is bit 0. */
334 return k_ra8_err_no_data;
335 }
336
337 /* HUM Ch 41 "CFDRFn ID/PTR/FDSTS/DF" p 2796 */ /* "CFDRFn ID/PTR/FDSTS/DF". */
341 out_frame);
342 internal_read_rx_data(reg, out_frame);
343
344 /* HUM Ch 41 p 2756 "CFDRFPCTRn.RFPC" -- write 0xFF to advance pointer.
345 * FSP r_canfd.c uses the same dummy 0xFF write to pop. */
347 return k_ra8_ok;
348}
349
350ra8_err_t ra8_canfd_get_error_state(uint8_t channel, uint8_t* tx_err, uint8_t* rx_err)
351{
352 volatile r_canfd_t* reg = ra8_canfd(channel);
353 RA8_CHECK_NULL_PTR(reg, s_tag, "channel out of range");
354 RA8_CHECK_NULL_PTR(tx_err, s_tag, "tx_err must not be nullptr");
355 RA8_CHECK_NULL_PTR(rx_err, s_tag, "rx_err must not be nullptr");
356
357 /* HUM Ch 41 p 2766 "CFDCnSTS" -- TEC[31:24] / REC[23:16] live in
358 * CFDC[0].STS, NOT in CFDC[0].ERFL like the previous header model. */
359 const uint32_t sts = reg->CFDC[0].STS;
360 *tx_err = (uint8_t)((sts >> (uint32_t)k_ra8_cnsts_bit_tec) & k_ra8_cnsts_mask_tec);
361 *rx_err = (uint8_t)((sts >> (uint32_t)k_ra8_cnsts_bit_rec) & k_ra8_cnsts_mask_rec);
362 return k_ra8_ok;
363}
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).
CANFD Lite driver (bit-timing, TX, RX, error state).
static void internal_write_tx_data(volatile r_canfd_t *reg, const ra8_canfd_frame_t *frame)
Copy the frame payload into CFDTM[0].DF[].
ra8_err_t ra8_canfd_transmit(uint8_t channel, const ra8_canfd_frame_t *frame)
Queue a frame into the TX message buffer and trigger transmission.
static uint32_t internal_tx_id(const ra8_canfd_frame_t *frame)
Assemble the CFDTM[0].ID word (raw ID plus IDE flag).
ra8_canfd_buffer_idx_t
Indices the driver currently owns within the channel block.
@ k_ra8_canfd_tx_mb_default
Driver uses TX MB 0 for fire-and-forget.
@ k_ra8_canfd_rx_fifo_default
Driver uses RX FIFO 0 for poll-receive.
static uint32_t internal_tx_fdctr(const ra8_canfd_frame_t *frame)
Assemble the CFDTM[0].FDCTR word (FDF/BRS/ESI flags).
static void internal_wait_tx_complete(volatile r_canfd_t *reg)
Best-effort bounded spin until CFDTMSTSj.TMTRF reads "complete".
ra8_err_t ra8_canfd_receive(uint8_t channel, ra8_canfd_frame_t *out_frame)
Poll the RX FIFO for the next available frame.
static ra8_err_t internal_validate_frame(const ra8_canfd_frame_t *frame)
Range-check a ra8_canfd_frame_t against the protocol limits.
ra8_err_t ra8_canfd_get_error_state(uint8_t channel, uint8_t *tx_err, uint8_t *rx_err)
Read the TX and RX error counters.
static void internal_read_rx_data(volatile r_canfd_t *reg, ra8_canfd_frame_t *out)
Copy 64 bytes of RX FIFO data from CFDRF[0].DF[] into the caller buffer.
ra8_canfd_frame_spin_t
TX-completion poll budget owned by the frame data path.
@ k_ra8_canfd_tx_spin
TX-completion poll: 500 us @ 1 GHz / 5 cyc.
static void internal_decode_rx_header(uint32_t id_word, uint32_t ptr_word, uint32_t fdsts_word, ra8_canfd_frame_t *out)
Decode the raw CFDRF[0].ID/PTR/FDSTS into out.
CANFD controller register layout for the Renesas RA8D2.
@ k_ra8_canfd_fd_brs
BRS: bit-rate switch.
@ k_ra8_canfd_fd_fdf
FDF: frame is CAN-FD.
@ k_ra8_rfpctr_value_ack
Dummy write to pop entry.
@ k_ra8_canfd_dlc_max
4-bit DLC max value (64 bytes).
@ k_ra8_canfd_data_bytes_max
CAN-FD payload cap in bytes.
@ k_ra8_canfd_ptr_mask_dlc
4-bit DLC mask.
@ k_ra8_rfsts_bit_empty
RFEMP: FIFO empty flag.
@ k_ra8_canfd_tmc_txreq
TMTR: transmit request.
@ k_ra8_canfd_ptr_shift_dlc
DLC field shift.
@ k_ra8_cnsts_mask_tec
TEC field mask (post-shift).
@ k_ra8_cnsts_mask_rec
REC field mask (post-shift).
@ k_ra8_canfd_id_std_mask
11-bit standard ID.
@ k_ra8_canfd_id_ext_mask
29-bit extended ID.
@ k_ra8_canfd_id_ide
IDE: extended flag.
@ k_ra8_cnsts_bit_rec
REC[23:16] in STS.
@ k_ra8_cnsts_bit_tec
TEC[31:24] in STS.
static volatile r_canfd_t * ra8_canfd(uint8_t channel)
Get pointer to CANFD instance N (0..1).
Validation and Error-Checking Macros for ra8-firmware.
#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_no_data
No application data available (e.g.
Definition ra8_err.h:202
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ 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.
volatile uint32_t STS
+0x008 Channel Status.
volatile uint32_t PTR
+0x004 RFTS + RFDLC.
volatile uint8_t DF[k_ra8_canfd_data_bytes_max]
+0x00C 64-byte data field.
volatile uint32_t ID
+0x000 RFID + RFRTR + RFIDE.
volatile uint32_t FDSTS
+0x008 RFESI + RFBRS + RFFDF + ...
volatile uint32_t FDCTR
+0x008 TMESI + TMBRS + TMFDF + ...
volatile uint32_t PTR
+0x004 TMTS + TMDLC.
volatile uint8_t DF[k_ra8_canfd_data_bytes_max]
+0x00C 64-byte data field.
volatile uint32_t ID
+0x000 TMID + THLEN + TMRTR + IDE.
volatile uint32_t CFDRFPCTR[k_ra8_canfd_rx_fifo_count]
CFDRFPCTR reg (offset 0x04C..0x053).
volatile uint32_t CFDRFSTS[k_ra8_canfd_rx_fifo_count]
CFDRFSTS register (offset 0x044..0x04B).
volatile uint8_t CFDTMC[k_ra8_canfd_tx_mb_count]
CFDTMC register (offset 0x070).
r_canfd_cfdtm_t CFDTM[k_ra8_canfd_tx_mb_count]
CFDTM register (offset 0x604..0x733).
r_canfd_cfdrf_t CFDRF[k_ra8_canfd_rx_fifo_count]
CFDRF register (offset 0x520..0x5B7).
volatile uint8_t CFDTMSTS[k_ra8_canfd_tx_mb_count]
CFDTMSTS register (offset 0x074).
r_canfd_cfdc_t CFDC[1]
CFDC register.
A single CAN / CAN-FD frame as seen by the driver public API.
Definition ra8_canfd.h:52
uint8_t is_fd
0 = classic CAN, 1 = CAN-FD.
Definition ra8_canfd.h:56
uint8_t is_brs
1 = bit-rate switch in data phase.
Definition ra8_canfd.h:57
uint32_t id
Arbitration-ID field.
Definition ra8_canfd.h:53
uint8_t dlc
DLC code (0..15).
Definition ra8_canfd.h:54
uint8_t data[k_ra8_canfd_data_bytes_max]
Payload bytes.
Definition ra8_canfd.h:58
uint8_t is_extended
0 = 11-bit ID, 1 = 29-bit ID.
Definition ra8_canfd.h:55