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