1 /*
2 * Copyright (c) 2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #include "hpm_mcan_drv.h"
8 #include <string.h>
9 #include <assert.h>
10
11 /***********************************************************************************************************************
12 *
13 * Definitions
14 *
15 **********************************************************************************************************************/
16
17 #define MCAN_CAN_BAUDRATE_DEFAULT (500UL * 1000UL) /*!< Default CAN2.0 baudrate:500 kbps */
18 #define MCAN_CANFD_BAUDRATE_DEFAULT (2UL * 1000UL * 1000UL) /*!< Default CANFD baudrate: 2 Mbps */
19
20 /* Hardware restriction of each types of element for MCAN */
21 #define MCAN_STD_FILTER_ELEM_CNT_MAX (128U)
22 #define MCAN_EXT_FILTER_ELEM_CNT_MAX (64U)
23 #define MCAN_RXFIFO_ELEM_CNT_MAX (64U)
24 #define MCAN_RXBUF_ELEM_CNT_MAX (64U)
25 #define MCAN_TXEVT_FIFO_ELEM_CNT_MAX (32U)
26 #define MCAN_TXBUF_ELEM_CNT_MAX (32U)
27
28
29 #define NUM_TQ_SYNC_SEG (1U)
30
31 /**
32 * @brief CAN2.0 Timing related definitions
33 */
34 #define TSEG1_MIN_FOR_CAN2_0 (2U)
35 #define TSEG1_MAX_FOR_CAN2_0 (256U)
36 #define TSEG2_MIN_FOR_CAN2_0 (2U)
37 #define TSEG2_MAX_FOR_CAN2_0 (128U)
38 #define TSJW_MIN_FOR_CAN2_0 (1U)
39 #define TSJW_MAX_FOR_CAN2_0 (128U)
40 #define PRESCALER_MIN_FOR_CAN2_0 (1U)
41 #define PRESCALER_MAX_FOR_CAN2_0 (512U)
42 #define NUM_TQ_MIN_FOR_CAN2_0 (8U)
43 #define NUM_TQ_MAX_FOR_CAN2_0 (TSEG1_MAX_FOR_CAN2_0 + TSEG2_MAX_FOR_CAN2_0)
44
45 /**
46 * @brief CANFD Nominal Timing related definitions
47 */
48 #define TSEG1_MIN_FOR_CANFD_NOMINAL (2U)
49 #define TSEG1_MAX_FOR_CANFD_NOMINAL (256U)
50 #define TSEG2_MIN_FOR_CANFD_NOMINAL (1U)
51 #define TSEG2_MAX_FOR_CANFD_NOMINAL (32U)
52 #define TSJW_MIN_FOR_CANFD_NOMINAL (1U)
53 #define TSJW_MAX_FOR_CANFD_NOMINAL (128U)
54 #define NUM_TQ_MIN_FOR_CANFD_NOMINAL (8U)
55 #define NUM_TQ_MAX_FOR_CANFD_NOMINAL (TSEG1_MAX_FOR_CANFD_NOMINAL + TSEG2_MAX_FOR_CANFD_NOMINAL)
56 #define PRESCALER_MIN_FOR_CANFD_NOMINAL (1U)
57 #define PRESCALER_MAX_FOR_CANFD_NOMINAL (512U)
58
59 /**
60 * @brief CANFD Data Timing related definitions
61 */
62 #define TSEG1_MIN_FOR_CANFD_DATA (2U)
63 #define TSEG1_MAX_FOR_CANFD_DATA (31U)
64 #define TSEG2_MIN_FOR_CANFD_DATA (0U)
65 #define TSEG2_MAX_FOR_CANFD_DATA (15U)
66 #define TSJW_MIN_FOR_CANFD_DATA (0U)
67 #define TSJW_MAX_FOR_CANFD_DATA (15U)
68 #define PRESCALER_MIN_FOR_CANFD_DATA (1U)
69 #define PRESCALER_MAX_FOR_CANFD_DATA (32U)
70
71 #define NUM_TQ_MIN_FOR_CANFD_DATA (8U)
72 #define NUM_TQ_MAX_FOR_CANFD_DATA (TSEG1_MAX_FOR_CANFD_DATA + TSEG2_MAX_FOR_CANFD_DATA)
73
74 #define MIN_TQ_MUL_PRESCALE (8U)
75 #define NUM_PRESCALE_MAX (256U)
76
77 #define CAN_SAMPLEPOINT_MIN (750U)
78 #define CAN_SAMPLEPOINT_MAX (875U)
79
80 /* Invalid start address of MCAN RAM */
81 #define MCAN_RAM_ADDR_INVALID ((1UL << 16) - 1U)
82
83 /* Maximum CAN TDC offset value */
84 #define MCAN_MAX_TDC_OFFSET ((uint32_t)(MCAN_TDCR_TDCO_MASK >> MCAN_TDCR_TDCO_SHIFT))
85
86 /**
87 * @brief MCAN bit timing table
88 */
89 typedef struct mcan_bit_timing_table_struct {
90 uint16_t tq_min; /*!< Minimum Tq */
91 uint16_t tq_max; /*!< Maximum Tq */
92 uint16_t seg1_min; /*!< Minimum TSEG1 */
93 uint16_t seg1_max; /*!< Maximum TSEG1 */
94 uint8_t seg2_min; /*!< Minimum TSEG2 */
95 uint8_t seg2_max; /*!< Maximum TSEG2 */
96 uint8_t sjw_min; /*!< Minimum SJW */
97 uint8_t sjw_max; /*!< Maximum SJW */
98 uint8_t min_diff_seg1_minus_seg2; /*!< Minimum value of (TSEG1 - TSEG2 ) */
99 uint8_t prescaler_min; /*!< Minimum Prescaler value */
100 uint16_t prescaler_max; /*!< Maximum Prescaler value */
101 } mcan_bit_timing_table_t;
102
103 /***********************************************************************************************************************
104 *
105 * Variables
106 *
107 **********************************************************************************************************************/
108 static const mcan_bit_timing_table_t k_mcan_bit_timing_tbl[3] = {
109 /* CAN2.0 bit timing requirement */
110 {
111 /* TQ range */
112 .tq_min = NUM_TQ_MIN_FOR_CAN2_0, .tq_max = NUM_TQ_MAX_FOR_CAN2_0,
113 /* SEG1 range(Including Sync_Seg + Prop_Seg + Phase_Seg1 */
114 .seg1_min = TSEG1_MIN_FOR_CAN2_0, .seg1_max = TSEG1_MAX_FOR_CAN2_0,
115 /* SEG2 Range */
116 .seg2_min = TSEG2_MIN_FOR_CAN2_0, .seg2_max = TSEG2_MAX_FOR_CAN2_0,
117 /* SJW range */
118 .sjw_min = TSJW_MIN_FOR_CAN2_0, .sjw_max = TSJW_MAX_FOR_CAN2_0, .min_diff_seg1_minus_seg2 = 2,
119 /* Prescaler range */
120 .prescaler_min = PRESCALER_MIN_FOR_CAN2_0, .prescaler_max = PRESCALER_MAX_FOR_CAN2_0,
121 },
122 /* CANFD Nominal Bit timing requirement */
123 {
124 /* TQ range */
125 .tq_min = NUM_TQ_MIN_FOR_CANFD_NOMINAL, .tq_max = NUM_TQ_MAX_FOR_CANFD_NOMINAL,
126 /* SEG1 range(Including Sync_Seg + Prop_Seg + Phase_Seg1 */
127 .seg1_min = TSEG1_MIN_FOR_CANFD_NOMINAL, .seg1_max = TSEG1_MAX_FOR_CANFD_NOMINAL,
128 /* SEG2 range */
129 .seg2_min = TSEG2_MIN_FOR_CANFD_NOMINAL, .seg2_max = TSEG2_MAX_FOR_CANFD_NOMINAL,
130 /* SJW range */
131 .sjw_min = TSJW_MIN_FOR_CANFD_NOMINAL, .sjw_max = TSJW_MAX_FOR_CANFD_NOMINAL, .min_diff_seg1_minus_seg2 = 2,
132 /* Prescaler range */
133 .prescaler_min = PRESCALER_MIN_FOR_CANFD_NOMINAL, .prescaler_max = PRESCALER_MAX_FOR_CANFD_NOMINAL
134 },
135 /* CANFD Data Bit timing requirement */
136 {
137 /* TQ range */
138 .tq_min = NUM_TQ_MIN_FOR_CANFD_DATA, .tq_max = NUM_TQ_MAX_FOR_CANFD_DATA,
139 /* SEG1 range(Including Sync_Seg + Prop_Seg + Phase_Seg2 */
140 .seg1_min = TSEG1_MIN_FOR_CANFD_DATA, .seg1_max = TSEG1_MAX_FOR_CANFD_DATA,
141 /* SEG2 range */
142 .seg2_min = TSEG2_MIN_FOR_CANFD_DATA, .seg2_max = TSEG2_MAX_FOR_CANFD_DATA,
143 /* SJW range */
144 .sjw_min = TSJW_MIN_FOR_CANFD_DATA, .sjw_max = TSJW_MAX_FOR_CANFD_DATA, .min_diff_seg1_minus_seg2 = 1,
145 /* Prescaler range */
146 .prescaler_min = PRESCALER_MIN_FOR_CANFD_DATA, .prescaler_max = PRESCALER_MAX_FOR_CANFD_DATA
147 }};
148
149 static const mcan_filter_elem_t k_default_std_id_filter = {
150 /* Use classic filter */
151 .filter_type = MCAN_FILTER_TYPE_CLASSIC_FILTER,
152 /* Store message into RXFIFO0 if matching */
153 .filter_config = MCAN_FILTER_ELEM_CFG_STORE_IN_RX_FIFO0_IF_MATCH,
154 /* For Standard Identify only */
155 .can_id_type = MCAN_CAN_ID_TYPE_STANDARD,
156 /* Sync Message, only evaluated when "CCCR.UTSU" is set */
157 .sync_message = 0U,
158 /* Don't care if mask is set to all 1s */
159 .filter_id = 0U,
160 /* Accept all messages */
161 .filter_mask = 0x7FFU,
162 };
163
164 static const mcan_filter_elem_t k_default_ext_id_filter = {
165 /* Use classic filter */
166 .filter_type = MCAN_FILTER_TYPE_CLASSIC_FILTER,
167 /* Store message into RXFIFO0 if matching */
168 .filter_config = MCAN_FILTER_ELEM_CFG_STORE_IN_RX_FIFO0_IF_MATCH,
169 /* For Standard Identify only */
170 .can_id_type = MCAN_CAN_ID_TYPE_EXTENDED,
171 /* Sync Message, only evaluated when "CCCR.UTSU" is set */
172 .sync_message = 0,
173 /* Don't care if mask is set to all 1s */
174 .filter_id = 0,
175 /* Accept all messages */
176 .filter_mask = 0x1FFFFFFFUL,
177 };
178
179 /***********************************************************************************************************************
180 *
181 * Prototypes
182 *
183 **********************************************************************************************************************/
184 /**
185 * @brief Set Nominal Bit timing
186 *
187 * @param [in] ptr MCAN base
188 * @param [in] bit_timing Bit timing parameter
189 */
190 static void mcan_set_can_nominal_bit_timing(MCAN_Type *ptr, const mcan_bit_timing_param_t *bit_timing);
191
192 /**
193 * @brief Set CANFD Data Bit timing
194 *
195 * @param [in] ptr MCAN base
196 *
197 * @param [in] bit_timing Bit timing parameter
198 */
199 static void mcan_set_can_data_bit_timing(MCAN_Type *ptr, const mcan_bit_timing_param_t *bit_timing);
200
201 /**
202 * @brief Calculate the closest prescaler
203 *
204 * @param [in] num_tq_mul_prescaler Number of TQ * Prescaler
205 * @param [in] start_prescaler Start of Prescaler value
206 * @param [in] max_tq Maximum Timing Quantum
207 * @param [in] min_tq Minimum Timing Quantum
208 *
209 * @return Calculated prescaler value
210 */
211 static uint32_t mcan_calculate_closest_prescaler(uint32_t num_tq_mul_prescaler,
212 uint32_t start_prescaler,
213 uint32_t max_tq,
214 uint32_t min_tq);
215
216 /**
217 * @brief Calculate Bit timing from baudrate
218 *
219 * @param [in] src_clk_freq CAN IP clock used for generating bit timing
220 * @param [in] option CAN bit timing option
221 * @param [in] baudrate CAN baudrate in bps
222 * @param [in] samplepoint_min Minimum sample point, value = actual sample point * 1000
223 * @param [in] samplepoint_max Maximum sample point, value = actual sample point * 1000
224 * @param [out] timing_param Calculated Bit timing parameter
225 *
226 * @retval status_success if no errors happened
227 * @retval status_invalid_argument if the timing parameters cannot be calculated from specified baudrate
228 */
229 static hpm_stat_t mcan_calc_bit_timing_from_baudrate(uint32_t src_clk_freq,
230 mcan_bit_timing_option_t option,
231 uint32_t baudrate,
232 uint16_t samplepoint_min,
233 uint16_t samplepoint_max,
234 mcan_bit_timing_param_t *timing_param);
235
236 /**
237 * @brief Set MCAN bit timing from Baudrate
238 *
239 * @param [in] ptr MCAN base
240 * @param [in] option MCAN bit timing option
241 * @param [in] src_clk_freq CAN IP clock used for generating bit timing
242 * @param [in] baudrate Baudrate in bps
243 * @param [in] samplepoint_min Minimum sample point, value = actual sample point * 1000
244 * @param [in] samplepoint_max Maximum sample point, value = actual sample point * 1000
245 *
246 * @retval status_success if no errors happened
247 * @retval status_invalid_argument if the timing parameters cannot be calculated from specified baudrate
248 */
249 static hpm_stat_t mcan_set_bit_timing_from_baudrate(MCAN_Type *ptr,
250 mcan_bit_timing_option_t option,
251 uint32_t src_clk_freq,
252 uint32_t baudrate,
253 uint16_t samplepoint_min,
254 uint16_t samplepoint_max);
255
256 /**
257 * @brief Configure MCAN TSU
258 *
259 * @param [in] ptr MCAN base
260 * @param [in] config TSU configuration
261 * @retval status_success if no errors happened
262 *
263 * @retval status_invalid_arugment if any parameters are invalid
264 */
265 static hpm_stat_t mcan_set_tsu(MCAN_Type *ptr, mcan_tsu_config_t *config);
266
267 /**
268 * @brief Configure MCAN internal timestamp
269 *
270 * @param [in] ptr MCAN base
271 * @param [in] config Internal Timestamp Configuratiojn
272 * @retval status_success if no errors happened
273 *
274 * @retval status_invalid_arugment if any parameters are invalid
275 */
276 static hpm_stat_t mcan_set_internal_timestamp(MCAN_Type *ptr, mcan_internal_timestamp_config_t *config);
277
278 /***********************************************************************************************************************
279 *
280 * Codes
281 */
mcan_set_can_nominal_bit_timing(MCAN_Type * ptr,const mcan_bit_timing_param_t * bit_timing)282 static void mcan_set_can_nominal_bit_timing(MCAN_Type *ptr, const mcan_bit_timing_param_t *bit_timing)
283 {
284 ptr->NBTP = MCAN_NBTP_NBRP_SET(bit_timing->prescaler - 1U) | MCAN_NBTP_NTSEG1_SET(bit_timing->num_seg1 - 1U) |
285 MCAN_NBTP_NTSEG2_SET(bit_timing->num_seg2 - 1U) | MCAN_NBTP_NSJW_SET(bit_timing->num_sjw - 1U);
286 }
287
mcan_set_can_data_bit_timing(MCAN_Type * ptr,const mcan_bit_timing_param_t * bit_timing)288 static void mcan_set_can_data_bit_timing(MCAN_Type *ptr, const mcan_bit_timing_param_t *bit_timing)
289 {
290 ptr->DBTP = MCAN_DBTP_DBRP_SET(bit_timing->prescaler - 1U) | MCAN_DBTP_DTSEG1_SET(bit_timing->num_seg1 - 1U) |
291 MCAN_DBTP_DTSEG2_SET(bit_timing->num_seg2 - 1U) | MCAN_DBTP_DSJW_SET(bit_timing->num_sjw - 1U) |
292 MCAN_DBTP_TDC_SET((uint32_t) bit_timing->enable_tdc);
293 }
294
mcan_calculate_closest_prescaler(uint32_t num_tq_mul_prescaler,uint32_t start_prescaler,uint32_t max_tq,uint32_t min_tq)295 static uint32_t mcan_calculate_closest_prescaler(uint32_t num_tq_mul_prescaler,
296 uint32_t start_prescaler,
297 uint32_t max_tq,
298 uint32_t min_tq)
299 {
300 bool has_found = false;
301
302 uint32_t prescaler = start_prescaler;
303
304 while (!has_found) {
305 if ((num_tq_mul_prescaler / prescaler > max_tq) || (num_tq_mul_prescaler % prescaler != 0)) {
306 ++prescaler;
307 continue;
308 } else {
309 uint32_t tq = num_tq_mul_prescaler / prescaler;
310 if (tq * prescaler == num_tq_mul_prescaler) {
311 has_found = true;
312 break;
313 } else if (tq < min_tq) {
314 has_found = false;
315 break;
316 } else {
317 ++prescaler;
318 }
319 }
320 }
321
322 return has_found ? prescaler : 0U;
323 }
324
mcan_calc_bit_timing_from_baudrate(uint32_t src_clk_freq,mcan_bit_timing_option_t option,uint32_t baudrate,uint16_t samplepoint_min,uint16_t samplepoint_max,mcan_bit_timing_param_t * timing_param)325 static hpm_stat_t mcan_calc_bit_timing_from_baudrate(uint32_t src_clk_freq,
326 mcan_bit_timing_option_t option,
327 uint32_t baudrate,
328 uint16_t samplepoint_min,
329 uint16_t samplepoint_max,
330 mcan_bit_timing_param_t *timing_param)
331 {
332 hpm_stat_t status = status_invalid_argument;
333 do {
334 if ((option > mcan_bit_timing_canfd_data) || (baudrate == 0U) ||
335 (src_clk_freq / baudrate < MIN_TQ_MUL_PRESCALE) || (timing_param == NULL)) {
336 break;
337 }
338
339 const mcan_bit_timing_table_t *tbl = &k_mcan_bit_timing_tbl[(uint8_t) option];
340
341 /* According to the CAN specification 2.0,
342 * the Tq must be in range specified in the above CAN bit-timing table
343 */
344 if (src_clk_freq / baudrate < tbl->tq_min) {
345 break;
346 }
347
348 uint32_t num_tq_mul_prescaler = src_clk_freq / baudrate;
349 uint32_t start_prescaler = 1U;
350 uint32_t num_seg1, num_seg2;
351 bool has_found = false;
352
353 /* Find out the minimum prescaler */
354 uint32_t current_prescaler;
355 while (!has_found) {
356 current_prescaler =
357 mcan_calculate_closest_prescaler(num_tq_mul_prescaler, start_prescaler, tbl->tq_max, tbl->tq_min);
358 if ((current_prescaler < start_prescaler) || (current_prescaler > NUM_PRESCALE_MAX)) {
359 break;
360 }
361 uint32_t num_tq = num_tq_mul_prescaler / current_prescaler;
362
363 num_seg2 = (num_tq - tbl->min_diff_seg1_minus_seg2) / 2U;
364 num_seg1 = num_tq - num_seg2;
365 while (num_seg2 > tbl->seg2_max) {
366 num_seg2--;
367 num_seg1++;
368 }
369
370 /* Recommended sample point is 75% - 87.5% */
371 while ((num_seg1 * 1000U) / num_tq < samplepoint_min) {
372 ++num_seg1;
373 --num_seg2;
374 }
375
376 if ((num_seg1 * 1000U) / num_tq > samplepoint_max) {
377 break;
378 }
379
380 if ((num_seg2 >= tbl->seg2_min) && (num_seg1 <= tbl->seg1_max)) {
381 has_found = true;
382 } else {
383 start_prescaler = current_prescaler + 1U;
384 }
385 }
386
387 if (has_found) {
388 uint32_t num_sjw = MIN(tbl->sjw_max, num_seg2);
389 timing_param->num_seg1 = num_seg1 - NUM_TQ_SYNC_SEG; /* Should exclude the Sync_Reg */
390 timing_param->num_seg2 = num_seg2;
391 timing_param->num_sjw = num_sjw;
392 timing_param->prescaler = current_prescaler;
393 status = status_success;
394 }
395 } while (false);
396
397 return status;
398 }
399
mcan_set_bit_timing_from_baudrate(MCAN_Type * ptr,mcan_bit_timing_option_t option,uint32_t src_clk_freq,uint32_t baudrate,uint16_t samplepoint_min,uint16_t samplepoint_max)400 static hpm_stat_t mcan_set_bit_timing_from_baudrate(MCAN_Type *ptr,
401 mcan_bit_timing_option_t option,
402 uint32_t src_clk_freq,
403 uint32_t baudrate,
404 uint16_t samplepoint_min,
405 uint16_t samplepoint_max)
406 {
407 hpm_stat_t status = status_invalid_argument;
408
409 do {
410 if (ptr == NULL) {
411 break;
412 }
413
414 mcan_bit_timing_param_t timing_param = { 0 };
415 status = mcan_calc_bit_timing_from_baudrate(src_clk_freq,
416 option,
417 baudrate,
418 samplepoint_min,
419 samplepoint_max,
420 &timing_param);
421
422 if (status == status_success) {
423 if (option < mcan_bit_timing_canfd_data) {
424 mcan_set_can_nominal_bit_timing(ptr, &timing_param);
425 } else {
426 mcan_set_can_data_bit_timing(ptr, &timing_param);
427 }
428 status = status_success;
429 }
430
431 } while (false);
432
433 return status;
434 }
435
mcan_get_default_ram_config(MCAN_Type * ptr,mcan_ram_config_t * simple_config,bool enable_canfd)436 void mcan_get_default_ram_config(MCAN_Type *ptr, mcan_ram_config_t *simple_config, bool enable_canfd)
437 {
438 (void) memset(simple_config, 0, sizeof(mcan_ram_config_t));
439 uint32_t start_addr = mcan_get_ram_offset(ptr);
440
441 if (!enable_canfd) {
442 simple_config->enable_std_filter = true;
443 simple_config->std_filter_elem_count = MCAN_FILTER_SIZE_CAN_DEFAULT;
444 start_addr += MCAN_FILTER_ELEM_STD_ID_SIZE * MCAN_FILTER_SIZE_CAN_DEFAULT;
445
446 simple_config->enable_ext_filter = true;
447 simple_config->ext_filter_elem_count = MCAN_FILTER_SIZE_CAN_DEFAULT;
448 start_addr += MCAN_FILTER_ELEM_EXT_ID_SIZE * MCAN_FILTER_SIZE_CAN_DEFAULT;
449
450 simple_config->enable_txbuf = true;
451 simple_config->txbuf_dedicated_txbuf_elem_count = MCAN_TXBUF_SIZE_CAN_DEFAULT / 2;
452 simple_config->txbuf_fifo_or_queue_elem_count = MCAN_TXBUF_SIZE_CAN_DEFAULT / 2;
453 simple_config->txfifo_or_txqueue_mode = MCAN_TXBUF_OPERATION_MODE_FIFO;
454 simple_config->txbuf_data_field_size = MCAN_DATA_FIELD_SIZE_8BYTES;
455 start_addr += MCAN_TXBUF_SIZE_CAN_DEFAULT * MCAN_TXRX_ELEM_SIZE_CAN_MAX;
456
457 for (uint32_t i = 0; i < ARRAY_SIZE(simple_config->rxfifos); i++) {
458 simple_config->rxfifos[i].enable = true;
459 simple_config->rxfifos[i].elem_count = MCAN_RXFIFO_SIZE_CAN_DEFAULT;
460 simple_config->rxfifos[i].operation_mode = MCAN_FIFO_OPERATION_MODE_BLOCKING;
461 simple_config->rxfifos[i].watermark = 1U;
462 simple_config->rxfifos[i].data_field_size = MCAN_DATA_FIELD_SIZE_8BYTES;
463 start_addr += MCAN_RXFIFO_SIZE_CAN_DEFAULT * MCAN_TXRX_ELEM_SIZE_CAN_MAX;
464 }
465 simple_config->enable_rxbuf = true;
466 simple_config->rxbuf_elem_count = MCAN_RXBUF_SIZE_CAN_DEFAULT;
467 simple_config->rxbuf_data_field_size = MCAN_DATA_FIELD_SIZE_8BYTES;
468 start_addr += MCAN_RXBUF_SIZE_CAN_DEFAULT * MCAN_TXRX_ELEM_SIZE_CAN_MAX;
469 } else {
470 simple_config->enable_std_filter = true;
471 simple_config->std_filter_elem_count = MCAN_FILTER_SIZE_CANFD_DEFAULT;
472 start_addr += MCAN_FILTER_ELEM_STD_ID_SIZE * MCAN_FILTER_SIZE_CANFD_DEFAULT;
473
474 simple_config->enable_ext_filter = true;
475 simple_config->ext_filter_elem_count = MCAN_FILTER_SIZE_CANFD_DEFAULT;
476 start_addr += MCAN_FILTER_ELEM_EXT_ID_SIZE * MCAN_FILTER_SIZE_CANFD_DEFAULT;
477
478 simple_config->enable_txbuf = true;
479 simple_config->txbuf_dedicated_txbuf_elem_count = MCAN_TXBUF_SIZE_CANFD_DEFAULT / 2;
480 simple_config->txbuf_fifo_or_queue_elem_count = MCAN_TXBUF_SIZE_CANFD_DEFAULT / 2;
481 simple_config->txfifo_or_txqueue_mode = MCAN_TXBUF_OPERATION_MODE_FIFO;
482 simple_config->txbuf_data_field_size = MCAN_DATA_FIELD_SIZE_64BYTES;
483 start_addr += MCAN_TXBUF_SIZE_CANFD_DEFAULT * MCAN_TXRX_ELEM_SIZE_CANFD_MAX;
484
485 for (uint32_t i = 0; i < ARRAY_SIZE(simple_config->rxfifos); i++) {
486 simple_config->rxfifos[i].enable = true;
487 simple_config->rxfifos[i].elem_count = MCAN_RXFIFO_SIZE_CANFD_DEFAULT;
488 simple_config->rxfifos[i].operation_mode = MCAN_FIFO_OPERATION_MODE_BLOCKING;
489 simple_config->rxfifos[i].watermark = 1U;
490 simple_config->rxfifos[i].data_field_size = MCAN_DATA_FIELD_SIZE_64BYTES;
491 start_addr += MCAN_RXFIFO_SIZE_CANFD_DEFAULT * MCAN_TXRX_ELEM_SIZE_CANFD_MAX;
492 }
493 simple_config->enable_rxbuf = true;
494 simple_config->rxbuf_elem_count = MCAN_RXBUF_SIZE_CANFD_DEFAULT;
495 simple_config->rxbuf_data_field_size = MCAN_DATA_FIELD_SIZE_64BYTES;
496 start_addr += MCAN_RXBUF_SIZE_CANFD_DEFAULT * MCAN_TXRX_ELEM_SIZE_CANFD_MAX;
497 }
498 simple_config->enable_tx_evt_fifo = true;
499 uint32_t tx_fifo_elem_count =
500 simple_config->txbuf_dedicated_txbuf_elem_count + simple_config->txbuf_fifo_or_queue_elem_count;
501 simple_config->tx_evt_fifo_elem_count = tx_fifo_elem_count;
502 simple_config->tx_evt_fifo_watermark = 1U;
503
504 start_addr += MCAN_TXEVT_ELEM_SIZE * tx_fifo_elem_count;
505
506 assert((start_addr - mcan_get_ram_offset(ptr)) <= mcan_get_ram_size(ptr));
507 }
508
mcan_get_default_ram_flexible_config(MCAN_Type * ptr,mcan_ram_flexible_config_t * ram_config,bool enable_canfd)509 void mcan_get_default_ram_flexible_config(MCAN_Type *ptr, mcan_ram_flexible_config_t *ram_config, bool enable_canfd)
510 {
511 (void) memset(ram_config, 0, sizeof(mcan_ram_config_t));
512 uint32_t start_addr = mcan_get_ram_offset(ptr);
513
514 if (!enable_canfd) {
515 ram_config->enable_std_filter = true;
516 ram_config->std_filter_config.list_start_addr = start_addr;
517 ram_config->std_filter_config.list_size = MCAN_FILTER_SIZE_CAN_DEFAULT;
518 start_addr += MCAN_FILTER_ELEM_STD_ID_SIZE * MCAN_FILTER_SIZE_CAN_DEFAULT;
519
520 ram_config->enable_ext_filter = true;
521 ram_config->ext_filter_config.list_start_addr = start_addr;
522 ram_config->ext_filter_config.list_size = MCAN_FILTER_SIZE_CAN_DEFAULT;
523 start_addr += MCAN_FILTER_ELEM_EXT_ID_SIZE * MCAN_FILTER_SIZE_CAN_DEFAULT;
524
525 ram_config->enable_txbuf = true;
526 ram_config->txbuf_config.start_addr = start_addr;
527 ram_config->txbuf_config.dedicated_tx_buf_size = MCAN_TXBUF_SIZE_CAN_DEFAULT / 2;
528 ram_config->txbuf_config.fifo_queue_size = MCAN_TXBUF_SIZE_CAN_DEFAULT / 2;
529 ram_config->txbuf_config.tx_fifo_queue_mode = MCAN_TXBUF_OPERATION_MODE_FIFO;
530 ram_config->txbuf_elem_config.data_field_size = MCAN_DATA_FIELD_SIZE_8BYTES;
531 start_addr += MCAN_TXBUF_SIZE_CAN_DEFAULT * MCAN_TXRX_ELEM_SIZE_CAN_MAX;
532
533 ram_config->enable_rxfifo0 = true;
534 ram_config->rxfifo0_config.start_addr = start_addr;
535 ram_config->rxfifo0_config.fifo_size = MCAN_RXFIFO_SIZE_CAN_DEFAULT;
536 ram_config->rxfifo0_config.operation_mode = MCAN_FIFO_OPERATION_MODE_BLOCKING;
537 ram_config->rxfifo0_config.watermark = 1U;
538 start_addr += MCAN_RXFIFO_SIZE_CAN_DEFAULT * MCAN_TXRX_ELEM_SIZE_CAN_MAX;
539
540 ram_config->enable_rxfifo1 = true;
541 ram_config->rxfifo1_config.start_addr = start_addr;
542 ram_config->rxfifo1_config.fifo_size = MCAN_RXFIFO_SIZE_CAN_DEFAULT;
543 ram_config->rxfifo1_config.operation_mode = MCAN_FIFO_OPERATION_MODE_BLOCKING;
544 ram_config->rxfifo1_config.watermark = 1U;
545 start_addr += MCAN_RXFIFO_SIZE_CAN_DEFAULT * MCAN_TXRX_ELEM_SIZE_CAN_MAX;
546
547 ram_config->enable_rxbuf = true;
548 ram_config->rxbuf_config.start_addr = start_addr;
549 start_addr += MCAN_RXBUF_SIZE_CAN_DEFAULT * MCAN_TXRX_ELEM_SIZE_CAN_MAX;
550 } else {
551 ram_config->enable_std_filter = true;
552 ram_config->std_filter_config.list_start_addr = start_addr;
553 ram_config->std_filter_config.list_size = MCAN_FILTER_SIZE_CANFD_DEFAULT;
554 start_addr += MCAN_FILTER_ELEM_STD_ID_SIZE * MCAN_FILTER_SIZE_CANFD_DEFAULT;
555
556 ram_config->enable_ext_filter = true;
557 ram_config->ext_filter_config.list_start_addr = start_addr;
558 ram_config->ext_filter_config.list_size = MCAN_FILTER_SIZE_CANFD_DEFAULT;
559 start_addr += MCAN_FILTER_ELEM_EXT_ID_SIZE * MCAN_FILTER_SIZE_CANFD_DEFAULT;
560
561 ram_config->enable_txbuf = true;
562 ram_config->txbuf_config.start_addr = start_addr;
563 ram_config->txbuf_config.dedicated_tx_buf_size = MCAN_TXBUF_SIZE_CANFD_DEFAULT / 2;
564 ram_config->txbuf_config.fifo_queue_size = MCAN_TXBUF_SIZE_CANFD_DEFAULT / 2;
565 ram_config->txbuf_config.tx_fifo_queue_mode = MCAN_TXBUF_OPERATION_MODE_FIFO;
566 ram_config->txbuf_elem_config.data_field_size = MCAN_DATA_FIELD_SIZE_64BYTES;
567 start_addr += MCAN_TXBUF_SIZE_CAN_DEFAULT * MCAN_TXRX_ELEM_SIZE_CAN_MAX;
568
569 ram_config->enable_rxfifo0 = true;
570 ram_config->rxfifo0_config.start_addr = start_addr;
571 ram_config->rxfifo0_config.fifo_size = MCAN_RXFIFO_SIZE_CANFD_DEFAULT;
572 ram_config->rxfifo0_config.operation_mode = MCAN_FIFO_OPERATION_MODE_BLOCKING;
573 ram_config->rxfifo0_config.watermark = 1U;
574 start_addr += MCAN_RXFIFO_SIZE_CANFD_DEFAULT * MCAN_TXRX_ELEM_SIZE_CANFD_MAX;
575
576 ram_config->enable_rxfifo1 = true;
577 ram_config->rxfifo1_config.start_addr = start_addr;
578 ram_config->rxfifo1_config.fifo_size = MCAN_RXFIFO_SIZE_CANFD_DEFAULT;
579 ram_config->rxfifo1_config.operation_mode = MCAN_FIFO_OPERATION_MODE_BLOCKING;
580 ram_config->rxfifo1_config.watermark = 1U;
581 start_addr += MCAN_RXFIFO_SIZE_CANFD_DEFAULT * MCAN_TXRX_ELEM_SIZE_CANFD_MAX;
582
583 ram_config->enable_rxbuf = true;
584 ram_config->rxbuf_config.start_addr = start_addr;
585 start_addr += MCAN_RXBUF_SIZE_CANFD_DEFAULT * MCAN_TXRX_ELEM_SIZE_CANFD_MAX;
586 }
587 ram_config->enable_tx_evt_fifo = true;
588 ram_config->tx_evt_fifo_config.start_addr = start_addr;
589 uint32_t tx_fifo_size = ram_config->txbuf_config.dedicated_tx_buf_size + ram_config->txbuf_config.fifo_queue_size;
590 ram_config->tx_evt_fifo_config.fifo_size = tx_fifo_size;
591 ram_config->tx_evt_fifo_config.fifo_watermark = 1U;
592
593 start_addr += MCAN_TXEVT_ELEM_SIZE * tx_fifo_size;
594
595 /* Ensure the requested MCAN RAM size is less than or equal to the total MCAN RAM size */
596 assert((start_addr - mcan_get_ram_offset(ptr)) <= mcan_get_ram_size(ptr));
597 }
598
mcan_get_default_config(MCAN_Type * ptr,mcan_config_t * config)599 void mcan_get_default_config(MCAN_Type *ptr, mcan_config_t *config)
600 {
601 (void) memset(config, 0, sizeof(mcan_config_t));
602 config->baudrate = MCAN_CAN_BAUDRATE_DEFAULT;
603 config->baudrate_fd = MCAN_CANFD_BAUDRATE_DEFAULT;
604 config->can20_samplepoint_max = CAN_SAMPLEPOINT_MAX;
605 config->can20_samplepoint_min = CAN_SAMPLEPOINT_MIN;
606 config->canfd_samplepoint_max = CAN_SAMPLEPOINT_MAX;
607 config->canfd_samplepoint_min = CAN_SAMPLEPOINT_MIN;
608
609 config->mode = mcan_mode_normal;
610 config->enable_canfd = false;
611
612 /* Default Filter settings */
613 mcan_all_filters_config_t *filters_config = &config->all_filters_config;
614 filters_config->global_filter_config.reject_remote_ext_frame = false;
615 filters_config->global_filter_config.reject_remote_std_frame = false;
616 filters_config->global_filter_config.accept_non_matching_std_frame_option =
617 MCAN_ACCEPT_NON_MATCHING_FRAME_OPTION_IN_RXFIFO0;
618 filters_config->global_filter_config.accept_non_matching_ext_frame_option =
619 MCAN_ACCEPT_NON_MATCHING_FRAME_OPTION_IN_RXFIFO0;
620 filters_config->ext_id_mask = 0x1FFFFFFFUL;
621 filters_config->std_id_filter_list.filter_elem_list = &k_default_std_id_filter;
622 filters_config->std_id_filter_list.mcan_filter_elem_count = 1;
623 filters_config->ext_id_filter_list.filter_elem_list = &k_default_ext_id_filter;
624 filters_config->ext_id_filter_list.mcan_filter_elem_count = 1;
625
626 /* Default MCAN RAM Configuration */
627 mcan_ram_config_t *ram_config = &config->ram_config;
628 mcan_get_default_ram_config(ptr, ram_config, false);
629
630 /* Default Internal Timestamp Configuration */
631 mcan_internal_timestamp_config_t *ts_config = &config->timestamp_cfg;
632 ts_config->counter_prescaler = 1U;
633 ts_config->timestamp_selection = MCAN_TIMESTAMP_SEL_VALUE_ALWAYS_ZERO;
634
635 /* Default TSU configuration */
636 mcan_tsu_config_t *tsu_config = &config->tsu_config;
637 tsu_config->prescaler = 1U;
638 #if defined(MCAN_SOC_TSU_SRC_TWO_STAGES) && (MCAN_SOC_TSU_SRC_TWO_STAGES == 1)
639 tsu_config->ext_timebase_src = MCAN_TSU_EXT_TIMEBASE_SRC_TBSEL_0;
640 tsu_config->tbsel_option = MCAN_TSU_TBSEL_PTPC0;
641 #else
642 tsu_config->ext_timebase_src = MCAN_TSU_EXT_TIMEBASE_SRC_PTPC;
643 #endif
644 tsu_config->use_ext_timebase = false;
645 tsu_config->capture_on_sof = false;
646 tsu_config->enable_tsu = false;
647 }
648
mcan_config_rxfifo(MCAN_Type * ptr,uint32_t index,uint32_t reg_val)649 static void mcan_config_rxfifo(MCAN_Type *ptr, uint32_t index, uint32_t reg_val)
650 {
651 if (index == 0U) {
652 ptr->RXF0C = reg_val;
653 } else {
654 ptr->RXF1C = reg_val;
655 }
656 }
657
mcan_config_ram(MCAN_Type * ptr,mcan_ram_config_t * config)658 hpm_stat_t mcan_config_ram(MCAN_Type *ptr, mcan_ram_config_t *config)
659 {
660 hpm_stat_t status = status_invalid_argument;
661 do {
662 uint32_t elem_bytes;
663 uint32_t elem_count;
664 uint32_t start_addr = mcan_get_ram_offset(ptr);
665 if (config->enable_std_filter) {
666 if (config->std_filter_elem_count > MCAN_STD_FILTER_ELEM_CNT_MAX) {
667 break;
668 }
669 mcan_filter_config_t filter_config = { .reg_val = 0 };
670 filter_config.list_size = config->std_filter_elem_count;
671 filter_config.list_start_addr = start_addr;
672 ptr->SIDFC = filter_config.reg_val;
673 start_addr += MCAN_FILTER_ELEM_STD_ID_SIZE * (uint32_t) config->std_filter_elem_count;
674 } else {
675 ptr->SIDFC = MCAN_RAM_ADDR_INVALID;
676 }
677
678 if (config->enable_ext_filter) {
679 if (config->ext_filter_elem_count > MCAN_EXT_FILTER_ELEM_CNT_MAX) {
680 break;
681 }
682 mcan_filter_config_t filter_config = { .reg_val = 0 };
683 filter_config.list_size = config->ext_filter_elem_count;
684 filter_config.list_start_addr = start_addr;
685 ptr->XIDFC = filter_config.reg_val;
686 start_addr += MCAN_FILTER_ELEM_EXT_ID_SIZE * (uint32_t) config->std_filter_elem_count;
687 } else {
688 ptr->XIDFC = MCAN_RAM_ADDR_INVALID;
689 }
690
691 mcan_rx_fifo_or_buf_elem_config_t rx_fifo_buf_elem_config = { .reg_val = 0U };
692
693 for (uint32_t i = 0; i < ARRAY_SIZE(config->rxfifos); i++) {
694 if (config->rxfifos[i].enable) {
695 elem_bytes = mcan_get_data_field_size(config->rxfifos[i].data_field_size)
696 + MCAN_MESSAGE_HEADER_SIZE_IN_BYTES;
697 elem_count = config->rxfifos[i].elem_count;
698 if (elem_count > MCAN_RXFIFO_ELEM_CNT_MAX) {
699 return status_invalid_argument;
700 }
701 mcan_rxfifo_config_t rxfifo_config = { .reg_val = 0 };
702 rxfifo_config.start_addr = start_addr;
703 rxfifo_config.watermark = 1U;
704 rxfifo_config.operation_mode = config->rxfifos[i].operation_mode;
705 rxfifo_config.fifo_size = elem_count;
706 mcan_config_rxfifo(ptr, i, rxfifo_config.reg_val);
707
708 if (i == 0) {
709 rx_fifo_buf_elem_config.fifo0_data_field_size = config->rxfifos[i].data_field_size;
710 } else {
711 rx_fifo_buf_elem_config.fifo1_data_field_size = config->rxfifos[i].data_field_size;
712 }
713
714 start_addr += elem_bytes * elem_count;
715 } else {
716 mcan_config_rxfifo(ptr, i, MCAN_RAM_ADDR_INVALID);
717 if (i == 0) {
718 rx_fifo_buf_elem_config.fifo0_data_field_size = 0;
719 } else {
720 rx_fifo_buf_elem_config.fifo1_data_field_size = 0;
721 }
722 }
723 }
724
725 if (config->enable_rxbuf) {
726 elem_bytes = mcan_get_data_field_size(config->rxbuf_data_field_size) + MCAN_MESSAGE_HEADER_SIZE_IN_BYTES;
727 elem_count = config->rxbuf_elem_count;
728 if (elem_count > MCAN_RXFIFO_ELEM_CNT_MAX) {
729 break;
730 }
731 ptr->RXBC = start_addr;
732 rx_fifo_buf_elem_config.buf_data_field_size = config->rxbuf_data_field_size;
733
734 start_addr += elem_bytes * elem_count;
735 } else {
736 rx_fifo_buf_elem_config.buf_data_field_size = 0;
737 ptr->RXBC = MCAN_RAM_ADDR_INVALID;
738 }
739 ptr->RXESC = rx_fifo_buf_elem_config.reg_val;
740
741 mcan_txbuf_config_t txbuf_config = { .reg_val = 0 };
742 if (config->enable_txbuf) {
743 txbuf_config.start_addr = start_addr;
744 txbuf_config.fifo_queue_size = config->txbuf_fifo_or_queue_elem_count;
745 txbuf_config.dedicated_tx_buf_size = config->txbuf_dedicated_txbuf_elem_count;
746 txbuf_config.tx_fifo_queue_mode = config->txfifo_or_txqueue_mode;
747
748 elem_count = config->txbuf_fifo_or_queue_elem_count + config->txbuf_dedicated_txbuf_elem_count;
749 if (elem_count > MCAN_TXEVT_FIFO_ELEM_CNT_MAX) {
750 break;
751 }
752
753 elem_bytes = mcan_get_data_field_size(config->txbuf_data_field_size) + MCAN_MESSAGE_HEADER_SIZE_IN_BYTES;
754
755 start_addr += elem_count * elem_bytes;
756 ptr->TXESC = (uint32_t) config->txbuf_data_field_size;
757 } else {
758 ptr->TXESC = MCAN_RAM_ADDR_INVALID;
759 }
760
761 ptr->TXBC = txbuf_config.reg_val;
762
763 mcan_tx_evt_fifo_config_t txevt_fifo_config = { .reg_val = 0 };
764 if (config->enable_tx_evt_fifo) {
765 elem_bytes = sizeof(mcan_tx_event_fifo_elem_t);
766 elem_count = config->tx_evt_fifo_elem_count;
767 if (elem_count > MCAN_TXEVT_FIFO_ELEM_CNT_MAX) {
768 break;
769 }
770
771 txevt_fifo_config.start_addr = start_addr;
772 txevt_fifo_config.fifo_size = elem_count;
773 txevt_fifo_config.fifo_watermark = 1U;
774 ptr->TXEFC = txevt_fifo_config.reg_val;
775
776 start_addr += elem_bytes * elem_count;
777 } else {
778 ptr->TXEFC = MCAN_RAM_ADDR_INVALID;
779 }
780
781 /* Check whether the requested RAM space exceeds the valid RAM range */
782 uint32_t requested_ram_size = start_addr - mcan_get_ram_offset(ptr);
783 if (requested_ram_size > mcan_get_ram_size(ptr)) {
784 status = status_mcan_ram_out_of_range;
785 break;
786 }
787
788 status = status_success;
789
790 } while (false);
791
792 return status;
793 }
794
mcan_config_ram_with_flexible_config(MCAN_Type * ptr,mcan_ram_flexible_config_t * config)795 hpm_stat_t mcan_config_ram_with_flexible_config(MCAN_Type *ptr, mcan_ram_flexible_config_t *config)
796 {
797 hpm_stat_t status = status_invalid_argument;
798 do {
799 if (config->enable_std_filter) {
800 if (config->std_filter_config.list_size > MCAN_STD_FILTER_ELEM_CNT_MAX) {
801 break;
802 }
803 ptr->SIDFC = config->std_filter_config.reg_val;
804 } else {
805 ptr->SIDFC = MCAN_RAM_ADDR_INVALID;
806 }
807
808 if (config->enable_ext_filter) {
809 if (config->std_filter_config.list_size > MCAN_EXT_FILTER_ELEM_CNT_MAX) {
810 break;
811 }
812 ptr->XIDFC = config->ext_filter_config.reg_val;
813 } else {
814 ptr->XIDFC = MCAN_RAM_ADDR_INVALID;
815 }
816
817 if (config->enable_rxfifo0) {
818 if (config->rxfifo0_config.fifo_size > MCAN_RXFIFO_ELEM_CNT_MAX) {
819 break;
820 }
821 ptr->RXF0C = config->rxfifo0_config.reg_val;
822 } else {
823 ptr->RXF0C = MCAN_RAM_ADDR_INVALID;
824 }
825
826 if (config->enable_rxfifo1) {
827 if (config->rxfifo1_config.fifo_size > MCAN_RXFIFO_ELEM_CNT_MAX) {
828 break;
829 }
830 ptr->RXF1C = config->rxfifo1_config.reg_val;
831 } else {
832 ptr->RXF1C = MCAN_RAM_ADDR_INVALID;
833 }
834
835 if (config->enable_rxbuf) {
836 /* NOTE: There is no register field for SW to validate the rxbuf element count,
837 * users should ensure the parameters are in valid range.
838 */
839 ptr->RXBC = config->rxbuf_config.start_addr;
840 } else {
841 ptr->RXBC = MCAN_RAM_ADDR_INVALID;
842 }
843
844 ptr->RXESC = config->rx_elem_config.reg_val;
845 if (config->enable_txbuf) {
846 uint32_t tx_fifo_size = config->txbuf_config.fifo_queue_size + config->txbuf_config.dedicated_tx_buf_size;
847 if (tx_fifo_size > MCAN_TXBUF_ELEM_CNT_MAX) {
848 break;
849 }
850 ptr->TXESC = config->txbuf_elem_config.data_field_size;
851 } else {
852 ptr->TXESC = MCAN_RAM_ADDR_INVALID;
853 }
854
855 ptr->TXBC = config->txbuf_config.reg_val;
856
857 if (config->enable_tx_evt_fifo) {
858 if (config->tx_evt_fifo_config.fifo_size > MCAN_TXEVT_FIFO_ELEM_CNT_MAX) {
859 break;
860 }
861 ptr->TXEFC = config->tx_evt_fifo_config.reg_val;
862 } else {
863 ptr->TXEFC = MCAN_RAM_ADDR_INVALID;
864 }
865
866 status = status_success;
867
868 } while (false);
869
870 return status;
871 }
872
mcan_config_all_filters(MCAN_Type * ptr,mcan_all_filters_config_t * config)873 hpm_stat_t mcan_config_all_filters(MCAN_Type *ptr, mcan_all_filters_config_t *config)
874 {
875 hpm_stat_t status = status_invalid_argument;
876
877 do {
878 if ((ptr == NULL) || (config == NULL)) {
879 break;
880 }
881
882 ptr->XIDAM = config->ext_id_mask;
883
884 ptr->GFC = MCAN_GFC_RRFE_SET(config->global_filter_config.reject_remote_ext_frame) |
885 MCAN_GFC_RRFS_SET(config->global_filter_config.reject_remote_std_frame) |
886 MCAN_GFC_ANFE_SET(config->global_filter_config.accept_non_matching_ext_frame_option) |
887 MCAN_GFC_ANFS_SET(config->global_filter_config.accept_non_matching_std_frame_option);
888
889 uint32_t elem_count = 0;
890 const mcan_filter_elem_t *elem = NULL;
891 if (config->ext_id_filter_list.mcan_filter_elem_count > 0) {
892 elem_count = config->ext_id_filter_list.mcan_filter_elem_count;
893 elem = config->ext_id_filter_list.filter_elem_list;
894 for (uint32_t i = 0; i < elem_count; i++) {
895 if (elem->can_id_type != MCAN_CAN_ID_TYPE_EXTENDED) {
896 status = status_invalid_argument;
897 break;
898 }
899
900 status = mcan_set_filter_element(ptr, elem, i);
901 if (status != status_success) {
902 break;
903 }
904 ++elem;
905 }
906 if (status != status_success) {
907 break;
908 }
909 }
910 if (config->std_id_filter_list.mcan_filter_elem_count > 0) {
911 elem_count = config->std_id_filter_list.mcan_filter_elem_count;
912 elem = config->std_id_filter_list.filter_elem_list;
913 for (uint32_t i = 0; i < elem_count; i++) {
914 if (elem->can_id_type != MCAN_CAN_ID_TYPE_STANDARD) {
915 status = status_invalid_argument;
916 break;
917 }
918 status = mcan_set_filter_element(ptr, elem, i);
919 if (status != status_success) {
920 break;
921 }
922 ++elem;
923 }
924 if (status != status_success) {
925 break;
926 }
927 }
928 status = status_success;
929
930 } while (false);
931
932 return status;
933 }
934
mcan_set_tsu(MCAN_Type * ptr,mcan_tsu_config_t * config)935 static hpm_stat_t mcan_set_tsu(MCAN_Type *ptr, mcan_tsu_config_t *config)
936 {
937 hpm_stat_t status = status_invalid_argument;
938
939 do {
940 uint32_t tscfg = 0;
941
942 if ((config->prescaler < 1U) || (config->prescaler > 256U) ||
943 (config->ext_timebase_src > MCAN_TSU_EXT_TIMEBASE_SRC_MAX)) {
944 break;
945 }
946
947 if (config->enable_tsu) {
948 tscfg |= MCAN_TSCFG_TSUE_MASK;
949 }
950 if (config->capture_on_sof) {
951 tscfg |= MCAN_TSCFG_SCP_MASK;
952 }
953 if (config->use_ext_timebase) {
954 tscfg |= MCAN_TSCFG_TBCS_MASK;
955 mcan_set_tsu_ext_timebase_src(ptr, config->ext_timebase_src);
956 #if defined(MCAN_SOC_TSU_SRC_TWO_STAGES) && (MCAN_SOC_TSU_SRC_TWO_STAGES == 1)
957 mcan_set_tsu_tbsel_option(ptr, config->ext_timebase_src, config->tbsel_option);
958 #endif
959 }
960 if (config->enable_64bit_timestamp) {
961 tscfg |= MCAN_TSCFG_EN64_MASK;
962 }
963
964 tscfg |= MCAN_TSCFG_TBPRE_SET(config->prescaler - 1U);
965
966 ptr->TSCFG = tscfg;
967
968 status = status_success;
969 } while (false);
970
971 return status;
972 }
973
mcan_set_internal_timestamp(MCAN_Type * ptr,mcan_internal_timestamp_config_t * config)974 static hpm_stat_t mcan_set_internal_timestamp(MCAN_Type *ptr, mcan_internal_timestamp_config_t *config)
975 {
976 hpm_stat_t status = status_invalid_argument;
977
978 do {
979 if ((config->counter_prescaler < 1U) || (config->counter_prescaler > 16) ||
980 (config->timestamp_selection > MCAN_TIMESTAMP_SEL_MAX)) {
981 break;
982 }
983
984 ptr->TSCC = MCAN_TSCC_TCP_SET(config->counter_prescaler - 1U) | MCAN_TSCC_TSS_SET(config->timestamp_selection);
985
986 status = status_success;
987 } while (false);
988
989 return status;
990 }
991
mcan_init(MCAN_Type * ptr,mcan_config_t * config,uint32_t src_clk_freq)992 hpm_stat_t mcan_init(MCAN_Type *ptr, mcan_config_t *config, uint32_t src_clk_freq)
993 {
994 hpm_stat_t status = status_invalid_argument;
995 do {
996 if ((ptr == NULL) || (config == NULL)) {
997 break;
998 }
999
1000 mcan_enable_clock(ptr);
1001 uint32_t retry_cnt = 10000UL;
1002 do {
1003 retry_cnt--;
1004 if (retry_cnt == 0UL) {
1005 break;
1006 }
1007 } while (!mcan_is_clock_enabled(ptr));
1008 if (retry_cnt == 0UL) {
1009 status = status_timeout;
1010 break;
1011 }
1012
1013 ptr->CCCR |= MCAN_CCCR_INIT_MASK;
1014 retry_cnt = 10000UL;
1015 while ((ptr->CCCR & MCAN_CCCR_INIT_MASK) == 0U) {
1016 retry_cnt--;
1017 if (retry_cnt == 0UL) {
1018 break;
1019 }
1020 }
1021 if (retry_cnt == 0UL) {
1022 status = status_timeout;
1023 break;
1024 }
1025
1026 ptr->CCCR |= MCAN_CCCR_CCE_MASK;
1027
1028 if (!config->use_lowlevel_timing_setting) {
1029 if (config->enable_canfd) {
1030 status = mcan_set_bit_timing_from_baudrate(ptr,
1031 mcan_bit_timing_canfd_nominal,
1032 src_clk_freq,
1033 config->baudrate,
1034 config->can20_samplepoint_min,
1035 config->can20_samplepoint_max);
1036 HPM_BREAK_IF(status != status_success);
1037 status = mcan_set_bit_timing_from_baudrate(ptr,
1038 mcan_bit_timing_canfd_data,
1039 src_clk_freq,
1040 config->baudrate_fd,
1041 config->canfd_samplepoint_min,
1042 config->canfd_samplepoint_max);
1043 } else {
1044 status = mcan_set_bit_timing_from_baudrate(ptr,
1045 mcan_bit_timing_can2_0,
1046 src_clk_freq,
1047 config->baudrate,
1048 config->can20_samplepoint_min,
1049 config->can20_samplepoint_max);
1050 }
1051 HPM_BREAK_IF(status != status_success);
1052 } else {
1053 mcan_set_can_nominal_bit_timing(ptr, &config->can_timing);
1054 if (config->enable_canfd) {
1055 mcan_set_can_data_bit_timing(ptr, &config->canfd_timing);
1056 }
1057 }
1058
1059 switch (config->mode) {
1060 default:
1061 case mcan_mode_normal:
1062 ptr->CCCR &= ~(MCAN_CCCR_MON_MASK | MCAN_CCCR_TEST_MASK);
1063 break;
1064 case mcan_mode_loopback_internal:
1065 ptr->CCCR |= MCAN_CCCR_MON_MASK | MCAN_CCCR_TEST_MASK;
1066 ptr->TEST |= MCAN_TEST_LBCK_MASK;
1067 break;
1068 case mcan_mode_loopback_external:
1069 ptr->CCCR |= MCAN_CCCR_TEST_MASK;
1070 ptr->TEST |= MCAN_TEST_LBCK_MASK;
1071 break;
1072 case mcan_mode_listen_only:
1073 ptr->CCCR |= MCAN_CCCR_MON_MASK;
1074 break;
1075 }
1076
1077 if (config->enable_canfd) {
1078 ptr->CCCR |= MCAN_CCCR_FDOE_MASK | MCAN_CCCR_BRSE_MASK;
1079 } else {
1080 ptr->CCCR &= ~(MCAN_CCCR_FDOE_MASK | MCAN_CCCR_BRSE_MASK);
1081 }
1082 if (config->enable_non_iso_mode) {
1083 ptr->CCCR |= MCAN_CCCR_NISO_MASK;
1084 } else {
1085 ptr->CCCR &= ~MCAN_CCCR_NISO_MASK;
1086 }
1087
1088 if (config->enable_transmit_pause) {
1089 ptr->CCCR |= MCAN_CCCR_TXP_MASK;
1090 } else {
1091 ptr->CCCR &= ~MCAN_CCCR_TXP_MASK;
1092 }
1093
1094 if (config->disable_protocol_exception_handling) {
1095 ptr->CCCR |= MCAN_CCCR_PXHD_MASK;
1096 } else {
1097 ptr->CCCR &= ~MCAN_CCCR_PXHD_MASK;
1098 }
1099
1100 if (config->enable_wide_message_marker) {
1101 ptr->CCCR |= MCAN_CCCR_WMM_MASK;
1102 } else {
1103 ptr->CCCR &= ~MCAN_CCCR_WMM_MASK;
1104 }
1105
1106 if (config->enable_edge_filtering) {
1107 ptr->CCCR |= MCAN_CCCR_EFBI_MASK;
1108 } else {
1109 ptr->CCCR &= ~MCAN_CCCR_EFBI_MASK;
1110 }
1111
1112 if (config->disable_auto_retransmission) {
1113 ptr->CCCR |= MCAN_CCCR_DAR_MASK;
1114 } else {
1115 ptr->CCCR &= ~MCAN_CCCR_DAR_MASK;
1116 }
1117
1118 if (config->enable_restricted_operation_mode) {
1119 ptr->CCCR |= MCAN_CCCR_ASM_MASK;
1120 } else {
1121 ptr->CCCR &= ~MCAN_CCCR_ASM_MASK;
1122 }
1123
1124 /* Configure Transmitter Delay Compensation */
1125 if (config->enable_tdc) {
1126 ptr->DBTP |= MCAN_DBTP_TDC_MASK;
1127 ptr->TDCR &= ~MCAN_TDCR_TDCO_MASK;
1128 uint32_t data_seg1 = MCAN_DBTP_DTSEG1_GET(ptr->DBTP);
1129 uint32_t prescaler = MCAN_DBTP_DSJW_GET(ptr->DBTP);
1130
1131 uint32_t calc_val = (data_seg1 + 2U) * (prescaler + 1U);
1132 if (calc_val < MCAN_MAX_TDC_OFFSET) {
1133 ptr->TDCR |= MCAN_TDCR_TDCO_SET(calc_val);
1134 } else {
1135 ptr->TDCR |= MCAN_TDCR_TDCO_SET(MCAN_MAX_TDC_OFFSET);
1136 }
1137 } else {
1138 ptr->DBTP &= ~MCAN_DBTP_TDC_MASK;
1139 }
1140
1141 /* Configure TSU */
1142 if (config->use_timestamping_unit) {
1143 ptr->CCCR |= MCAN_CCCR_UTSU_MASK;
1144 status = mcan_set_tsu(ptr, &config->tsu_config);
1145 HPM_BREAK_IF(status != status_success);
1146 } else {
1147 ptr->CCCR &= ~MCAN_CCCR_UTSU_MASK;
1148 }
1149
1150 /* Configure Internal Timestamp */
1151 status = mcan_set_internal_timestamp(ptr, &config->timestamp_cfg);
1152 HPM_BREAK_IF(status != status_success);
1153
1154 /* Initialize CAN RAM */
1155 uint32_t can_ram_size = mcan_get_ram_size(ptr);
1156 uint32_t *ram_base = (uint32_t *) (mcan_get_ram_base(ptr) + mcan_get_ram_offset(ptr));
1157 for (uint32_t i = 0U; i < can_ram_size / sizeof(uint32_t); i++) {
1158 ram_base[i] = 0UL;
1159 }
1160 status = mcan_config_ram(ptr, &config->ram_config);
1161 HPM_BREAK_IF(status != status_success);
1162
1163 /* Configure Filters */
1164 status = mcan_config_all_filters(ptr, &config->all_filters_config);
1165 HPM_BREAK_IF(status != status_success);
1166
1167 /* Disable all interrupts by default */
1168 mcan_disable_interrupts(ptr, ~0UL);
1169 mcan_disable_txbuf_transmission_interrupt(ptr, ~0UL);
1170 mcan_disable_txbuf_cancel_finish_interrupt(ptr, ~0UL);
1171 /* Enable interrupts on demand */
1172 mcan_enable_interrupts(ptr, config->interrupt_mask);
1173 mcan_enable_txbuf_transmission_interrupt(ptr, config->txbuf_trans_interrupt_mask);
1174 mcan_enable_txbuf_cancel_finish_interrupt(ptr, config->txbuf_cancel_finish_interrupt_mask);
1175
1176 /* Clear all Interrupt Flags */
1177 mcan_clear_interrupt_flags(ptr, ~0UL);
1178
1179 ptr->CCCR &= ~MCAN_CCCR_INIT_MASK;
1180 while ((ptr->CCCR & MCAN_CCCR_INIT_MASK) != 0U) {
1181 }
1182
1183 status = status_success;
1184
1185 } while (false);
1186
1187 return status;
1188 }
1189
mcan_deinit(MCAN_Type * ptr)1190 void mcan_deinit(MCAN_Type *ptr)
1191 {
1192 if (ptr != NULL) {
1193
1194 mcan_enter_init_mode(ptr); /* Stop MCAN function */
1195
1196 /* Enable write access to protected configuration registers */
1197 mcan_enable_write_to_prot_config_registers(ptr);
1198
1199 /* Restore critical registers to default values */
1200 ptr->RWD = 0UL;
1201 ptr->TSCC = 0UL;
1202 ptr->GFC = 0UL;
1203 ptr->SIDFC = 0UL;
1204 ptr->XIDAM = 0UL;
1205 ptr->XIDAM = 0x1FFFFFFFUL;
1206 ptr->RXBC = 0UL;
1207 ptr->RXF1C = 0UL;
1208 ptr->RXESC = 0UL;
1209 ptr->TXBC = 0UL;
1210 ptr->TXESC = 0UL;
1211 ptr->TXEFC = 0UL;
1212
1213 ptr->TSCFG = 0UL;
1214
1215 /* Disable all interrupts and clear all flags */
1216 mcan_disable_interrupts(ptr, ~0UL);
1217 mcan_clear_interrupt_flags(ptr, ~0UL);
1218 mcan_disable_txbuf_transmission_interrupt(ptr, ~0UL);
1219 mcan_disable_txbuf_cancel_finish_interrupt(ptr, ~0UL);
1220
1221 /* Restore CCCR to default value */
1222 ptr->CCCR = MCAN_CCCR_INIT_MASK;
1223 }
1224 }
1225
mcan_set_filter_element(MCAN_Type * ptr,const mcan_filter_elem_t * filter_elem,uint32_t index)1226 hpm_stat_t mcan_set_filter_element(MCAN_Type *ptr, const mcan_filter_elem_t *filter_elem, uint32_t index)
1227 {
1228 hpm_stat_t status = status_invalid_argument;
1229
1230 do {
1231 if ((ptr == NULL) || (filter_elem == NULL)) {
1232 break;
1233 }
1234 bool is_ext_id = (filter_elem->can_id_type == MCAN_CAN_ID_TYPE_EXTENDED);
1235
1236 uint32_t ram_offset;
1237 uint32_t filter_elem_size;
1238 uint32_t size_max;
1239 if (is_ext_id) {
1240 ram_offset = MCAN_XIDFC_FLESA_GET(ptr->XIDFC) << MCAN_XIDFC_FLESA_SHIFT;
1241 filter_elem_size = MCAN_FILTER_ELEM_EXT_ID_SIZE;
1242 size_max = MCAN_XIDFC_LSE_GET(ptr->XIDFC);
1243 } else {
1244 ram_offset = MCAN_SIDFC_FLSSA_GET(ptr->SIDFC) << MCAN_SIDFC_FLSSA_SHIFT;
1245 filter_elem_size = MCAN_FILTER_ELEM_STD_ID_SIZE;
1246 size_max = MCAN_SIDFC_LSS_GET(ptr->SIDFC);
1247 }
1248
1249 if (index >= size_max) {
1250 status = status_mcan_filter_index_out_of_range;
1251 break;
1252 }
1253
1254 volatile uint32_t *config_start;
1255 config_start = (volatile uint32_t *) (mcan_get_ram_base(ptr) + ram_offset + filter_elem_size * index);
1256
1257 uint32_t config_words[2] = { 0, 0 };
1258 if (is_ext_id) {
1259 /* EFEC + EFID1 */
1260 config_words[0] = ((uint32_t) (filter_elem->filter_config) << 29) | filter_elem->id1;
1261
1262 /* EFT + ESYNC + EFFID2 */
1263 config_words[1] = filter_elem->id2;
1264 config_words[1] |= (filter_elem->sync_message != 0) ? (1UL << 29) : 0;
1265 config_words[1] |= ((uint32_t) filter_elem->filter_type) << 30;
1266
1267 config_start[0] = config_words[0];
1268 config_start[1] = config_words[1];
1269 } else {
1270 config_words[0] = (filter_elem->id2 & 0x7FFUL) | ((filter_elem->id1 & 0x7FFU) << 16);
1271 config_words[0] |= (filter_elem->sync_message != 0) ? (1UL << 15) : 0;
1272 config_words[0] |= ((uint32_t) filter_elem->filter_config) << 27;
1273 config_words[0] |= ((uint32_t) filter_elem->filter_type) << 30;
1274
1275 config_start[0] = config_words[0];
1276 }
1277
1278 status = status_success;
1279
1280 } while (false);
1281
1282 return status;
1283 }
1284
mcan_get_rxfifo0_base(MCAN_Type * ptr)1285 static uint32_t mcan_get_rxfifo0_base(MCAN_Type *ptr)
1286 {
1287 uint32_t rxfifo0_buf_offset = MCAN_RXF0C_F0SA_GET(ptr->RXF0C) << 2;
1288 uint32_t fifo_addr_base = mcan_get_ram_base(ptr) + rxfifo0_buf_offset;
1289 return fifo_addr_base;
1290 }
1291
mcan_get_rxfifo1_base(MCAN_Type * ptr)1292 static uint32_t mcan_get_rxfifo1_base(MCAN_Type *ptr)
1293 {
1294 uint32_t rxfifo1_buf_offset = MCAN_RXF1C_F1SA_GET(ptr->RXF1C) << 2;
1295 uint32_t fifo_addr_base = mcan_get_ram_base(ptr) + rxfifo1_buf_offset;
1296 return fifo_addr_base;
1297 }
1298
mcan_get_rxbuf_elem_addr(MCAN_Type * ptr,uint32_t index)1299 static uint32_t mcan_get_rxbuf_elem_addr(MCAN_Type *ptr, uint32_t index)
1300 {
1301 uint32_t elem_size;
1302 uint32_t elem_size_option = MCAN_RXESC_RBDS_GET(ptr->RXESC);
1303 if (elem_size_option < 5U) {
1304 elem_size = 8U + 4U * elem_size_option;
1305 } else {
1306 elem_size = 32U + (elem_size_option - 5U) * 16U;
1307 }
1308 elem_size += MCAN_MESSAGE_HEADER_SIZE_IN_BYTES;
1309
1310 uint32_t rxbuf_offset = MCAN_RXBC_RBSA_GET(ptr->RXBC) << MCAN_RXBC_RBSA_SHIFT;
1311
1312 uint32_t rxbuf_addr_base = mcan_get_ram_base(ptr) + rxbuf_offset;
1313
1314 uint32_t elem_addr = rxbuf_addr_base + elem_size * index;
1315
1316 return elem_addr;
1317 }
1318
mcan_get_txbuf_elem_addr(MCAN_Type * ptr,uint32_t index)1319 static uint32_t mcan_get_txbuf_elem_addr(MCAN_Type *ptr, uint32_t index)
1320 {
1321 uint32_t elem_size;
1322 uint32_t elem_size_option = MCAN_TXESC_TBDS_GET(ptr->TXESC);
1323 if (elem_size_option < 5U) {
1324 elem_size = 8U + 4U * elem_size_option;
1325 } else {
1326 elem_size = 32U + (elem_size_option - 5U) * 16U;
1327 }
1328 elem_size += MCAN_MESSAGE_HEADER_SIZE_IN_BYTES;
1329
1330 uint32_t txbuf_offset = MCAN_TXBC_TBSA_GET(ptr->TXBC) << MCAN_TXBC_TBSA_SHIFT;
1331
1332 uint32_t txbuf_addr_base = mcan_get_ram_base(ptr) + txbuf_offset;
1333
1334 uint32_t elem_addr = txbuf_addr_base + elem_size * index;
1335
1336 return elem_addr;
1337 }
1338
mcan_get_message_size_from_dlc(uint8_t dlc)1339 uint8_t mcan_get_message_size_from_dlc(uint8_t dlc)
1340 {
1341 uint32_t msg_size;
1342 if (dlc <= 8U) {
1343 msg_size = dlc;
1344 } else if (dlc <= 12U) {
1345 msg_size = 8 + (dlc - 8) * 4;
1346 } else {
1347 msg_size = 32 + (dlc - 13) * 16U;
1348 }
1349 return msg_size;
1350 }
1351
mcan_get_data_field_size(uint8_t data_field_size_option)1352 uint8_t mcan_get_data_field_size(uint8_t data_field_size_option)
1353 {
1354 uint8_t size_in_bytes = 0;
1355
1356 switch (data_field_size_option) {
1357 case MCAN_DATA_FIELD_SIZE_8BYTES:
1358 size_in_bytes = 8U;
1359 break;
1360 case MCAN_DATA_FIELD_SIZE_12BYTES:
1361 size_in_bytes = 12U;
1362 break;
1363 case MCAN_DATA_FIELD_SIZE_16BYTES:
1364 size_in_bytes = 16U;
1365 break;
1366 case MCAN_DATA_FIELD_SIZE_20BYTES:
1367 size_in_bytes = 20U;
1368 break;
1369 case MCAN_DATA_FIELD_SIZE_24BYTES:
1370 size_in_bytes = 24U;
1371 break;
1372 case MCAN_DATA_FIELD_SIZE_32BYTES:
1373 size_in_bytes = 32U;
1374 break;
1375 case MCAN_DATA_FIELD_SIZE_48BYTES:
1376 size_in_bytes = 48U;
1377 break;
1378 case MCAN_DATA_FIELD_SIZE_64BYTES:
1379 size_in_bytes = 64U;
1380 break;
1381 default:
1382 /* Invalid option */
1383 break;
1384 }
1385 return size_in_bytes;
1386 }
1387
mcan_write_txbuf(MCAN_Type * ptr,uint32_t index,mcan_tx_frame_t * tx_frame)1388 hpm_stat_t mcan_write_txbuf(MCAN_Type *ptr, uint32_t index, mcan_tx_frame_t *tx_frame)
1389 {
1390 hpm_stat_t status = status_invalid_argument;
1391
1392 do {
1393 if ((ptr == NULL) || (tx_frame == NULL)) {
1394 break;
1395 }
1396
1397 uint32_t txbuf_index_max = MCAN_TXBC_NDTB_GET(ptr->TXBC);
1398 if (index >= txbuf_index_max) {
1399 status = status_mcan_txbuf_index_out_of_range;
1400 break;
1401 }
1402
1403 if (!mcan_is_transmit_request_pending(ptr, index)) {
1404 uint32_t *msg_hdr = (uint32_t *) mcan_get_txbuf_elem_addr(ptr, index);
1405 uint32_t *msg_data = msg_hdr + 2;
1406 uint8_t msg_size_words = (mcan_get_message_size_from_dlc(tx_frame->dlc) + 3U) / sizeof(uint32_t);
1407 uint32_t *tx_frame_u32 = (uint32_t *) tx_frame;
1408 msg_hdr[0] = tx_frame_u32[0];
1409 msg_hdr[1] = tx_frame_u32[1];
1410
1411 for (uint32_t i = 0; i < msg_size_words; i++) {
1412 msg_data[i] = tx_frame->data_32[i];
1413 }
1414
1415 status = status_success;
1416 } else {
1417 status = status_fail;
1418 }
1419 } while (false);
1420
1421 return status;
1422 }
1423
mcan_write_txfifo(MCAN_Type * ptr,mcan_tx_frame_t * tx_frame)1424 hpm_stat_t mcan_write_txfifo(MCAN_Type *ptr, mcan_tx_frame_t *tx_frame)
1425 {
1426 hpm_stat_t status = status_invalid_argument;
1427
1428 do {
1429 if ((ptr == NULL) || (tx_frame == NULL)) {
1430 break;
1431 }
1432 if (!mcan_is_txfifo_full(ptr)) {
1433 uint32_t put_index = mcan_get_txfifo_put_index(ptr);
1434 uint32_t *msg_hdr = (uint32_t *) mcan_get_txbuf_elem_addr(ptr, put_index);
1435 uint32_t *msg_data = msg_hdr + 2;
1436 uint8_t msg_size_words = (mcan_get_message_size_from_dlc(tx_frame->dlc) + 3U) / sizeof(uint32_t);
1437 uint32_t *tx_frame_u32 = (uint32_t *) tx_frame;
1438 msg_hdr[0] = tx_frame_u32[0];
1439 msg_hdr[1] = tx_frame_u32[1];
1440
1441 for (uint32_t i = 0; i < msg_size_words; i++) {
1442 msg_data[i] = tx_frame->data_32[i];
1443 }
1444 status = status_success;
1445 } else {
1446 status = status_mcan_txfifo_full;
1447 }
1448 } while (false);
1449
1450 return status;
1451 }
1452
mcan_read_rxbuf(MCAN_Type * ptr,uint32_t index,mcan_rx_message_t * rx_frame)1453 hpm_stat_t mcan_read_rxbuf(MCAN_Type *ptr, uint32_t index, mcan_rx_message_t *rx_frame)
1454 {
1455 hpm_stat_t status = status_invalid_argument;
1456
1457 do {
1458 if ((ptr == NULL) || (rx_frame == NULL)) {
1459 break;
1460 }
1461
1462 if (!mcan_is_rxbuf_data_available(ptr, index)) {
1463 status = status_mcan_rxbuf_empty;
1464 break;
1465 }
1466
1467 uint32_t *msg_hdr = (uint32_t *) mcan_get_rxbuf_elem_addr(ptr, index);
1468 uint32_t *msg_data = msg_hdr + 2;
1469 uint32_t *rx_frame_u32 = (uint32_t *) rx_frame;
1470 rx_frame_u32[0] = msg_hdr[0];
1471 rx_frame_u32[1] = msg_hdr[1];
1472 uint8_t msg_size_words = (mcan_get_message_size_from_dlc(rx_frame->dlc) + 3) / 4;
1473 for (uint32_t i = 0; i < msg_size_words; i++) {
1474 rx_frame->data_32[i] = msg_data[i];
1475 }
1476 status = status_success;
1477
1478 } while (false);
1479
1480 return status;
1481 }
1482
mcan_read_rxfifo(MCAN_Type * ptr,uint32_t fifo_index,mcan_rx_message_t * rx_frame)1483 hpm_stat_t mcan_read_rxfifo(MCAN_Type *ptr, uint32_t fifo_index, mcan_rx_message_t *rx_frame)
1484 {
1485 hpm_stat_t status = status_invalid_argument;
1486
1487 do {
1488 if ((ptr == NULL) || (rx_frame == NULL)) {
1489 break;
1490 }
1491
1492 uint32_t base_addr;
1493 uint32_t elem_index;
1494 uint32_t elem_size;
1495 uint32_t elem_size_option;
1496 if (fifo_index == 0) {
1497 uint32_t rxf0s = ptr->RXF0S;
1498 if (MCAN_RXF0S_F0FL_GET(rxf0s) == 0) {
1499 status = status_mcan_rxfifo_empty;
1500 break;
1501 }
1502 base_addr = mcan_get_rxfifo0_base(ptr);
1503 elem_size_option = MCAN_RXESC_F0DS_GET(ptr->RXESC);
1504 elem_index = MCAN_RXF0S_F0GI_GET(rxf0s);
1505 } else {
1506 uint32_t rxf1s = ptr->RXF1S;
1507 if (MCAN_RXF1S_F1FL_GET(rxf1s) == 0) {
1508 status = status_mcan_rxfifo_empty;
1509 break;
1510 }
1511 base_addr = mcan_get_rxfifo1_base(ptr);
1512 elem_size_option = MCAN_RXESC_F1DS_GET(ptr->RXESC);
1513 elem_index = MCAN_RXF1S_F1GI_GET(rxf1s);
1514 }
1515
1516
1517 if (elem_size_option < 5U) {
1518 elem_size = 8U + 4U * elem_size_option;
1519 } else {
1520 elem_size = 32U + (elem_size_option - 5U) * 16U;
1521 }
1522 elem_size += MCAN_MESSAGE_HEADER_SIZE_IN_BYTES;
1523
1524 uint32_t elem_addr = base_addr + elem_size * elem_index;
1525 uint32_t *msg_hdr = (uint32_t *) elem_addr;
1526 uint32_t *msg_data = msg_hdr + 2;
1527 uint32_t *rx_frame_u32 = (uint32_t *) rx_frame;
1528 rx_frame_u32[0] = msg_hdr[0];
1529 rx_frame_u32[1] = msg_hdr[1];
1530 uint8_t msg_size_words = (mcan_get_message_size_from_dlc(rx_frame->dlc) + 3) / 4;
1531 for (uint32_t i = 0; i < msg_size_words; i++) {
1532 rx_frame->data_32[i] = msg_data[i];
1533 }
1534
1535 if (fifo_index == 0) {
1536 ptr->RXF0A = MCAN_RXF0S_F0GI_GET(ptr->RXF0S);
1537 } else {
1538 ptr->RXF1A = MCAN_RXF1S_F1GI_GET(ptr->RXF1S);
1539 }
1540
1541 status = status_success;
1542
1543 } while (false);
1544
1545 return status;
1546 }
1547
mcan_read_tx_evt_fifo(MCAN_Type * ptr,mcan_tx_event_fifo_elem_t * tx_evt)1548 hpm_stat_t mcan_read_tx_evt_fifo(MCAN_Type *ptr, mcan_tx_event_fifo_elem_t *tx_evt)
1549 {
1550 hpm_stat_t status = status_invalid_argument;
1551
1552 do {
1553 if ((ptr == NULL) || (tx_evt == NULL)) {
1554 break;
1555 }
1556
1557 uint32_t txefs = ptr->TXEFS;
1558
1559 if (MCAN_TXEFS_EFFL_GET(txefs) == 0U) {
1560 status = status_mcan_tx_evt_fifo_empty;
1561 break;
1562 }
1563
1564 uint32_t base_addr = mcan_get_ram_base(ptr) + (MCAN_TXEFC_EFSA_GET(ptr->TXEFC) << MCAN_TXEFC_EFSA_SHIFT);
1565 uint32_t elem_size = sizeof(mcan_tx_event_fifo_elem_t);
1566 uint32_t elem_index = MCAN_TXEFS_EFGI_GET(txefs);
1567
1568 uint32_t elem_addr = base_addr + elem_size * elem_index;
1569 uint32_t *tx_evt_buf = (uint32_t *) elem_addr;
1570
1571 tx_evt->words[0] = tx_evt_buf[0];
1572 tx_evt->words[1] = tx_evt_buf[1];
1573
1574 ptr->TXEFA = MCAN_TXEFA_EFAI_SET(elem_index);
1575
1576 status = status_success;
1577
1578 } while (false);
1579
1580 return status;
1581 }
1582
mcan_transmit_via_txbuf_nonblocking(MCAN_Type * ptr,uint32_t index,mcan_tx_frame_t * tx_frame)1583 hpm_stat_t mcan_transmit_via_txbuf_nonblocking(MCAN_Type *ptr, uint32_t index, mcan_tx_frame_t *tx_frame)
1584 {
1585 hpm_stat_t status = status_invalid_argument;
1586 do {
1587 if ((ptr == NULL) || (tx_frame == NULL)) {
1588 break;
1589 }
1590
1591 status = mcan_write_txbuf(ptr, index, tx_frame);
1592 HPM_BREAK_IF(status != status_success);
1593
1594 mcan_send_add_request(ptr, index);
1595 status = status_success;
1596
1597 } while (false);
1598 return status;
1599 }
1600
mcan_transmit_blocking(MCAN_Type * ptr,mcan_tx_frame_t * tx_frame)1601 hpm_stat_t mcan_transmit_blocking(MCAN_Type *ptr, mcan_tx_frame_t *tx_frame)
1602 {
1603 hpm_stat_t status = status_invalid_argument;
1604 do {
1605 uint32_t put_index = 0;
1606 status = mcan_transmit_via_txfifo_nonblocking(ptr, tx_frame, &put_index);
1607 if (status != status_success) {
1608 break;
1609 }
1610
1611 uint32_t retry_cnt = 0;
1612 while (!mcan_is_transmit_occurred(ptr, put_index)) {
1613 retry_cnt++;
1614 if (retry_cnt >= MCAN_TX_RETRY_COUNT_MAX) {
1615 break;
1616 }
1617 }
1618 if (retry_cnt >= MCAN_TX_RETRY_COUNT_MAX) {
1619 status = status_timeout;
1620 } else {
1621 status = status_success;
1622 }
1623 } while (false);
1624 return status;
1625 }
1626
mcan_transmit_via_txfifo_nonblocking(MCAN_Type * ptr,mcan_tx_frame_t * tx_frame,uint32_t * fifo_index)1627 hpm_stat_t mcan_transmit_via_txfifo_nonblocking(MCAN_Type *ptr, mcan_tx_frame_t *tx_frame, uint32_t *fifo_index)
1628 {
1629 hpm_stat_t status = status_invalid_argument;
1630 do {
1631 if ((ptr == NULL) || (tx_frame == NULL)) {
1632 break;
1633 }
1634 if (mcan_is_txfifo_full(ptr)) {
1635 status = status_mcan_txfifo_full;
1636 break;
1637 }
1638
1639 status = mcan_write_txfifo(ptr, tx_frame);
1640 HPM_BREAK_IF(status != status_success);
1641
1642 uint32_t put_index = mcan_get_txfifo_put_index(ptr);
1643 mcan_send_add_request(ptr, put_index);
1644
1645 if (fifo_index != NULL) {
1646 *fifo_index = put_index;
1647 }
1648
1649 status = status_success;
1650
1651 } while (false);
1652
1653 return status;
1654 }
1655
mcan_receive_from_buf_blocking(MCAN_Type * ptr,uint32_t index,mcan_rx_message_t * rx_frame)1656 hpm_stat_t mcan_receive_from_buf_blocking(MCAN_Type *ptr, uint32_t index, mcan_rx_message_t *rx_frame)
1657 {
1658 hpm_stat_t status = status_invalid_argument;
1659
1660 do {
1661 uint32_t retry_cnt = 0;
1662
1663 while (!mcan_is_rxbuf_data_available(ptr, index)) {
1664 retry_cnt++;
1665 if (retry_cnt >= MCAN_RX_RETRY_COUNT_MAX) {
1666 status = status_timeout;
1667 break;
1668 }
1669 }
1670 if (status == status_timeout) {
1671 break;
1672 }
1673
1674 mcan_clear_rxbuf_data_available_flag(ptr, index);
1675 status = mcan_read_rxbuf(ptr, index, rx_frame);
1676 } while (false);
1677
1678 return status;
1679 }
1680
mcan_receive_from_fifo_blocking(MCAN_Type * ptr,uint32_t fifo_index,mcan_rx_message_t * rx_frame)1681 hpm_stat_t mcan_receive_from_fifo_blocking(MCAN_Type *ptr, uint32_t fifo_index, mcan_rx_message_t *rx_frame)
1682 {
1683 hpm_stat_t status = status_invalid_argument;
1684
1685 do {
1686 uint32_t retry_cnt = 0;
1687 uint32_t interrupt_flag = (fifo_index == 0U) ? MCAN_IR_RF0N_MASK : MCAN_IR_RF1N_MASK;
1688
1689 while (!mcan_is_interrupt_flag_set(ptr, interrupt_flag)) {
1690 retry_cnt++;
1691 if (retry_cnt >= MCAN_RX_RETRY_COUNT_MAX) {
1692 status = status_timeout;
1693 break;
1694 }
1695 }
1696 if (status == status_timeout) {
1697 break;
1698 }
1699
1700 mcan_clear_interrupt_flags(ptr, interrupt_flag);
1701 status = mcan_read_rxfifo(ptr, fifo_index, rx_frame);
1702 } while (false);
1703
1704 return status;
1705 }
1706
mcan_get_high_priority_message_status(MCAN_Type * ptr,mcan_high_priority_message_status_t * status)1707 void mcan_get_high_priority_message_status(MCAN_Type *ptr, mcan_high_priority_message_status_t *status)
1708 {
1709 uint32_t hpms = ptr->HPMS;
1710 status->buffer_index = MCAN_HPMS_BIDX_GET(hpms);
1711 status->filter_index = MCAN_HPMS_FIDX_GET(hpms);
1712 status->filter_list_type = MCAN_HPMS_FLST_GET(hpms);
1713 status->message_storage_indicator = MCAN_HPMS_MSI_GET(hpms);
1714 }
1715
mcan_set_global_filter_config(MCAN_Type * ptr,mcan_global_filter_config_t * filter_config)1716 hpm_stat_t mcan_set_global_filter_config(MCAN_Type *ptr, mcan_global_filter_config_t *filter_config)
1717 {
1718 hpm_stat_t status = status_invalid_argument;
1719
1720 do {
1721 if ((ptr == NULL) || (filter_config == NULL)) {
1722 break;
1723 }
1724
1725 ptr->GFC = MCAN_GFC_ANFE_SET(filter_config->accept_non_matching_ext_frame_option) |
1726 MCAN_GFC_ANFS_SET(filter_config->accept_non_matching_std_frame_option) |
1727 MCAN_GFC_RRFS_SET(filter_config->reject_remote_std_frame) |
1728 MCAN_GFC_RRFE_SET(filter_config->reject_remote_ext_frame);
1729
1730 status = status_success;
1731
1732 } while (false);
1733
1734 return status;
1735 }
1736
mcan_config_transmitter_delay_compensation(MCAN_Type * ptr,mcan_tdc_config_t * config)1737 hpm_stat_t mcan_config_transmitter_delay_compensation(MCAN_Type *ptr, mcan_tdc_config_t *config)
1738 {
1739 hpm_stat_t status = status_invalid_argument;
1740
1741 do {
1742 if ((ptr == NULL) || (config == NULL)) {
1743 break;
1744 }
1745
1746 ptr->TDCR = MCAN_TDCR_TDCO_SET(config->ssp_offset) | MCAN_TDCR_TDCF_SET(config->filter_window_length);
1747 status = status_success;
1748
1749 } while (false);
1750 return status;
1751 }
1752
mcan_read_32bit_tsu_timestamp(MCAN_Type * ptr,uint32_t index)1753 uint32_t mcan_read_32bit_tsu_timestamp(MCAN_Type *ptr, uint32_t index)
1754 {
1755 uint32_t ts_val = 0U;
1756 if (index < ARRAY_SIZE(ptr->TS_SEL)) {
1757 ts_val = ptr->TS_SEL[index];
1758 }
1759 return ts_val;
1760 }
1761
mcan_read_64bit_tsu_timestamp(MCAN_Type * ptr,uint32_t index)1762 uint64_t mcan_read_64bit_tsu_timestamp(MCAN_Type *ptr, uint32_t index)
1763 {
1764 uint64_t ts_val = 0U;
1765 uint32_t real_index = index & 0x7U; /* Clear bit3 according to IP design */
1766 if (index < ARRAY_SIZE(ptr->TS_SEL)) {
1767 ts_val = ((uint64_t) (ptr->TS_SEL[2U * real_index + 1]) << 32U);
1768 ts_val |= ptr->TS_SEL[2U * real_index];
1769 /* Workaround: dummy read to clear the corresponding bits in TSS1 if the index is equal to/greater than 8 */
1770 if (index >= 8U) {
1771 (void) ptr->TS_SEL[index];
1772 }
1773 }
1774
1775 return ts_val;
1776 }
1777
mcan_get_timestamp_from_tx_event(MCAN_Type * ptr,const mcan_tx_event_fifo_elem_t * tx_evt,mcan_timestamp_value_t * timestamp)1778 hpm_stat_t mcan_get_timestamp_from_tx_event(MCAN_Type *ptr,
1779 const mcan_tx_event_fifo_elem_t *tx_evt,
1780 mcan_timestamp_value_t *timestamp)
1781 {
1782 hpm_stat_t status = status_invalid_argument;
1783
1784 do {
1785 HPM_BREAK_IF((ptr == NULL) || (tx_evt == NULL) || (timestamp == NULL));
1786
1787 (void) memset(timestamp, 0, sizeof(mcan_timestamp_value_t));
1788
1789 bool is_tsu_used = mcan_is_tsu_used(ptr);
1790 if (!is_tsu_used) {
1791 timestamp->is_16bit = true;
1792 timestamp->ts_16bit = tx_evt->tx_timestamp;
1793 } else if (tx_evt->tx_timestamp_captured != 0U) {
1794 bool is_64bit_ts = mcan_is_64bit_tsu_timestamp_used(ptr);
1795 uint32_t ts_index = tx_evt->tx_timestamp_pointer;
1796 if (!is_64bit_ts) {
1797 timestamp->is_32bit = true;
1798 timestamp->ts_32bit = mcan_read_32bit_tsu_timestamp(ptr, ts_index);
1799 } else {
1800 timestamp->is_64bit = true;
1801 timestamp->ts_64bit = mcan_read_64bit_tsu_timestamp(ptr, ts_index);
1802 }
1803 status = status_success;
1804 } else {
1805 status = status_mcan_timestamp_not_exist;
1806 }
1807
1808 } while (false);
1809
1810 return status;
1811 }
1812
mcan_get_timestamp_from_received_message(MCAN_Type * ptr,const mcan_rx_message_t * rx_msg,mcan_timestamp_value_t * timestamp)1813 hpm_stat_t mcan_get_timestamp_from_received_message(MCAN_Type *ptr,
1814 const mcan_rx_message_t *rx_msg,
1815 mcan_timestamp_value_t *timestamp)
1816 {
1817 hpm_stat_t status = status_invalid_argument;
1818
1819 do {
1820 HPM_BREAK_IF((ptr == NULL) || (rx_msg == NULL) || (timestamp == NULL));
1821
1822 (void) memset(timestamp, 0, sizeof(mcan_timestamp_value_t));
1823
1824 bool is_tsu_used = mcan_is_tsu_used(ptr);
1825 if (!is_tsu_used) {
1826 timestamp->is_16bit = true;
1827 timestamp->ts_16bit = rx_msg->rx_timestamp;
1828 } else if (rx_msg->rx_timestamp_captured != 0U) {
1829 bool is_64bit_ts = mcan_is_64bit_tsu_timestamp_used(ptr);
1830 uint32_t ts_index = rx_msg->rx_timestamp_pointer;
1831 if (!is_64bit_ts) {
1832 timestamp->is_32bit = true;
1833 timestamp->ts_32bit = mcan_read_32bit_tsu_timestamp(ptr, ts_index);
1834 } else {
1835 timestamp->is_64bit = true;
1836 timestamp->ts_64bit = mcan_read_64bit_tsu_timestamp(ptr, ts_index);
1837 }
1838 status = status_success;
1839 } else {
1840 status = status_mcan_timestamp_not_exist;
1841 }
1842 } while (false);
1843
1844 return status;
1845 }
1846
mcan_parse_protocol_status(uint32_t psr,mcan_protocol_status_t * protocol_status)1847 hpm_stat_t mcan_parse_protocol_status(uint32_t psr, mcan_protocol_status_t *protocol_status)
1848 {
1849 if (protocol_status == NULL) {
1850 return status_invalid_argument;
1851 }
1852 memset(protocol_status, 0, sizeof(mcan_protocol_status_t));
1853 uint32_t psr_val = psr;
1854 if (MCAN_PSR_PXE_GET(psr_val) != 0U) {
1855 protocol_status->protocol_exception_evt_occurred = true;
1856 }
1857 if (MCAN_PSR_RFDF_GET(psr_val) != 0U) {
1858 protocol_status->canfd_msg_received = true;
1859 }
1860 if (MCAN_PSR_RBRS_GET(psr_val) != 0U) {
1861 protocol_status->brs_flag_set_in_last_rcv_canfd_msg = true;
1862 }
1863 if (MCAN_PSR_RESI_GET(psr_val) != 0U) {
1864 protocol_status->esi_flag_set_in_last_rcv_canfd_msg = true;
1865 }
1866 if (MCAN_PSR_BO_GET(psr_val) != 0U) {
1867 protocol_status->in_bus_off_state = true;
1868 }
1869 if (MCAN_PSR_EW_GET(psr_val) != 0U) {
1870 protocol_status->in_warning_state = true;
1871 }
1872 if (MCAN_PSR_EP_GET(psr_val) != 0U) {
1873 protocol_status->in_error_passive_state = true;
1874 }
1875 protocol_status->activity = (mcan_activity_state_t) MCAN_PSR_ACT_GET(psr_val);
1876 protocol_status->tdc_val = MCAN_PSR_TDCV_GET(psr_val);
1877
1878 if (protocol_status->brs_flag_set_in_last_rcv_canfd_msg) {
1879 protocol_status->last_error_code = (mcan_last_err_code_t) MCAN_PSR_DLEC_GET(psr_val);
1880 } else {
1881 protocol_status->last_error_code = (mcan_last_err_code_t) MCAN_PSR_LEC_GET(psr_val);
1882 }
1883 return status_success;
1884 }
1885
mcan_get_protocol_status(MCAN_Type * ptr,mcan_protocol_status_t * protocol_status)1886 hpm_stat_t mcan_get_protocol_status(MCAN_Type *ptr, mcan_protocol_status_t *protocol_status)
1887 {
1888 hpm_stat_t status = status_invalid_argument;
1889
1890 do {
1891 HPM_BREAK_IF((ptr == NULL) || (protocol_status == NULL));
1892 status = mcan_parse_protocol_status(ptr->PSR, protocol_status);
1893
1894 } while (false);
1895
1896 return status;
1897 }