1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /***********************************************************************************************************************
8 * Includes
9 **********************************************************************************************************************/
10 #include "r_canfd.h"
11 #include "r_canfd_cfg.h"
12
13 /***********************************************************************************************************************
14 * Macro definitions
15 **********************************************************************************************************************/
16
17 #define CANFD_OPEN (0x52434644U) // "RCFD" in ASCII
18
19 #define CANFD_BAUD_RATE_PRESCALER_MIN (1U)
20 #define CANFD_BAUD_RATE_PRESCALER_MAX (1024U)
21
22 #define CANFD_PRV_CTR_MODE_MASK (R_CANFD_CFDGCTR_GSLPR_Msk + R_CANFD_CFDGCTR_GMDC_Msk)
23 #define CANFD_PRV_CTR_RESET_BIT (1U)
24 #define CANFD_PRV_RXMB_MAX (32U)
25 #define CANFD_PRV_TXMB_OFFSET (32U)
26 #define CANFD_PRV_TXMB_CHANNEL_OFFSET (64U)
27 #define CANFD_PRV_STANDARD_ID_MAX (0x7FFU)
28
29 /** Whether or not the peripheral contains CFDCFTISTS and CFDCFRISTS registers. */
30 #define CANFD_PRV_CFIFO_HAS_ISTS (!(BSP_FEATURE_CANFD_LITE && BSP_FEATURE_CANFD_NUM_CHANNELS == 1))
31
32 #if BSP_FEATURE_CANFD_LITE
33 #define CANFD_PRV_CFIFO_CHANNEL_OFFSET (1U)
34
35 #define R_CANFD_CFDRM_RM_TYPE R_CANFD_CFDRM_RM_Type
36
37 #define CANFD_PRV_RXMB_PTR(buffer) ((volatile R_CANFD_CFDRM_RM_TYPE *) &p_reg->CFDRM[buffer >> 3].RM[buffer & 7U])
38 #define CANFD_PRV_RX_FIFO_MAX (2U)
39 #define CANFD_PRV_COMMON_FIFO_MAX (1U)
40 #define CANFD_PRV_CFDTMIEC_LENGTH (1)
41 #define CANFD_PRV_RMID_POSITION (R_CANFD_CFDRM_RM_ID_RMID_Pos)
42 #define CANFD_PRV_RMID_MASK (R_CANFD_CFDRM_RM_ID_RMID_Msk)
43 #define CANFD_PRV_RMRTR_POSITION (R_CANFD_CFDRM_RM_ID_RMRTR_Pos)
44 #define CANFD_PRV_RMRTR_MASK (R_CANFD_CFDRM_RM_ID_RMRTR_Msk)
45 #define CANFD_PRV_RMIDE_POSITION (R_CANFD_CFDRM_RM_ID_RMIDE_Pos)
46 #define CANFD_PRV_RMIDE_MASK (R_CANFD_CFDRM_RM_ID_RMIDE_Msk)
47 #define CANFD_PRV_RMDLC_POSITION (R_CANFD_CFDRM_RM_PTR_RMDLC_Pos)
48 #define CANFD_PRV_RMDLC_MASK (R_CANFD_CFDRM_RM_PTR_RMDLC_Msk)
49 #else
50 #define CANFD_PRV_CFIFO_CHANNEL_OFFSET (3U)
51
52 #define R_CANFD_CFDRM_RM_TYPE R_CANFD_CFDRM_Type
53
54 #define CANFD_PRV_RXMB_PTR(buffer) (&p_reg->CFDRM[buffer])
55 #define CANFD_PRV_RX_FIFO_MAX (8U)
56 #define CANFD_PRV_COMMON_FIFO_MAX (3U)
57 #define CANFD_PRV_CFDTMIEC_LENGTH (2)
58 #define CANFD_PRV_RMID_POSITION (R_CANFD_CFDRM_ID_RMID_Pos)
59 #define CANFD_PRV_RMID_MASK (R_CANFD_CFDRM_ID_RMID_Msk)
60 #define CANFD_PRV_RMRTR_POSITION (R_CANFD_CFDRM_ID_RMRTR_Pos)
61 #define CANFD_PRV_RMRTR_MASK (R_CANFD_CFDRM_ID_RMRTR_Msk)
62 #define CANFD_PRV_RMIDE_POSITION (R_CANFD_CFDRM_ID_RMIDE_Pos)
63 #define CANFD_PRV_RMIDE_MASK (R_CANFD_CFDRM_ID_RMIDE_Msk)
64 #define CANFD_PRV_RMDLC_POSITION (R_CANFD_CFDRM_PTR_RMDLC_Pos)
65 #define CANFD_PRV_RMDLC_MASK (R_CANFD_CFDRM_PTR_RMDLC_Msk)
66 #endif
67
68 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
69 #define CANFD_INTER_CH(channel) (0U)
70 #else
71 #define CANFD_INTER_CH(channel) (channel)
72 #endif
73
74 #define CANFD_PRV_CFIFO_INDEX(buffer, channel) ((buffer) + ((channel) * CANFD_PRV_CFIFO_CHANNEL_OFFSET))
75
76 /***********************************************************************************************************************
77 * Const data
78 **********************************************************************************************************************/
79
80 /* LUT to convert DLC values to payload size in bytes */
81 static const uint8_t dlc_to_bytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
82
83 #if CANFD_CFG_PARAM_CHECKING_ENABLE
84
85 /* LUT to determine the hierarchy of can_operation_mode_t modes. */
86 static const uint8_t g_mode_order[] = {0, 2, 1, 0, 0, 3};
87 #endif
88
89 /***********************************************************************************************************************
90 * Typedef definitions
91 **********************************************************************************************************************/
92 #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
93 typedef void (BSP_CMSE_NONSECURE_CALL * canfd_prv_ns_callback)(can_callback_args_t * p_args);
94 #elif defined(__GNUC__)
95 typedef BSP_CMSE_NONSECURE_CALL void (*volatile canfd_prv_ns_callback)(can_callback_args_t * p_args);
96 #endif
97
98 /***********************************************************************************************************************
99 * Private function prototypes
100 **********************************************************************************************************************/
101 #if CANFD_CFG_PARAM_CHECKING_ENABLE
102 static bool r_canfd_bit_timing_parameter_check(can_bit_timing_cfg_t * p_bit_timing, bool is_data_phase);
103
104 #endif
105
106 #if BSP_FEATURE_CANFD_FD_SUPPORT
107 static uint8_t r_canfd_bytes_to_dlc(uint8_t bytes);
108
109 #endif
110
111 static void r_candfd_global_error_handler(uint32_t instance);
112 static void r_canfd_rx_fifo_handler(uint32_t instance);
113 static void r_canfd_mb_read(R_CANFD_Type * p_reg, uint32_t buffer, can_frame_t * const frame);
114 static void r_canfd_call_callback(canfd_instance_ctrl_t * p_ctrl, can_callback_args_t * p_args);
115 static void r_canfd_mode_transition(canfd_instance_ctrl_t * p_ctrl, can_operation_mode_t operation_mode);
116 static void r_canfd_mode_ctr_set(volatile uint32_t * p_ctr_reg, can_operation_mode_t operation_mode);
117 void canfd_error_isr(void);
118 void canfd_rx_fifo_isr(void);
119 void canfd_common_fifo_rx_isr(void);
120 void canfd_channel_tx_isr(void);
121
122 /***********************************************************************************************************************
123 * ISR prototypes
124 **********************************************************************************************************************/
125
126 /***********************************************************************************************************************
127 * Private global variables
128 **********************************************************************************************************************/
129
130 /***********************************************************************************************************************
131 * Global Variables
132 **********************************************************************************************************************/
133
134 /* Channel control struct array */
135 static canfd_instance_ctrl_t * gp_ctrl[BSP_FEATURE_CANFD_NUM_INSTANCES * BSP_FEATURE_CANFD_NUM_CHANNELS] = {NULL};
136
137 /* CAN function pointers */
138 const can_api_t g_canfd_on_canfd =
139 {
140 .open = R_CANFD_Open,
141 .close = R_CANFD_Close,
142 .write = R_CANFD_Write,
143 .read = R_CANFD_Read,
144 .modeTransition = R_CANFD_ModeTransition,
145 .infoGet = R_CANFD_InfoGet,
146 .callbackSet = R_CANFD_CallbackSet,
147 };
148
149 /*******************************************************************************************************************//**
150 * @addtogroup CANFD
151 * @{
152 **********************************************************************************************************************/
153
154 /***********************************************************************************************************************
155 * Functions
156 **********************************************************************************************************************/
157
158 /***************************************************************************************************************//**
159 * Open and configure the CANFD channel for operation.
160 *
161 * Example:
162 * @snippet r_canfd_example.c R_CANFD_Open
163 *
164 * @retval FSP_SUCCESS Channel opened successfully.
165 * @retval FSP_ERR_ALREADY_OPEN Driver already open.
166 * @retval FSP_ERR_IN_USE Channel is already in use.
167 * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT Channel does not exist on this MCU.
168 * @retval FSP_ERR_ASSERTION A required pointer was NULL.
169 * @retval FSP_ERR_CAN_INIT_FAILED The provided nominal or data bitrate is invalid.
170 * @retval FSP_ERR_CLOCK_INACTIVE CANFD source clock is disabled (PLL or PLL2).
171 *****************************************************************************************************************/
R_CANFD_Open(can_ctrl_t * const p_api_ctrl,can_cfg_t const * const p_cfg)172 fsp_err_t R_CANFD_Open (can_ctrl_t * const p_api_ctrl, can_cfg_t const * const p_cfg)
173 {
174 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
175
176 #if CANFD_CFG_PARAM_CHECKING_ENABLE
177 FSP_ASSERT(p_ctrl);
178 FSP_ASSERT(p_cfg);
179 FSP_ASSERT(p_cfg->p_extend);
180 FSP_ASSERT(p_cfg->p_callback);
181 FSP_ASSERT(p_cfg->p_bit_timing);
182
183 uint32_t channel = p_cfg->channel;
184
185 /* Check that the module is not open, the channel is present and that it is not in use */
186 FSP_ERROR_RETURN(CANFD_OPEN != p_ctrl->open, FSP_ERR_ALREADY_OPEN);
187 FSP_ERROR_RETURN(channel < BSP_FEATURE_CANFD_NUM_CHANNELS * BSP_FEATURE_CANFD_NUM_INSTANCES,
188 FSP_ERR_IP_CHANNEL_NOT_PRESENT);
189 FSP_ERROR_RETURN(NULL == gp_ctrl[channel], FSP_ERR_IN_USE);
190
191 /* Check that mandatory interrupts are enabled */
192 FSP_ERROR_RETURN(VECTOR_NUMBER_CAN_RXF >= 0, FSP_ERR_CAN_INIT_FAILED);
193 FSP_ERROR_RETURN(VECTOR_NUMBER_CAN_GLERR >= 0, FSP_ERR_CAN_INIT_FAILED);
194
195 /* Check that the global config is present */
196 canfd_extended_cfg_t * p_extend = (canfd_extended_cfg_t *) p_cfg->p_extend;
197 FSP_ASSERT(p_extend->p_global_cfg);
198
199 #if BSP_CFG_CANFDCLK_SOURCE != BSP_CLOCKS_SOURCE_CLOCK_MAIN_OSC
200
201 /* Check that PLL/PLL2 is running when it is selected as the DLL source clock */
202 FSP_ERROR_RETURN(0U ==
203 (FSP_STYPE3_REG8_READ(R_SYSTEM->CANFDCKCR,
204 !R_SYSTEM->CGFSAR_b.NONSEC18) == BSP_CLOCKS_SOURCE_CLOCK_PLL ?
205 FSP_STYPE3_REG8_READ(R_SYSTEM->PLLCR, !R_SYSTEM->CGFSAR_b.NONSEC08) :
206 FSP_STYPE3_REG8_READ(R_SYSTEM->PLL2CR, !R_SYSTEM->CGFSAR_b.NONSEC09)),
207 FSP_ERR_CLOCK_INACTIVE);
208 #endif
209
210 /* Check nominal bit timing parameters for correctness */
211 FSP_ERROR_RETURN(r_canfd_bit_timing_parameter_check(p_cfg->p_bit_timing, false), FSP_ERR_CAN_INIT_FAILED);
212
213 #if BSP_FEATURE_CANFD_FD_SUPPORT
214
215 /* Check that bit timing for FD bitrate switching is present and correct */
216 can_bit_timing_cfg_t * p_data_timing = p_extend->p_data_timing;
217 FSP_ASSERT(p_data_timing);
218 FSP_ERROR_RETURN(r_canfd_bit_timing_parameter_check(p_data_timing, true), FSP_ERR_CAN_INIT_FAILED);
219
220 can_bit_timing_cfg_t * p_bit_timing = p_cfg->p_bit_timing;
221
222 /* Check that data rate > nominal rate */
223 uint32_t data_rate_clocks = p_data_timing->baud_rate_prescaler *
224 (p_data_timing->time_segment_1 + p_data_timing->time_segment_2 + 1U);
225 uint32_t nominal_rate_clocks = p_bit_timing->baud_rate_prescaler *
226 (p_bit_timing->time_segment_1 + p_bit_timing->time_segment_2 + 1U);
227 FSP_ERROR_RETURN(data_rate_clocks <= nominal_rate_clocks, FSP_ERR_CAN_INIT_FAILED);
228 #endif
229 #else
230 uint32_t channel = p_cfg->channel;
231
232 /* Get extended config */
233 canfd_extended_cfg_t * p_extend = (canfd_extended_cfg_t *) p_cfg->p_extend;
234 #endif
235
236 fsp_err_t err = FSP_SUCCESS;
237
238 /* Save the base register for this channel. */
239 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
240 R_CANFD_Type * p_reg =
241 (R_CANFD_Type *) ((uint32_t) R_CANFD0 + (channel * ((uint32_t) R_CANFD1 - (uint32_t) R_CANFD0)));
242 #else
243 R_CANFD_Type * p_reg = R_CANFD;
244 #endif
245 p_ctrl->p_reg = p_reg;
246
247 /* Initialize the control block */
248 p_ctrl->p_cfg = p_cfg;
249
250 /* Set callback and context pointers, if configured */
251 p_ctrl->p_callback = p_cfg->p_callback;
252 p_ctrl->p_context = p_cfg->p_context;
253 p_ctrl->p_callback_memory = NULL;
254
255 /* Get global config */
256 canfd_global_cfg_t * p_global_cfg = p_extend->p_global_cfg;
257
258 /* Start module */
259 #if BSP_FEATURE_CANFD_LITE
260 R_BSP_MODULE_START(FSP_IP_CANFD, channel);
261 #else
262 R_BSP_MODULE_START(FSP_IP_CANFD, 0);
263 #endif
264
265 /* Perform global config only if the module is in Global Sleep or Global Reset */
266 #if !BSP_FEATURE_CANFD_LITE
267 if (p_reg->CFDGSTS & R_CANFD_CFDGSTS_GRSTSTS_Msk)
268 #endif
269 {
270 /* Wait for RAM initialization (see RA6M5 User's Manual (R01UH0891EJ0100) section 32.3.4.1 Note 2) */
271 FSP_HARDWARE_REGISTER_WAIT((p_reg->CFDGSTS & R_CANFD_CFDGSTS_GRAMINIT_Msk), 0);
272
273 /* Cancel Global Sleep and wait for transition to Global Reset */
274 r_canfd_mode_transition(p_ctrl, CAN_OPERATION_MODE_GLOBAL_RESET);
275
276 /* Configure global TX priority, DLC check/replace functions, external/internal clock select and payload
277 * overflow behavior */
278 p_reg->CFDGCFG = p_global_cfg->global_config;
279
280 /* Configure rule count for both channels */
281 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
282 p_reg->CFDGAFLCFG0 = (CANFD_CFG_AFL_CH0_RULE_NUM << R_CANFD_CFDGAFLCFG0_RNC0_Pos);
283 if (channel == 1)
284 {
285 p_reg->CFDGAFLCFG0 = (CANFD_CFG_AFL_CH1_RULE_NUM << R_CANFD_CFDGAFLCFG0_RNC0_Pos);
286 }
287 #else
288 p_reg->CFDGAFLCFG0 = (CANFD_CFG_AFL_CH0_RULE_NUM << R_CANFD_CFDGAFLCFG0_RNC0_Pos) |
289 CANFD_CFG_AFL_CH1_RULE_NUM;
290 #endif
291
292 /* Set CAN FD Protocol Exception response (ISO exception state or send error frame) */
293 p_reg->CFDGFDCFG = CANFD_CFG_FD_PROTOCOL_EXCEPTION;
294
295 /* Set number and size of RX message buffers */
296 p_reg->CFDRMNB = p_global_cfg->rx_mb_config;
297
298 /* Configure RX FIFOs and interrupt */
299 for (uint32_t i = 0; i < CANFD_PRV_RX_FIFO_MAX; i++)
300 {
301 p_reg->CFDRFCC[i] = p_global_cfg->rx_fifo_config[i];
302 }
303
304 R_BSP_IrqCfgEnable(VECTOR_NUMBER_CAN_RXF, p_global_cfg->rx_fifo_ipl, NULL);
305
306 /* Set global error interrupts */
307 p_reg->CFDGCTR = p_global_cfg->global_interrupts;
308
309 /* Configure Common FIFOs */
310 for (uint32_t i = 0; i < R_CANFD_NUM_COMMON_FIFOS; i++)
311 {
312 /* Configure the Common FIFOs. Mask out the enable bit because it can only be set once operating.
313 * See Section 32.2.29 of the RA6M5 user manual (R01UH0891EJ0120) */
314 p_reg->CFDCFCC[i] = p_global_cfg->common_fifo_config[i] & ~R_CANFD_CFDCFCC_CFE_Msk;
315 }
316 }
317
318 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
319 if (CANFD_CFG_GLOBAL_ERROR_CH == channel)
320 #endif
321 {
322 /* Configure global error interrupt */
323 R_BSP_IrqCfgEnable(VECTOR_NUMBER_CAN_GLERR, p_global_cfg->global_err_ipl, p_ctrl);
324 }
325
326 /* Track ctrl struct */
327 gp_ctrl[channel] = p_ctrl;
328
329 /* Get AFL entry and limit */
330 uint32_t afl_entry = 0;
331 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
332 uint32_t afl_max = CANFD_CFG_AFL_CH0_RULE_NUM;
333 if (1U == channel)
334 {
335 afl_max = CANFD_CFG_AFL_CH1_RULE_NUM;
336 }
337
338 #else
339 uint32_t afl_max = CANFD_CFG_AFL_CH0_RULE_NUM;
340 if (1U == channel)
341 {
342 afl_entry += CANFD_CFG_AFL_CH0_RULE_NUM;
343 afl_max += CANFD_CFG_AFL_CH1_RULE_NUM;
344 }
345 #endif
346
347 /* Unlock AFL */
348 p_reg->CFDGAFLECTR = R_CANFD_CFDGAFLECTR_AFLDAE_Msk;
349
350 /* Write all configured AFL entries */
351 R_CANFD_CFDGAFL_Type * p_afl = (R_CANFD_CFDGAFL_Type *) p_extend->p_afl;
352 for ( ; afl_entry < afl_max; afl_entry++)
353 {
354 /* AFL register access is performed through a page window comprised of 16 entries. See Section 32.5.4 "Entering
355 * Entries in the AFL" in the RA6M5 User's Manual (R01UH0891EJ010) for more details. */
356
357 /* Set AFL page */
358 p_reg->CFDGAFLECTR = (afl_entry >> 4) | R_CANFD_CFDGAFLECTR_AFLDAE_Msk;
359
360 /* Get pointer to current AFL rule and set it to the rule pointed to by p_afl */
361 volatile R_CANFD_CFDGAFL_Type * cfdgafl = &p_reg->CFDGAFL[afl_entry & 0xF];
362 *cfdgafl = *p_afl++;
363
364 /* Set Information Label 0 to the channel being configured */
365 cfdgafl->P0_b.GAFLIFL0 = channel & 1U;
366 }
367
368 /* Lock AFL */
369 p_reg->CFDGAFLECTR = 0;
370
371 /* Cancel Channel Sleep and wait for transition to Channel Reset */
372 r_canfd_mode_transition(p_ctrl, CAN_OPERATION_MODE_RESET);
373
374 uint32_t interlaced_channel = CANFD_INTER_CH(channel);
375
376 /* Configure bitrate */
377 p_reg->CFDC[interlaced_channel].NCFG =
378 (uint32_t) (((p_cfg->p_bit_timing->baud_rate_prescaler - 1) & R_CANFD_CFDC_NCFG_NBRP_Msk) <<
379 R_CANFD_CFDC_NCFG_NBRP_Pos) |
380 ((p_cfg->p_bit_timing->time_segment_1 - 1U) << R_CANFD_CFDC_NCFG_NTSEG1_Pos) |
381 ((p_cfg->p_bit_timing->time_segment_2 - 1U) << R_CANFD_CFDC_NCFG_NTSEG2_Pos) |
382 ((p_cfg->p_bit_timing->synchronization_jump_width - 1U) << R_CANFD_CFDC_NCFG_NSJW_Pos);
383
384 #if BSP_FEATURE_CANFD_FD_SUPPORT
385
386 /* Configure data bitrate for rate switching on FD frames */
387 p_reg->CFDC2[interlaced_channel].DCFG =
388 (uint32_t) (((p_extend->p_data_timing->baud_rate_prescaler - 1) & R_CANFD_CFDC2_DCFG_DBRP_Msk) <<
389 R_CANFD_CFDC2_DCFG_DBRP_Pos) |
390 ((p_extend->p_data_timing->time_segment_1 - 1U) << R_CANFD_CFDC2_DCFG_DTSEG1_Pos) |
391 ((p_extend->p_data_timing->time_segment_2 - 1U) << R_CANFD_CFDC2_DCFG_DTSEG2_Pos) |
392 ((p_extend->p_data_timing->synchronization_jump_width - 1U) << R_CANFD_CFDC2_DCFG_DSJW_Pos);
393
394 /* Ensure transceiver delay offset is not larger than 8 bits */
395 uint32_t tdco = p_extend->p_data_timing->time_segment_1;
396 if (tdco > UINT8_MAX)
397 {
398 tdco = UINT8_MAX;
399 }
400
401 /* Configure transceiver delay compensation; allow user to set ESI bit manually */
402 p_reg->CFDC2[interlaced_channel].FDCFG =
403 (tdco << R_CANFD_CFDC2_FDCFG_TDCO_Pos) |
404 (uint32_t) (p_extend->delay_compensation << R_CANFD_CFDC2_FDCFG_TDCE_Pos) |
405 R_CANFD_CFDC2_FDCFG_ESIC_Msk | 1U;
406 #endif
407
408 /* Write TX message buffer interrupt enable bits */
409 memcpy((void *) &p_reg->CFDTMIEC[interlaced_channel * CANFD_PRV_CFDTMIEC_LENGTH],
410 &p_extend->txmb_txi_enable,
411 CANFD_PRV_CFDTMIEC_LENGTH * sizeof(uint32_t));
412
413 /* Configure channel error interrupts */
414 p_reg->CFDC[interlaced_channel].CTR = p_extend->error_interrupts | R_CANFD_CFDC_CTR_CHMDC_Msk;
415
416 /* Enable channel interrupts */
417
418 if (p_cfg->error_irq >= 0)
419 {
420 R_BSP_IrqCfgEnable(p_cfg->error_irq, p_cfg->ipl, p_ctrl);
421 }
422
423 if (p_cfg->tx_irq >= 0)
424 {
425 R_BSP_IrqCfgEnable(p_cfg->tx_irq, p_cfg->ipl, p_ctrl);
426 }
427
428 /* Use the CAN RX IRQ for Common FIFO RX. */
429 if (p_cfg->rx_irq >= 0)
430 {
431 R_BSP_IrqCfgEnable(p_cfg->rx_irq, p_cfg->ipl, p_ctrl);
432 }
433
434 /* Set global mode to Operation and wait for transition */
435 r_canfd_mode_transition(p_ctrl, CAN_OPERATION_MODE_GLOBAL_OPERATION);
436
437 /* Transition to Channel Operation */
438 r_canfd_mode_transition(p_ctrl, CAN_OPERATION_MODE_NORMAL);
439
440 /* Set current operation modes */
441 p_ctrl->operation_mode = CAN_OPERATION_MODE_NORMAL;
442 p_ctrl->test_mode = CAN_TEST_MODE_DISABLED;
443
444 /* Set driver to open */
445 p_ctrl->open = CANFD_OPEN;
446
447 return err;
448 }
449
450 /***************************************************************************************************************//**
451 * Close the CANFD channel.
452 *
453 * @retval FSP_SUCCESS Channel closed successfully.
454 * @retval FSP_ERR_NOT_OPEN Control block not open.
455 * @retval FSP_ERR_ASSERTION Null pointer presented.
456 *****************************************************************************************************************/
R_CANFD_Close(can_ctrl_t * const p_api_ctrl)457 fsp_err_t R_CANFD_Close (can_ctrl_t * const p_api_ctrl)
458 {
459 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
460
461 #if CANFD_CFG_PARAM_CHECKING_ENABLE
462 FSP_ASSERT(NULL != p_ctrl);
463 FSP_ERROR_RETURN(p_ctrl->open == CANFD_OPEN, FSP_ERR_NOT_OPEN);
464 #endif
465
466 /* Set driver to closed */
467 p_ctrl->open = 0U;
468
469 /* Get config struct */
470 can_cfg_t * p_cfg = (can_cfg_t *) p_ctrl->p_cfg;
471
472 /* Disable channel interrupts */
473
474 if (p_cfg->error_irq >= 0)
475 {
476 R_BSP_IrqDisable(p_cfg->error_irq);
477 }
478
479 if (p_cfg->tx_irq >= 0)
480 {
481 R_BSP_IrqDisable(p_cfg->tx_irq);
482 }
483
484 if (p_cfg->rx_irq >= 0)
485 {
486 R_BSP_IrqDisable(p_cfg->rx_irq);
487 }
488
489 /* Disable Global Error interrupt if the handler channel is being closed */
490 #if !BSP_FEATURE_CANFD_LITE
491 if (CANFD_CFG_GLOBAL_ERROR_CH == p_cfg->channel)
492 #elif BSP_FEATURE_CANFD_NUM_INSTANCES > 1
493
494 /* Only disable the Global Error interrupt if both channels are closed. */
495 if (NULL == gp_ctrl[!p_cfg->channel])
496 #endif
497 {
498 R_BSP_IrqDisable(VECTOR_NUMBER_CAN_GLERR);
499
500 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
501
502 /* Disable RX FIFO interrupt */
503 R_BSP_IrqDisable(VECTOR_NUMBER_CAN_RXF);
504 #endif
505 }
506
507 #if !BSP_FEATURE_CANFD_LITE
508
509 /* Set channel to Sleep if other is open, otherwise reset/stop CANFD module */
510 if (gp_ctrl[!p_cfg->channel])
511 {
512 r_canfd_mode_transition(p_ctrl, CAN_OPERATION_MODE_SLEEP);
513 }
514 else
515 #endif
516 {
517 #if BSP_FEATURE_CANFD_NUM_INSTANCES == 1
518
519 /* Disable RX FIFO interrupt */
520 R_BSP_IrqDisable(VECTOR_NUMBER_CAN_RXF);
521 #endif
522
523 /* Transition to Global Sleep */
524 r_canfd_mode_transition(p_ctrl, CAN_OPERATION_MODE_GLOBAL_RESET);
525 r_canfd_mode_transition(p_ctrl, CAN_OPERATION_MODE_GLOBAL_SLEEP);
526
527 /* Stop CANFD module */
528 #if BSP_FEATURE_CANFD_LITE
529 R_BSP_MODULE_STOP(FSP_IP_CANFD, p_cfg->channel);
530 #else
531 R_BSP_MODULE_STOP(FSP_IP_CANFD, 0);
532 #endif
533 }
534
535 /* Reset global control struct pointer */
536 gp_ctrl[p_cfg->channel] = NULL;
537
538 return FSP_SUCCESS;
539 }
540
541 /***************************************************************************************************************//**
542 * Write data to the CANFD channel.
543 *
544 * Example:
545 * @snippet r_canfd_example.c R_CANFD_Write
546 *
547 * @retval FSP_SUCCESS Operation succeeded.
548 * @retval FSP_ERR_NOT_OPEN Control block not open.
549 * @retval FSP_ERR_CAN_TRANSMIT_NOT_READY Transmit in progress, cannot write data at this time.
550 * @retval FSP_ERR_INVALID_ARGUMENT Data length or buffer number invalid.
551 * @retval FSP_ERR_INVALID_MODE An FD option was set on a non-FD frame.
552 * @retval FSP_ERR_ASSERTION One or more pointer arguments is NULL.
553 * @retval FSP_ERR_UNSUPPORTED FD is not supported on this MCU.
554 *****************************************************************************************************************/
R_CANFD_Write(can_ctrl_t * const p_api_ctrl,uint32_t buffer,can_frame_t * const p_frame)555 fsp_err_t R_CANFD_Write (can_ctrl_t * const p_api_ctrl, uint32_t buffer, can_frame_t * const p_frame)
556 {
557 #if CANFD_CFG_PARAM_CHECKING_ENABLE
558 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
559
560 FSP_ASSERT(NULL != p_ctrl);
561 FSP_ASSERT(NULL != p_frame);
562 FSP_ERROR_RETURN(p_ctrl->open == CANFD_OPEN, FSP_ERR_NOT_OPEN);
563
564 #if !BSP_FEATURE_CANFD_LITE
565
566 /* CANFD channels have 16 TX message buffers + 3 common FIFOs each (0-7, 32-39, 40-42) */
567 FSP_ERROR_RETURN((buffer <= 7U) ||
568 (buffer - 32U <= 7U) ||
569 (buffer - (uint32_t) CANFD_TX_BUFFER_FIFO_COMMON_0 <= 2U),
570 FSP_ERR_INVALID_ARGUMENT);
571 #else
572
573 /* CANFD Lite has 4 TX message buffers + 1 common FIFO */
574 FSP_ERROR_RETURN((buffer <= 3U) ||
575 (buffer - (uint32_t) CANFD_TX_BUFFER_FIFO_COMMON_0 <= 0U),
576 FSP_ERR_INVALID_ARGUMENT);
577 #endif
578
579 /* Check DLC field */
580 #if BSP_FEATURE_CANFD_FD_SUPPORT
581 if (!(p_frame->options & CANFD_FRAME_OPTION_FD))
582 {
583 FSP_ERROR_RETURN(p_frame->data_length_code <= 8, FSP_ERR_INVALID_ARGUMENT);
584 FSP_ERROR_RETURN(p_frame->options == 0, FSP_ERR_INVALID_MODE);
585 }
586 else if (p_frame->data_length_code > 0)
587 {
588 /* Make sure the supplied data size corresponds to a valid DLC value */
589 FSP_ERROR_RETURN(0U != r_canfd_bytes_to_dlc(p_frame->data_length_code), FSP_ERR_INVALID_ARGUMENT);
590 }
591 else
592 {
593 /* Do nothing. */
594 }
595
596 #else
597 FSP_ERROR_RETURN(p_frame->data_length_code <= 8, FSP_ERR_INVALID_ARGUMENT);
598 FSP_ERROR_RETURN(p_frame->options == 0, FSP_ERR_UNSUPPORTED);
599 #endif
600 #else
601 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
602 #endif
603
604 /* Provide variables to store common values. */
605 const bool is_cfifo = buffer >= (uint32_t) CANFD_TX_BUFFER_FIFO_COMMON_0;
606 const uint32_t interlaced_channel = CANFD_INTER_CH(p_ctrl->p_cfg->channel);
607
608 const uint32_t id = p_frame->id | ((uint32_t) p_frame->type << R_CANFD_CFDTM_ID_TMRTR_Pos) |
609 ((uint32_t) p_frame->id_mode << R_CANFD_CFDTM_ID_TMIDE_Pos);
610
611 uint32_t buffer_idx = 0;
612 uint8_t * p_dest = NULL;
613
614 if (!is_cfifo)
615 {
616 /* Calculate global TX message buffer number */
617 buffer_idx = buffer + (interlaced_channel * CANFD_PRV_TXMB_CHANNEL_OFFSET);
618
619 /* Ensure MB is ready */
620 FSP_ERROR_RETURN(0U == p_ctrl->p_reg->CFDTMSTS_b[buffer_idx].TMTRM, FSP_ERR_CAN_TRANSMIT_NOT_READY);
621
622 /* Set ID */
623 p_ctrl->p_reg->CFDTM[buffer_idx].ID = id;
624 #if BSP_FEATURE_CANFD_FD_SUPPORT
625
626 /* Set DLC */
627 p_ctrl->p_reg->CFDTM[buffer_idx].PTR = (uint32_t) r_canfd_bytes_to_dlc(p_frame->data_length_code) <<
628 R_CANFD_CFDTM_PTR_TMDLC_Pos;
629
630 /* Set FD bits (ESI, BRS and FDF) */
631 p_ctrl->p_reg->CFDTM[buffer_idx].FDCTR = p_frame->options & 7U;
632 #else
633
634 /* Set DLC */
635 p_ctrl->p_reg->CFDTM[buffer_idx].PTR = (uint32_t) p_frame->data_length_code << R_CANFD_CFDTM_PTR_TMDLC_Pos;
636 #endif
637
638 /* Store the data pointer. */
639 p_dest = (uint8_t *) p_ctrl->p_reg->CFDTM[buffer_idx].DF;
640 }
641 else
642 {
643 /* Calculate the Common FIFO index. */
644 buffer_idx = buffer - (uint32_t) CANFD_TX_BUFFER_FIFO_COMMON_0 +
645 (interlaced_channel * CANFD_PRV_CFIFO_CHANNEL_OFFSET);
646
647 /* Set ID. */
648 p_ctrl->p_reg->CFDCF[buffer_idx].ID = id;
649
650 #if BSP_FEATURE_CANFD_FD_SUPPORT
651
652 /* Set DLC. */
653 p_ctrl->p_reg->CFDCF[buffer_idx].PTR = (uint32_t) r_canfd_bytes_to_dlc(p_frame->data_length_code) <<
654 R_CANFD_CFDCF_PTR_CFDLC_Pos;
655
656 /* Set the FD bits (ESI, BRS and FDF). */
657 p_ctrl->p_reg->CFDCF[buffer_idx].FDSTS = p_frame->options & 7U;
658 #else
659
660 /* Set DLC. */
661 p_ctrl->p_reg->CFDTM[buffer_idx].PTR = (uint32_t) p_frame->data_length_code << R_CANFD_CFDCF_PTR_CFDLC_Pos;
662 #endif
663
664 /* Store the data poitner. */
665 p_dest = (uint8_t *) p_ctrl->p_reg->CFDCF[buffer_idx].DF;
666 }
667
668 /* Copy data to register buffer */
669 uint32_t len = p_frame->data_length_code;
670 uint8_t * p_src = p_frame->data;
671 while (len--)
672 {
673 *p_dest++ = *p_src++;
674 }
675
676 if (!is_cfifo)
677 {
678 /* Request transmission */
679 p_ctrl->p_reg->CFDTMC[buffer_idx] = 1;
680 }
681 else
682 {
683 /* Increment the FIFO pointer by writing 0xFF to CFPC. */
684 p_ctrl->p_reg->CFDCFPCTR[buffer_idx] = R_CANFD_CFDCFPCTR_CFPC_Msk;
685 }
686
687 return FSP_SUCCESS;
688 }
689
690 /***************************************************************************************************************//**
691 * Read data from a CANFD Message Buffer or FIFO.
692 *
693 * Example:
694 * snippet r_canfd_example.c R_CANFD_Read
695 *
696 * @retval FSP_SUCCESS Operation succeeded.
697 * @retval FSP_ERR_NOT_OPEN Control block not open.
698 * @retval FSP_ERR_INVALID_ARGUMENT Buffer number invalid.
699 * @retval FSP_ERR_ASSERTION p_api_ctrl or p_frame is NULL.
700 * @retval FSP_ERR_BUFFER_EMPTY Buffer or FIFO is empty.
701 *****************************************************************************************************************/
R_CANFD_Read(can_ctrl_t * const p_api_ctrl,uint32_t buffer,can_frame_t * const p_frame)702 fsp_err_t R_CANFD_Read (can_ctrl_t * const p_api_ctrl, uint32_t buffer, can_frame_t * const p_frame)
703 {
704 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
705 #if CANFD_CFG_PARAM_CHECKING_ENABLE
706 FSP_ASSERT(NULL != p_ctrl);
707 FSP_ASSERT(NULL != p_frame);
708 FSP_ERROR_RETURN(p_ctrl->open == CANFD_OPEN, FSP_ERR_NOT_OPEN);
709 FSP_ERROR_RETURN((buffer < CANFD_PRV_RXMB_MAX + CANFD_PRV_RX_FIFO_MAX) ||
710 ((buffer >= CANFD_RX_BUFFER_FIFO_COMMON_0) &&
711 (buffer < CANFD_RX_BUFFER_FIFO_COMMON_0 + CANFD_PRV_COMMON_FIFO_MAX)),
712 FSP_ERR_INVALID_ARGUMENT);
713 #endif
714
715 uint32_t not_empty;
716
717 /* Return an error if the buffer or FIFO is empty */
718 if (buffer < CANFD_PRV_RXMB_MAX)
719 {
720 not_empty = p_ctrl->p_reg->CFDRMND0 & (1U << buffer);
721 }
722 else if (buffer < (uint32_t) CANFD_RX_BUFFER_FIFO_COMMON_0)
723 {
724 not_empty = !(p_ctrl->p_reg->CFDFESTS & (1U << (buffer - CANFD_PRV_RXMB_MAX)));
725 }
726 else
727 {
728 /* Common FIFO status are grouped together and not channelized, so calculate the index based on the channel. */
729 const uint32_t cfifo_idx = CANFD_PRV_CFIFO_INDEX(buffer - (uint32_t) CANFD_RX_BUFFER_FIFO_COMMON_0,
730 CANFD_INTER_CH(p_ctrl->p_cfg->channel));
731
732 /* Update the buffer to be effectively the cfifo index calculated above. */
733 /* This is needed since r_canfd_mb_read(...) doesn't take a channel number. */
734 buffer = cfifo_idx + (uint32_t) CANFD_RX_BUFFER_FIFO_COMMON_0;
735
736 not_empty = (~p_ctrl->p_reg->CFDFESTS & (1U << (R_CANFD_CFDFESTS_CFXEMP_Pos + cfifo_idx))) != 0;
737 }
738
739 FSP_ERROR_RETURN(not_empty, FSP_ERR_BUFFER_EMPTY);
740
741 /* Retrieve message from buffer */
742 r_canfd_mb_read(p_ctrl->p_reg, buffer, p_frame);
743
744 return FSP_SUCCESS;
745 }
746
747 /***************************************************************************************************************//**
748 * Switch to a different channel, global or test mode.
749 *
750 * Example:
751 * @snippet r_canfd_example.c R_CANFD_ModeTransition
752 *
753 * @retval FSP_SUCCESS Operation succeeded.
754 * @retval FSP_ERR_NOT_OPEN Control block not open.
755 * @retval FSP_ERR_ASSERTION Null pointer presented
756 * @retval FSP_ERR_INVALID_MODE Cannot change to the requested mode from the current global mode.
757 *****************************************************************************************************************/
R_CANFD_ModeTransition(can_ctrl_t * const p_api_ctrl,can_operation_mode_t operation_mode,can_test_mode_t test_mode)758 fsp_err_t R_CANFD_ModeTransition (can_ctrl_t * const p_api_ctrl,
759 can_operation_mode_t operation_mode,
760 can_test_mode_t test_mode)
761 {
762 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
763 fsp_err_t err = FSP_SUCCESS;
764 #if CANFD_CFG_PARAM_CHECKING_ENABLE
765 FSP_ASSERT(NULL != p_ctrl);
766 FSP_ERROR_RETURN(p_ctrl->open == CANFD_OPEN, FSP_ERR_NOT_OPEN);
767
768 /* Get Global Status */
769 uint32_t cfdgsts = p_ctrl->p_reg->CFDGSTS;
770
771 #if !BSP_FEATURE_CANFD_LITE
772
773 /* Check to ensure the current mode is Global Halt when transitioning into or out of Internal Bus mode */
774 FSP_ERROR_RETURN((cfdgsts & R_CANFD_CFDGSTS_GHLTSTS_Msk) || !((p_ctrl->test_mode != test_mode) &&
775 ((CAN_TEST_MODE_INTERNAL_BUS == p_ctrl->test_mode) ||
776 (CAN_TEST_MODE_INTERNAL_BUS == test_mode))),
777 FSP_ERR_INVALID_MODE);
778 #else
779
780 /* Internal Bus mode is not supported on this MCU */
781 FSP_ERROR_RETURN(CAN_TEST_MODE_INTERNAL_BUS != test_mode, FSP_ERR_INVALID_MODE);
782 #endif
783
784 /* Check to ensure the current mode is Global Reset when transitioning into or out of Global Sleep (see Section
785 * 32.3.2 "Global Modes" in the RA6M5 User's Manual (R01UH0891EJ0100) for details) */
786 FSP_ERROR_RETURN(((cfdgsts & R_CANFD_CFDGSTS_GRSTSTS_Msk) && (CAN_OPERATION_MODE_RESET & operation_mode)) ||
787 (!(cfdgsts & R_CANFD_CFDGSTS_GSLPSTS_Msk) && (CAN_OPERATION_MODE_GLOBAL_SLEEP != operation_mode)),
788 FSP_ERR_INVALID_MODE);
789
790 /* Check to ensure the current Global mode supports the requested Channel mode, if applicable. The requested mode
791 * and the current global mode are converted into a number 0-3 corresponding to Operation, Halt, Reset and Sleep
792 * respectively. The channel mode cannot be switched to a mode with an index lower than the current global mode. */
793 if (operation_mode < CAN_OPERATION_MODE_GLOBAL_OPERATION)
794 {
795 FSP_ERROR_RETURN(g_mode_order[operation_mode] >= g_mode_order[cfdgsts & CANFD_PRV_CTR_MODE_MASK],
796 FSP_ERR_INVALID_MODE);
797 }
798 #endif
799
800 uint32_t interlaced_channel = CANFD_INTER_CH(p_ctrl->p_cfg->channel);
801
802 if (p_ctrl->test_mode != test_mode)
803 {
804 #if !BSP_FEATURE_CANFD_LITE
805
806 /* Follow the procedure for switching to Internal Bus mode given in Section 32.9.2.2 "Internal CAN Bus
807 * Communication Test Mode" of the RA6M5 User's Manual (R01UH0891EJ0100) */
808 if (CAN_TEST_MODE_INTERNAL_BUS == test_mode)
809 {
810 /* Disable channel test mode */
811 p_ctrl->p_reg->CFDC[interlaced_channel].CTR_b.CTME = 0;
812
813 /* Link channel to internal bus */
814 p_ctrl->p_reg->CFDGTSTCFG |= 1U << interlaced_channel;
815
816 /* Enable internal bus test mode */
817 p_ctrl->p_reg->CFDGTSTCTR = 1;
818 }
819 else
820 #endif
821 {
822 #if !BSP_FEATURE_CANFD_LITE
823 if (p_ctrl->test_mode == CAN_TEST_MODE_INTERNAL_BUS)
824 {
825 /* Unlink channel from internal bus */
826 p_ctrl->p_reg->CFDGTSTCFG &= ~(1U << interlaced_channel);
827
828 /* Disable global test mode if no channels are linked */
829 if (!p_ctrl->p_reg->CFDGTSTCFG)
830 {
831 p_ctrl->p_reg->CFDGTSTCTR = 0;
832 }
833 }
834 #endif
835
836 /* Transition to Channel Halt when changing test modes */
837 r_canfd_mode_transition(p_ctrl, CAN_OPERATION_MODE_HALT);
838
839 /* Set channel test mode */
840 uint32_t cfdcnctr = p_ctrl->p_reg->CFDC[interlaced_channel].CTR;
841 cfdcnctr &= ~(R_CANFD_CFDC_CTR_CTME_Msk | R_CANFD_CFDC_CTR_CTMS_Msk);
842 p_ctrl->p_reg->CFDC[interlaced_channel].CTR = cfdcnctr |
843 ((uint32_t) test_mode << R_CANFD_CFDC_CTR_CTME_Pos);
844 }
845
846 p_ctrl->test_mode = test_mode;
847 }
848
849 if (p_ctrl->operation_mode != operation_mode)
850 {
851 r_canfd_mode_transition(p_ctrl, operation_mode);
852 }
853
854 return err;
855 }
856
857 /***************************************************************************************************************//**
858 * Get CANFD state and status information for the channel.
859 *
860 * @retval FSP_SUCCESS Operation succeeded.
861 * @retval FSP_ERR_NOT_OPEN Control block not open.
862 * @retval FSP_ERR_ASSERTION Null pointer presented
863 *****************************************************************************************************************/
R_CANFD_InfoGet(can_ctrl_t * const p_api_ctrl,can_info_t * const p_info)864 fsp_err_t R_CANFD_InfoGet (can_ctrl_t * const p_api_ctrl, can_info_t * const p_info)
865 {
866 #if CANFD_CFG_PARAM_CHECKING_ENABLE
867 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
868
869 /* Check pointers for NULL values */
870 FSP_ASSERT(NULL != p_ctrl);
871 FSP_ASSERT(NULL != p_info);
872
873 /* If channel is not open, return an error */
874 FSP_ERROR_RETURN(p_ctrl->open == CANFD_OPEN, FSP_ERR_NOT_OPEN);
875 #else
876 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
877 #endif
878
879 uint32_t interlaced_channel = CANFD_INTER_CH(p_ctrl->p_cfg->channel);
880
881 uint32_t cfdcnsts = p_ctrl->p_reg->CFDC[interlaced_channel].STS;
882 p_info->status = cfdcnsts & UINT16_MAX;
883 p_info->error_count_receive = (uint8_t) ((cfdcnsts & R_CANFD_CFDC_STS_REC_Msk) >> R_CANFD_CFDC_STS_REC_Pos);
884 p_info->error_count_transmit = (uint8_t) ((cfdcnsts & R_CANFD_CFDC_STS_TEC_Msk) >> R_CANFD_CFDC_STS_TEC_Pos);
885 p_info->error_code = p_ctrl->p_reg->CFDC[interlaced_channel].ERFL & UINT16_MAX;
886 p_info->rx_mb_status = p_ctrl->p_reg->CFDRMND0;
887 p_info->rx_fifo_status = (~p_ctrl->p_reg->CFDFESTS) &
888 (R_CANFD_CFDFESTS_RFXEMP_Msk | R_CANFD_CFDFESTS_CFXEMP_Msk);
889
890 /* Clear error flags */
891 p_ctrl->p_reg->CFDC[interlaced_channel].ERFL &= ~((uint32_t) UINT16_MAX);
892
893 return FSP_SUCCESS;
894 }
895
896 /*******************************************************************************************************************//**
897 * Updates the user callback with the option to provide memory for the callback argument structure.
898 * Implements @ref can_api_t::callbackSet.
899 *
900 * @retval FSP_SUCCESS Callback updated successfully.
901 * @retval FSP_ERR_ASSERTION A required pointer is NULL.
902 * @retval FSP_ERR_NOT_OPEN The control block has not been opened.
903 * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL.
904 **********************************************************************************************************************/
R_CANFD_CallbackSet(can_ctrl_t * const p_api_ctrl,void (* p_callback)(can_callback_args_t *),void const * const p_context,can_callback_args_t * const p_callback_memory)905 fsp_err_t R_CANFD_CallbackSet (can_ctrl_t * const p_api_ctrl,
906 void ( * p_callback)(can_callback_args_t *),
907 void const * const p_context,
908 can_callback_args_t * const p_callback_memory)
909 {
910 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) p_api_ctrl;
911
912 #if CANFD_CFG_PARAM_CHECKING_ENABLE
913 FSP_ASSERT(p_ctrl);
914 FSP_ASSERT(p_callback);
915 FSP_ERROR_RETURN(CANFD_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
916 #endif
917
918 #if BSP_TZ_SECURE_BUILD
919
920 /* Get security state of p_callback */
921 bool callback_is_secure =
922 (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
923
924 #if CANFD_CFG_PARAM_CHECKING_ENABLE
925
926 /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */
927 can_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory,
928 CMSE_AU_NONSECURE);
929 FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY);
930 #endif
931 #endif
932
933 /* Store callback and context */
934 #if BSP_TZ_SECURE_BUILD
935 p_ctrl->p_callback = callback_is_secure ? p_callback :
936 (void (*)(can_callback_args_t *))cmse_nsfptr_create(p_callback);
937 #else
938 p_ctrl->p_callback = p_callback;
939 #endif
940 p_ctrl->p_context = p_context;
941 p_ctrl->p_callback_memory = p_callback_memory;
942
943 return FSP_SUCCESS;
944 }
945
946 /*******************************************************************************************************************//**
947 * @} (end addtogroup CAN)
948 **********************************************************************************************************************/
949
950 /***********************************************************************************************************************
951 * Private Functions
952 **********************************************************************************************************************/
953 #if CANFD_CFG_PARAM_CHECKING_ENABLE
r_canfd_bit_timing_parameter_check(can_bit_timing_cfg_t * const p_bit_timing,bool is_data_phase)954 static bool r_canfd_bit_timing_parameter_check (can_bit_timing_cfg_t * const p_bit_timing, bool is_data_phase)
955 {
956 /* Check that prescaler is in range */
957 FSP_ERROR_RETURN((p_bit_timing->baud_rate_prescaler <= CANFD_BAUD_RATE_PRESCALER_MAX) &&
958 (p_bit_timing->baud_rate_prescaler >= CANFD_BAUD_RATE_PRESCALER_MIN),
959 false);
960
961 /* Check that TSEG1 > TSEG2 >= SJW for nominal bitrate and that TSEG1 >= TSEG2 >= SJW for data bitrate per section
962 * 32.4.1.1 "Bit Timing Conditions" in the RA6M5 User's Manual (R01UH0891EJ0100). */
963
964 #if BSP_FEATURE_CANFD_FD_SUPPORT
965 if (is_data_phase)
966 {
967 /* Check Time Segment 1 is greater than or equal to Time Segment 2 */
968 FSP_ERROR_RETURN((uint32_t) p_bit_timing->time_segment_1 >= (uint32_t) p_bit_timing->time_segment_2, false);
969 }
970 else
971 #else
972
973 /* Data phase is only avaiable for FD mode. */
974 FSP_PARAMETER_NOT_USED(is_data_phase);
975 #endif
976 {
977 /* Check Time Segment 1 is greater than Time Segment 2 */
978 FSP_ERROR_RETURN((uint32_t) p_bit_timing->time_segment_1 > (uint32_t) p_bit_timing->time_segment_2, false);
979 }
980
981 /* Check Time Segment 2 is greater than or equal to the synchronization jump width */
982 FSP_ERROR_RETURN((uint32_t) p_bit_timing->time_segment_2 >= (uint32_t) p_bit_timing->synchronization_jump_width,
983 false);
984
985 return true;
986 }
987
988 #endif
989
990 /*******************************************************************************************************************//**
991 * Read from a Message Buffer or FIFO.
992 *
993 * NOTE: Does not index FIFOs.
994 *
995 * @param[in] p_reg Pointer to the CANFD registers
996 * @param[in] buffer Index of buffer to read from (MBs 0-31, FIFOs 32+)
997 * @param[in] frame Pointer to CAN frame to write to
998 **********************************************************************************************************************/
r_canfd_mb_read(R_CANFD_Type * p_reg,uint32_t buffer,can_frame_t * const frame)999 static void r_canfd_mb_read (R_CANFD_Type * p_reg, uint32_t buffer, can_frame_t * const frame)
1000 {
1001 const bool is_mb = buffer < CANFD_PRV_RXMB_MAX;
1002 const bool is_cfifo = buffer >= (uint32_t) CANFD_RX_BUFFER_FIFO_COMMON_0;
1003
1004 /* Get pointer to message buffer (FIFOs use the same buffer structure) */
1005 volatile R_CANFD_CFDRM_RM_TYPE * mb_regs;
1006 if (is_mb)
1007 {
1008 mb_regs = CANFD_PRV_RXMB_PTR(buffer);
1009 }
1010 else if (is_cfifo)
1011 {
1012 mb_regs = (volatile R_CANFD_CFDRM_RM_TYPE *) &(p_reg->CFDCF[buffer - (uint32_t) CANFD_RX_BUFFER_FIFO_COMMON_0]);
1013 }
1014 else
1015 {
1016 mb_regs = (volatile R_CANFD_CFDRM_RM_TYPE *) &(p_reg->CFDRF[buffer - CANFD_PRV_RXMB_MAX]);
1017 }
1018
1019 /* Get frame data. */
1020 uint32_t id = mb_regs->ID;
1021
1022 /* Get the frame type */
1023 frame->type = (can_frame_type_t) ((id & CANFD_PRV_RMRTR_MASK) >> CANFD_PRV_RMRTR_POSITION);
1024
1025 #if BSP_FEATURE_CANFD_FD_SUPPORT
1026
1027 /* Get FD status bits (ESI, BRS and FDF) */
1028 frame->options = mb_regs->FDSTS & 7U;
1029 #else
1030 frame->options = 0U;
1031 #endif
1032
1033 /* Get the frame ID */
1034 frame->id = id & CANFD_PRV_RMID_MASK;
1035
1036 /* Get the frame ID mode (IDE bit) */
1037 frame->id_mode = (can_id_mode_t) (id >> CANFD_PRV_RMIDE_POSITION);
1038
1039 /* Get the frame data length code */
1040 frame->data_length_code = dlc_to_bytes[mb_regs->PTR >> CANFD_PRV_RMDLC_POSITION];
1041
1042 /* Copy data to frame */
1043 uint32_t len = frame->data_length_code;
1044 uint8_t * p_dest = frame->data;
1045 uint8_t * p_src = (uint8_t *) mb_regs->DF;
1046 while (len--)
1047 {
1048 *p_dest++ = *p_src++;
1049 }
1050
1051 if (is_mb)
1052 {
1053 /* Clear RXMB New Data bit */
1054 p_reg->CFDRMND0 &= ~(1U << buffer);
1055 }
1056 else if (is_cfifo)
1057 {
1058 /* Increment the Common FIFO pointer. */
1059 p_reg->CFDCFPCTR[buffer - (uint32_t) CANFD_RX_BUFFER_FIFO_COMMON_0] = R_CANFD_CFDCFPCTR_CFPC_Msk;
1060 }
1061 else
1062 {
1063 /* Increment RX FIFO pointer */
1064 p_reg->CFDRFPCTR[buffer - CANFD_PRV_RXMB_MAX] = UINT8_MAX;
1065 }
1066 }
1067
1068 /*******************************************************************************************************************//**
1069 * Calls user callback.
1070 *
1071 * @param[in] p_ctrl Pointer to CAN instance control block
1072 * @param[in] p_args Pointer to arguments on stack
1073 **********************************************************************************************************************/
r_canfd_call_callback(canfd_instance_ctrl_t * p_ctrl,can_callback_args_t * p_args)1074 static void r_canfd_call_callback (canfd_instance_ctrl_t * p_ctrl, can_callback_args_t * p_args)
1075 {
1076 can_callback_args_t args;
1077
1078 /* Store callback arguments in memory provided by user if available. This allows callback arguments to be
1079 * stored in non-secure memory so they can be accessed by a non-secure callback function. */
1080 can_callback_args_t * p_args_memory = p_ctrl->p_callback_memory;
1081 if (NULL == p_args_memory)
1082 {
1083 /* Use provided args struct on stack */
1084 p_args_memory = p_args;
1085 }
1086 else
1087 {
1088 /* Save current arguments on the stack in case this is a nested interrupt. */
1089 args = *p_args_memory;
1090
1091 /* Copy the stacked args to callback memory */
1092 *p_args_memory = *p_args;
1093 }
1094
1095 #if BSP_TZ_SECURE_BUILD
1096
1097 /* p_callback can point to a secure function or a non-secure function. */
1098 if (!cmse_is_nsfptr(p_ctrl->p_callback))
1099 {
1100 /* If p_callback is secure, then the project does not need to change security state. */
1101 p_ctrl->p_callback(p_args_memory);
1102 }
1103 else
1104 {
1105 /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */
1106 canfd_prv_ns_callback p_callback = (canfd_prv_ns_callback) (p_ctrl->p_callback);
1107 p_callback(p_args_memory);
1108 }
1109
1110 #else
1111
1112 /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */
1113 p_ctrl->p_callback(p_args_memory);
1114 #endif
1115
1116 if (NULL != p_ctrl->p_callback_memory)
1117 {
1118 /* Restore callback memory in case this is a nested interrupt. */
1119 *p_ctrl->p_callback_memory = args;
1120 }
1121 }
1122
1123 /*******************************************************************************************************************//**
1124 * Global Error Handler.
1125 *
1126 * Handles the Global Error IRQ for a given instance of CANFD.
1127 **********************************************************************************************************************/
r_candfd_global_error_handler(uint32_t instance)1128 static void r_candfd_global_error_handler (uint32_t instance)
1129 {
1130 canfd_instance_ctrl_t * p_ctrl = gp_ctrl[instance];
1131
1132 can_callback_args_t args = {0U};
1133
1134 args.event = CAN_EVENT_ERR_GLOBAL;
1135
1136 /* Read global error flags. */
1137 uint32_t cfdgerfl = p_ctrl->p_reg->CFDGERFL;
1138
1139 /* Global errors are in the top halfword of canfd_error_t; move and preserve ECC error flags. */
1140 args.error = ((cfdgerfl & UINT16_MAX) << 16) + ((cfdgerfl >> 16) << 28);
1141
1142 /* Clear global error flags. */
1143 p_ctrl->p_reg->CFDGERFL = 0;
1144
1145 if (args.error & CANFD_ERROR_GLOBAL_MESSAGE_LOST)
1146 {
1147 /* Get lowest RX FIFO with Message Lost condition and clear the flag */
1148 args.buffer = __CLZ(__RBIT(p_ctrl->p_reg->CFDFMSTS));
1149 p_ctrl->p_reg->CFDRFSTS[args.buffer] &= ~R_CANFD_CFDRFSTS_RFMLT_Msk;
1150 }
1151
1152 /* Set channel and context based on selected global error handler channel. */
1153 args.channel = CANFD_CFG_GLOBAL_ERROR_CH;
1154 args.p_context = p_ctrl->p_context;
1155
1156 /* Set remaining arguments and call callback */
1157 r_canfd_call_callback(p_ctrl, &args);
1158 }
1159
1160 /*******************************************************************************************************************//**
1161 * Error ISR.
1162 *
1163 * Saves context if RTOS is used, clears interrupts, calls common error function, and restores context if RTOS is used.
1164 **********************************************************************************************************************/
canfd_error_isr(void)1165 void canfd_error_isr (void)
1166 {
1167 /* Save context if RTOS is used */
1168 FSP_CONTEXT_SAVE
1169
1170 /* Get IRQ and context */
1171 IRQn_Type irq = R_FSP_CurrentIrqGet();
1172
1173 if (VECTOR_NUMBER_CAN_GLERR == irq)
1174 {
1175 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
1176
1177 /* If there are seperate instances of CANFD, then loop over each instance to handle the source of the global
1178 * error IRQ. */
1179 for (uint32_t i = 0; i < BSP_FEATURE_CANFD_NUM_INSTANCES; i++)
1180 {
1181 if (NULL != gp_ctrl[i])
1182 {
1183 r_candfd_global_error_handler(i);
1184 }
1185 }
1186
1187 #else
1188 r_candfd_global_error_handler(CANFD_CFG_GLOBAL_ERROR_CH);
1189 #endif
1190 }
1191 else
1192 {
1193 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1194
1195 can_callback_args_t args = {0U};
1196 canfd_instance_ctrl_t * p_callback_ctrl;
1197
1198 args.event = CAN_EVENT_ERR_CHANNEL;
1199
1200 /* Read and clear channel error flags. */
1201 uint32_t interlaced_channel = CANFD_INTER_CH(p_ctrl->p_cfg->channel);
1202 args.error = p_ctrl->p_reg->CFDC[interlaced_channel].ERFL & UINT16_MAX; // Upper halfword contains latest CRC
1203 p_ctrl->p_reg->CFDC[interlaced_channel].ERFL = 0;
1204
1205 /* Choose the channel provided by the interrupt context. */
1206 p_callback_ctrl = p_ctrl;
1207
1208 args.channel = interlaced_channel;
1209 args.p_context = p_ctrl->p_context;
1210 args.buffer = 0U;
1211
1212 /* Set remaining arguments and call callback */
1213 r_canfd_call_callback(p_callback_ctrl, &args);
1214 }
1215
1216 /* Clear IRQ */
1217 R_BSP_IrqStatusClear(irq);
1218
1219 /* Restore context if RTOS is used */
1220 FSP_CONTEXT_RESTORE
1221 }
1222
1223 /*******************************************************************************************************************//**
1224 * Receive FIFO handler.
1225 *
1226 * Handles the Receive IRQ for a given instance of CANFD.
1227 **********************************************************************************************************************/
r_canfd_rx_fifo_handler(uint32_t instance)1228 static void r_canfd_rx_fifo_handler (uint32_t instance)
1229 {
1230 can_callback_args_t args;
1231 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
1232 R_CANFD_Type * p_reg =
1233 (R_CANFD_Type *) ((uint32_t) R_CANFD0 + (instance * ((uint32_t) R_CANFD1 - (uint32_t) R_CANFD0)));
1234 #else
1235 FSP_PARAMETER_NOT_USED(instance);
1236 R_CANFD_Type * p_reg = R_CANFD;
1237 #endif
1238
1239 /* Get lowest FIFO requesting interrupt */
1240 uint32_t fifo = __CLZ(__RBIT(p_reg->CFDRFISTS));
1241
1242 /* Only perform ISR duties if a FIFO has requested it */
1243 if (fifo < CANFD_PRV_RX_FIFO_MAX)
1244 {
1245 /* Set static arguments */
1246 args.event = CAN_EVENT_RX_COMPLETE;
1247 args.buffer = fifo + CANFD_PRV_RXMB_MAX;
1248
1249 /* Read from the FIFO until it is empty */
1250 while (!(p_reg->CFDFESTS & (1U << fifo)))
1251 {
1252 /* Get channel associated with the AFL entry */
1253 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
1254 args.channel = instance;
1255 #else
1256 args.channel = p_reg->CFDRF[fifo].FDSTS_b.RFIFL;
1257 #endif
1258
1259 /* Read and index FIFO */
1260 r_canfd_mb_read(p_reg, fifo + CANFD_PRV_RXMB_MAX, &args.frame);
1261
1262 /* Set the remaining callback arguments */
1263 args.p_context = gp_ctrl[args.channel]->p_context;
1264 r_canfd_call_callback(gp_ctrl[args.channel], &args);
1265 }
1266
1267 /* Clear RX FIFO Interrupt Flag */
1268 p_reg->CFDRFSTS[fifo] &= ~R_CANFD_CFDRFSTS_RFIF_Msk;
1269 }
1270
1271 if (!p_reg->CFDRFISTS)
1272 {
1273 /* Clear interrupt in NVIC if there are no pending RX FIFO IRQs */
1274 R_BSP_IrqStatusClear(VECTOR_NUMBER_CAN_RXF);
1275 }
1276 }
1277
1278 /*******************************************************************************************************************//**
1279 * Receive ISR.
1280 *
1281 * Saves context if RTOS is used, clears interrupts, calls common receive function
1282 * and restores context if RTOS is used.
1283 **********************************************************************************************************************/
canfd_rx_fifo_isr(void)1284 void canfd_rx_fifo_isr (void)
1285 {
1286 /* Save context if RTOS is used */
1287 FSP_CONTEXT_SAVE
1288
1289 #if BSP_FEATURE_CANFD_NUM_INSTANCES > 1
1290
1291 /* If there are seperate instances of CANFD, then loop over each instance to handle the source of the global
1292 * receive IRQ. */
1293 for (uint32_t i = 0; i < BSP_FEATURE_CANFD_NUM_INSTANCES; i++)
1294 {
1295 if (NULL != gp_ctrl[i])
1296 {
1297 r_canfd_rx_fifo_handler(i);
1298 }
1299 }
1300
1301 #else
1302 r_canfd_rx_fifo_handler(0U);
1303 #endif
1304
1305 /* Restore context if RTOS is used */
1306 FSP_CONTEXT_RESTORE
1307 }
1308
1309 /*******************************************************************************************************************//**
1310 * Transmit ISR.
1311 *
1312 * Saves context if RTOS is used, clears interrupts, calls common transmit function
1313 * and restores context if RTOS is used.
1314 **********************************************************************************************************************/
canfd_channel_tx_isr(void)1315 void canfd_channel_tx_isr (void)
1316 {
1317 /* Save context if RTOS is used */
1318 FSP_CONTEXT_SAVE
1319
1320 IRQn_Type irq = R_FSP_CurrentIrqGet();
1321 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1322 canfd_extended_cfg_t * p_extend = (canfd_extended_cfg_t *) p_ctrl->p_cfg->p_extend;
1323 uint32_t channel = p_ctrl->p_cfg->channel;
1324
1325 /* Set static arguments */
1326 can_callback_args_t args;
1327 args.channel = channel;
1328 args.p_context = p_ctrl->p_context;
1329
1330 uint32_t interlaced_channel = CANFD_INTER_CH(channel);
1331
1332 /* Check the byte of CFDGTINTSTS0 that corresponds to the interrupting channel */
1333 volatile uint8_t * p_cfdgtintsts = (((volatile uint8_t *) &p_ctrl->p_reg->CFDGTINTSTS0) + interlaced_channel);
1334 while (*p_cfdgtintsts)
1335 {
1336 bool is_cfifo = false;
1337 uint32_t txmb;
1338 volatile uint32_t * p_cfdtm_sts;
1339 const uint32_t cfdgtintsts = *p_cfdgtintsts;
1340
1341 interlaced_channel <<= 1;
1342
1343 /* Get relevant TX status register bank */
1344 if (cfdgtintsts & R_CANFD_CFDGTINTSTS0_TSIF0_Msk)
1345 {
1346 p_cfdtm_sts = (volatile uint32_t *) &p_ctrl->p_reg->CFDTMTCSTS[interlaced_channel];
1347 args.event = CAN_EVENT_TX_COMPLETE;
1348 }
1349 else if (cfdgtintsts & R_CANFD_CFDGTINTSTS0_CFTIF0_Msk)
1350 {
1351 is_cfifo = true;
1352 #if CANFD_PRV_CFIFO_HAS_ISTS
1353 p_cfdtm_sts = &p_ctrl->p_reg->CFDCFTISTS;
1354 #endif
1355 args.event = (p_extend->p_global_cfg->common_fifo_config[interlaced_channel] & R_CANFD_CFDCFCC_CFIM_Msk) ?
1356 CAN_EVENT_TX_COMPLETE : CAN_EVENT_TX_FIFO_EMPTY;
1357 }
1358 else
1359 {
1360 p_cfdtm_sts = (volatile uint32_t *) &p_ctrl->p_reg->CFDTMTASTS[interlaced_channel];
1361 args.event = CAN_EVENT_TX_ABORTED;
1362 }
1363
1364 interlaced_channel >>= 1;
1365
1366 /* Calculate lowest TXMB with the specified event */
1367 if (!is_cfifo)
1368 {
1369 txmb = __CLZ(__RBIT(*p_cfdtm_sts));
1370 txmb = (txmb < 8) ? txmb : __CLZ(__RBIT(*(p_cfdtm_sts + 1))) + CANFD_PRV_TXMB_OFFSET;
1371
1372 /* Clear TX complete/abort flags */
1373 p_ctrl->p_reg->CFDTMSTS_b[txmb + (CANFD_PRV_TXMB_CHANNEL_OFFSET * interlaced_channel)].TMTRF = 0;
1374 }
1375 else
1376 {
1377 #if CANFD_PRV_CFIFO_HAS_ISTS
1378
1379 /* Adjust txmb with the lowest indexed Common FIFO that could have triggered this event.
1380 * Mask out only the Common FIFOs associated with this channel. */
1381 uint32_t cfdtm_mask = ((1U << CANFD_PRV_COMMON_FIFO_MAX) - 1U) <<
1382 (interlaced_channel * CANFD_PRV_COMMON_FIFO_MAX);
1383 txmb = __CLZ(__RBIT(*p_cfdtm_sts & cfdtm_mask));
1384 #else
1385 txmb = 0;
1386 #endif
1387
1388 /* Clear the interrupt flag for Common FIFO TX. */
1389 p_ctrl->p_reg->CFDCFSTS[txmb] &= ~R_CANFD_CFDCFSTS_CFTXIF_Msk;
1390
1391 /* Add the Common FIFO offset so the correct type of buffer will be available in the callback. */
1392 txmb += CANFD_TX_BUFFER_FIFO_COMMON_0;
1393 }
1394
1395 /* Set the callback arguments */
1396 args.buffer = txmb;
1397 r_canfd_call_callback(p_ctrl, &args);
1398 }
1399
1400 /* Clear interrupt */
1401 R_BSP_IrqStatusClear(irq);
1402
1403 /* Restore context if RTOS is used */
1404 FSP_CONTEXT_RESTORE
1405 }
1406
1407 /*******************************************************************************************************************//**
1408 * Common FIFO Receive ISR.
1409 *
1410 * Saves context if RTOS is used, clears interrupts, calls common receive function
1411 * and restores context if RTOS is used.
1412 **********************************************************************************************************************/
canfd_common_fifo_rx_isr(void)1413 void canfd_common_fifo_rx_isr (void)
1414 {
1415 /* Save context if RTOS is used */
1416 FSP_CONTEXT_SAVE
1417
1418 IRQn_Type irq = R_FSP_CurrentIrqGet();
1419 canfd_instance_ctrl_t * p_ctrl = (canfd_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1420 uint32_t channel = p_ctrl->p_cfg->channel;
1421 can_callback_args_t args;
1422
1423 #if CANFD_PRV_CFIFO_HAS_ISTS
1424
1425 /* Get lowest FIFO requesting interrupt */
1426
1427 /* To satisfy clang-tidy mask out the index. A value of 32 only happens if no flag is set which shouldn't happen in
1428 * this ISR. If it does for some reason, the while loop below will be bypassed since the associated flag being
1429 * checked will be ignored. */
1430 uint32_t fifo = __CLZ(__RBIT(p_ctrl->p_reg->CFDCFRISTS & R_CANFD_CFDCFRISTS_CFXRXIF_Msk)) & 0x1FU;
1431 #else
1432 uint32_t fifo = 0;
1433 #endif
1434
1435 /* Set static arguments */
1436 args.event = CAN_EVENT_RX_COMPLETE;
1437 args.channel = channel;
1438
1439 #if BSP_FEATURE_CANFD_NUM_CHANNELS > 1
1440
1441 /* Get the channel based fifo index to get the currect buffer value. */
1442 if (fifo > CANFD_PRV_CFIFO_CHANNEL_OFFSET)
1443 {
1444 args.buffer = fifo % (CANFD_PRV_CFIFO_CHANNEL_OFFSET + 1);
1445 }
1446 else
1447 {
1448 args.buffer = fifo;
1449 }
1450
1451 #else
1452 args.buffer = fifo;
1453 #endif
1454
1455 /* Move buffer up to the correct range. */
1456 args.buffer += (uint32_t) CANFD_RX_BUFFER_FIFO_COMMON_0;
1457
1458 /* Read from the FIFO until it is empty */
1459 while (!(p_ctrl->p_reg->CFDFESTS & (1U << (R_CANFD_CFDFESTS_CFXEMP_Pos + fifo))))
1460 {
1461 /* Read and index FIFO */
1462 /* buffer is slightly different in this function since it operates globally. */
1463 r_canfd_mb_read(p_ctrl->p_reg, fifo + (uint32_t) CANFD_RX_BUFFER_FIFO_COMMON_0, &args.frame);
1464
1465 /* Set the remaining callback arguments */
1466 args.p_context = gp_ctrl[args.channel]->p_context;
1467 r_canfd_call_callback(gp_ctrl[args.channel], &args);
1468 }
1469
1470 /* Clear Common FIFO RX Interrupt Flag */
1471 p_ctrl->p_reg->CFDCFSTS[fifo] &= ~R_CANFD_CFDCFSTS_CFRXIF_Msk;
1472
1473 #if CANFD_PRV_CFIFO_HAS_ISTS
1474 if (!p_ctrl->p_reg->CFDCFRISTS)
1475 #else
1476
1477 /* This device is single channel and single Common FIFO. */
1478 if (!(p_ctrl->p_reg->CFDCFSTS[0] & R_CANFD_CFDCFSTS_CFRXIF_Msk))
1479 #endif
1480 {
1481 /* Clear interrupt in NVIC if there are no pending RX FIFO IRQs */
1482 R_BSP_IrqStatusClear(irq);
1483 }
1484
1485 /* Restore context if RTOS is used */
1486 FSP_CONTEXT_RESTORE
1487 }
1488
1489 /*******************************************************************************************************************//**
1490 * This function is used to switch the CANFD peripheral operation mode.
1491 * @param[in] p_ctrl - pointer to control structure
1492 * @param[in] operation_mode - destination operation mode
1493 **********************************************************************************************************************/
r_canfd_mode_transition(canfd_instance_ctrl_t * p_ctrl,can_operation_mode_t operation_mode)1494 static void r_canfd_mode_transition (canfd_instance_ctrl_t * p_ctrl, can_operation_mode_t operation_mode)
1495 {
1496 uint32_t interlaced_channel = CANFD_INTER_CH(p_ctrl->p_cfg->channel);
1497
1498 /* Get bit 7 from operation_mode to determine if this is a global mode change request */
1499 bool global_mode = (bool) (operation_mode >> 7);
1500 operation_mode &= 0xF;
1501
1502 if (global_mode)
1503 {
1504 uint32_t cfdgctr = p_ctrl->p_reg->CFDGCTR;
1505
1506 /* If CANFD is transitioning to Global Reset, make sure the FIFOs are disabled. */
1507 if (!(cfdgctr & R_CANFD_CFDGSTS_GRSTSTS_Msk) && (operation_mode & CAN_OPERATION_MODE_RESET))
1508 {
1509 /* Disable RX FIFOs */
1510 for (uint32_t i = 0; i < CANFD_PRV_RX_FIFO_MAX; i++)
1511 {
1512 p_ctrl->p_reg->CFDRFCC[i] &= ~R_CANFD_CFDRFCC_RFE_Msk;
1513 }
1514
1515 /* Disable Common FIFOs */
1516 for (uint32_t i = 0; i < CANFD_PRV_COMMON_FIFO_MAX * BSP_FEATURE_CANFD_NUM_CHANNELS; i++)
1517 {
1518 p_ctrl->p_reg->CFDCFCC[i] &= ~R_CANFD_CFDCFCC_CFE_Msk;
1519 }
1520 }
1521
1522 r_canfd_mode_ctr_set(&p_ctrl->p_reg->CFDGCTR, operation_mode);
1523
1524 /* If CANFD is transitioning out of Reset the FIFOs need to be enabled. */
1525 if ((cfdgctr & R_CANFD_CFDGSTS_GRSTSTS_Msk) && !(operation_mode & CAN_OPERATION_MODE_RESET))
1526 {
1527 /* Get global config */
1528 canfd_global_cfg_t * p_global_cfg =
1529 ((canfd_extended_cfg_t *) p_ctrl->p_cfg->p_extend)->p_global_cfg;
1530
1531 /* Enable RX FIFOs */
1532 for (uint32_t i = 0; i < CANFD_PRV_RX_FIFO_MAX; i++)
1533 {
1534 p_ctrl->p_reg->CFDRFCC[i] = p_global_cfg->rx_fifo_config[i];
1535 }
1536 }
1537 }
1538 else
1539 {
1540 uint32_t cfdcnctr = p_ctrl->p_reg->CFDC[interlaced_channel].CTR;
1541
1542 if (((cfdcnctr & R_CANFD_CFDC_CTR_CSLPR_Msk) && (!(CAN_OPERATION_MODE_RESET & operation_mode))) ||
1543 ((!(cfdcnctr & CANFD_PRV_CTR_RESET_BIT)) && (CAN_OPERATION_MODE_SLEEP == operation_mode)))
1544 {
1545 /* Transition channel to Reset if a transition to/from Sleep is requested (see Section 32.3.3 "Channel
1546 * Modes" in the RA6M5 User's Manual (R01UH0891EJ0100) for details) */
1547 r_canfd_mode_ctr_set(&p_ctrl->p_reg->CFDC[interlaced_channel].CTR, CAN_OPERATION_MODE_RESET);
1548 }
1549
1550 /* Request transition to selected mode */
1551 r_canfd_mode_ctr_set(&p_ctrl->p_reg->CFDC[interlaced_channel].CTR, operation_mode);
1552
1553 /* If CANFD is transitioning from Reset, make sure the Common FIFOs are enabled.
1554 * The FIFOs will be disabled automatically if configured for TX and the channel is transitioned to reset. */
1555 if ((cfdcnctr & R_CANFD_CFDC_CTR_CHMDC_Msk) && !(operation_mode & CAN_OPERATION_MODE_RESET))
1556 {
1557 /* Get global config */
1558 canfd_global_cfg_t * p_global_cfg =
1559 ((canfd_extended_cfg_t *) p_ctrl->p_cfg->p_extend)->p_global_cfg;
1560
1561 const uint32_t ch_offset = interlaced_channel * CANFD_PRV_COMMON_FIFO_MAX;
1562
1563 /* Enable Common FIFOs */
1564 for (uint32_t i = 0; i < CANFD_PRV_COMMON_FIFO_MAX; i++)
1565 {
1566 p_ctrl->p_reg->CFDCFCC[ch_offset + i] |=
1567 (p_global_cfg->common_fifo_config[ch_offset + i] & R_CANFD_CFDCFCC_CFE_Msk);
1568 }
1569 }
1570 }
1571
1572 p_ctrl->operation_mode =
1573 (can_operation_mode_t) (p_ctrl->p_reg->CFDC[interlaced_channel].CTR & CANFD_PRV_CTR_MODE_MASK);
1574 }
1575
1576 /*******************************************************************************************************************//**
1577 * Sets the provided CTR register to the requested mode and waits for the associated STS register to reflect the change
1578 * @param[in] p_ctr_reg - pointer to control register
1579 * @param[in] operation_mode - requested mode (not including global bits)
1580 **********************************************************************************************************************/
r_canfd_mode_ctr_set(volatile uint32_t * p_ctr_reg,can_operation_mode_t operation_mode)1581 static void r_canfd_mode_ctr_set (volatile uint32_t * p_ctr_reg, can_operation_mode_t operation_mode)
1582 {
1583 volatile uint32_t * p_sts_reg = p_ctr_reg + 1;
1584
1585 /* See definitions for CFDCnCTR, CFDCnSTS, CFDGCTR and CFDGSTS in the RA6M5 User's Manual (R01UH0891EJ0100) */
1586 *p_ctr_reg = (*p_ctr_reg & ~CANFD_PRV_CTR_MODE_MASK) | operation_mode;
1587 FSP_HARDWARE_REGISTER_WAIT((*p_sts_reg & CANFD_PRV_CTR_MODE_MASK), operation_mode);
1588 }
1589
1590 #if BSP_FEATURE_CANFD_FD_SUPPORT
1591
1592 /*******************************************************************************************************************//**
1593 * Converts bytes into a DLC value
1594 * @param[in] bytes Number of payload bytes
1595 **********************************************************************************************************************/
r_canfd_bytes_to_dlc(uint8_t bytes)1596 static uint8_t r_canfd_bytes_to_dlc (uint8_t bytes)
1597 {
1598 if (bytes <= 8)
1599 {
1600 return bytes;
1601 }
1602
1603 if (bytes <= 24)
1604 {
1605 return (uint8_t) (8U + ((bytes - 8U) / 4U));
1606 }
1607
1608 return (uint8_t) (0xDU + ((bytes / 16U) - 2U));
1609 }
1610
1611 #endif
1612