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