• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }