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