1 /*
2 * Copyright (c) 2021-2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_can_drv.h"
9 #include <assert.h>
10
11 /***********************************************************************************************************************
12 *
13 * Definitions
14 *
15 **********************************************************************************************************************/
16 #define TSEG1_MIN_FOR_CAN2_0 (2U)
17 #define TSEG1_MAX_FOR_CAN2_0 (65U)
18
19 #define TSEG1_MIN_FOR_CANFD_NORMINAL (2U)
20 #define TSEG1_MAX_FOR_CANFD_NORMINAL (65U)
21
22 #define TSEG1_MIN_FOR_CANFD_DATA (2U)
23 #define TSEG1_MAX_FOR_CANFD_DATA (17U)
24
25 #define TSEG2_MIN_FOR_CAN2_0 (1U)
26 #define TSEG2_MAX_FOR_CAN2_0 (8U)
27
28 #define TSEG2_MIN_FOR_CANFD_NORMINAL (1U)
29 #define TSEG2_MAX_FOR_CANFD_NORMINAL (32U)
30
31 #define TSEG2_MIN_FOR_CANFD_DATA (1U)
32 #define TSEG2_MAX_FOR_CANFD_DATA (8U)
33
34 #define TSJW_MIN_FOR_CAN2_0 (1U)
35 #define TSJW_MAX_FOR_CAN2_0 (16U)
36
37 #define TSJW_MIN_FOR_CANFD_NORMINAL (1U)
38 #define TSJW_MAX_FOR_CANFD_NORMINAL (16U)
39
40 #define TSJW_MIN_FOR_CANFD_DATA (1U)
41 #define TSJW_MAX_FOR_CANFD_DATA (8U)
42
43 #define NUM_TQ_MIN_FOR_CAN2_0 (8U)
44 #define NUM_TQ_MAX_FOR_CAN2_0 (TSEG1_MAX_FOR_CAN2_0 + TSEG2_MAX_FOR_CAN2_0)
45
46 #define NUM_TQ_MIN_FOR_CANFD_NOMINAL (8U)
47 #define NUM_TQ_MAX_FOR_CANFD_NOMINAL (TSEG1_MAX_FOR_CANFD_NORMINAL + TSEG2_MAX_FOR_CANFD_NORMINAL)
48
49 #define NUM_TQ_MIN_FOR_CANFD_DATA (8U)
50 #define NUM_TQ_MAX_FOR_CANFD_DATA (TSEG1_MAX_FOR_CANFD_DATA + TSEG2_MAX_FOR_CANFD_DATA)
51
52 #define MIN_TQ_MUL_PRESCALE (10U)
53
54 #define NUM_PRESCALE_MAX (256U)
55
56 #define CAN_FILTER_INDEX_MAX (15U)
57 #define CAN_FILTER_NUM_MAX (16U)
58
59 #define PRESCALER_MAX (256U)
60
61 #define CAN_TIMEOUT_CNT (0xFFFFFFUL)
62
63 #define CAN_SAMPLEPOINT_MIN (750U)
64 #define CAN_SAMPLEPOINT_MAX (875U)
65
66
67 #define CAN_DEFAULT_FILTER_SETTING {0, can_filter_id_mode_both_frames, true, 0, (1UL << 29) - 1U }
68
69 /*
70 * @brief CAN bit-timing table
71 */
72 typedef struct {
73 uint8_t tq_min;
74 uint8_t tq_max;
75 uint8_t seg1_min;
76 uint8_t seg1_max;
77 uint8_t seg2_min;
78 uint8_t seg2_max;
79 uint8_t sjw_min;
80 uint8_t sjw_max;
81 uint8_t min_diff_seg1_minus_seg2;
82 } can_bit_timing_table_t;
83
84 /**
85 * @brief CAN bit timing list for all supported bit timing modes
86 */
87 static const can_bit_timing_table_t s_can_bit_timing_tbl[3] = {
88 {
89 .tq_min = NUM_TQ_MIN_FOR_CAN2_0,
90 .tq_max = NUM_TQ_MAX_FOR_CAN2_0,
91 .seg1_min = TSEG1_MIN_FOR_CAN2_0,
92 .seg1_max = TSEG1_MAX_FOR_CAN2_0,
93 .seg2_min = TSEG2_MIN_FOR_CAN2_0,
94 .seg2_max = TSEG2_MAX_FOR_CAN2_0,
95 .sjw_min = TSJW_MIN_FOR_CAN2_0,
96 .sjw_max = TSJW_MAX_FOR_CAN2_0,
97 .min_diff_seg1_minus_seg2 = 2,
98 },
99 {
100 .tq_min = NUM_TQ_MIN_FOR_CANFD_NOMINAL,
101 .tq_max = NUM_TQ_MAX_FOR_CANFD_NOMINAL,
102 .seg1_min = TSEG1_MIN_FOR_CANFD_NORMINAL,
103 .seg1_max = TSEG1_MAX_FOR_CANFD_NORMINAL,
104 .seg2_min = TSEG2_MIN_FOR_CANFD_NORMINAL,
105 .seg2_max = TSEG2_MAX_FOR_CANFD_NORMINAL,
106 .sjw_min = TSJW_MIN_FOR_CANFD_NORMINAL,
107 .sjw_max = TSJW_MAX_FOR_CANFD_NORMINAL,
108 .min_diff_seg1_minus_seg2 = 2,
109 },
110 {
111 .tq_min = NUM_TQ_MIN_FOR_CANFD_DATA,
112 .tq_max = NUM_TQ_MAX_FOR_CANFD_DATA,
113 .seg1_min = TSEG1_MIN_FOR_CANFD_DATA,
114 .seg1_max = TSEG1_MAX_FOR_CANFD_DATA,
115 .seg2_min = TSEG2_MIN_FOR_CANFD_DATA,
116 .seg2_max = TSEG2_MAX_FOR_CANFD_DATA,
117 .sjw_min = TSJW_MIN_FOR_CANFD_DATA,
118 .sjw_max = TSJW_MAX_FOR_CANFD_DATA,
119 .min_diff_seg1_minus_seg2 = 1,
120 }
121 };
122
123 /***********************************************************************************************************************
124 *
125 * Prototypes
126 */
127 static uint32_t find_closest_prescaler(uint32_t num_tq_mul_prescaler, uint32_t start_prescaler,
128 uint32_t max_tq, uint32_t min_tq);
129
130 static uint8_t can_get_data_words_from_dlc(uint32_t dlc);
131
132 static void can_fill_tx_buffer(CAN_Type *base, const can_transmit_buf_t *message);
133
134
135 /***********************************************************************************************************************
136 *
137 * Codes
138 */
find_closest_prescaler(uint32_t num_tq_mul_prescaler,uint32_t start_prescaler,uint32_t max_tq,uint32_t min_tq)139 static uint32_t find_closest_prescaler(uint32_t num_tq_mul_prescaler, uint32_t start_prescaler,
140 uint32_t max_tq, uint32_t min_tq)
141 {
142 bool has_found = false;
143
144 uint32_t prescaler = start_prescaler;
145
146 while (!has_found) {
147
148 if ((num_tq_mul_prescaler / prescaler > max_tq) || (num_tq_mul_prescaler % prescaler != 0)) {
149 ++prescaler;
150 continue;
151 } else {
152 uint32_t tq = num_tq_mul_prescaler / prescaler;
153 if (tq * prescaler == num_tq_mul_prescaler) {
154 has_found = true;
155 break;
156 } else if (tq < min_tq) {
157 has_found = false;
158 break;
159 } else {
160 ++prescaler;
161 }
162 }
163 }
164
165 return has_found ? prescaler : 0U;
166 }
167
168
can_calculate_bit_timing(uint32_t src_clk_freq,can_bit_timing_option_t option,uint32_t baudrate,uint16_t samplepoint_min,uint16_t samplepoint_max,can_bit_timing_param_t * timing_param)169 hpm_stat_t can_calculate_bit_timing(uint32_t src_clk_freq, can_bit_timing_option_t option, uint32_t baudrate,
170 uint16_t samplepoint_min, uint16_t samplepoint_max,
171 can_bit_timing_param_t *timing_param)
172 {
173 hpm_stat_t status = status_invalid_argument;
174 do {
175 if ((option > can_bit_timing_canfd_data) || (baudrate == 0U) ||
176 (src_clk_freq / baudrate < MIN_TQ_MUL_PRESCALE) || (timing_param == NULL)) {
177 break;
178 }
179
180 const can_bit_timing_table_t *tbl = &s_can_bit_timing_tbl[(uint8_t) option];
181
182 /* According to the CAN specification 2.0,
183 * the Tq must be in range specified in the above CAN bit-timing table
184 */
185 if (src_clk_freq / baudrate < tbl->tq_min) {
186 break;
187 }
188
189 uint32_t num_tq_mul_prescaler = src_clk_freq / baudrate;
190 uint32_t start_prescaler = 1U;
191 uint32_t num_seg1, num_seg2;
192 bool has_found = false;
193
194 /* Find out the minimum prescaler */
195 uint32_t current_prescaler;
196 while (!has_found) {
197 current_prescaler = find_closest_prescaler(num_tq_mul_prescaler, start_prescaler,
198 tbl->tq_max,
199 tbl->tq_min);
200 if ((current_prescaler < start_prescaler) || (current_prescaler > NUM_PRESCALE_MAX)) {
201 break;
202 }
203 uint32_t num_tq = num_tq_mul_prescaler / current_prescaler;
204
205 num_seg2 = (num_tq - tbl->min_diff_seg1_minus_seg2) / 2U;
206 num_seg1 = num_tq - num_seg2;
207 while (num_seg2 > tbl->seg2_max) {
208 num_seg2--;
209 num_seg1++;
210 }
211
212 /* Recommended sample point is 75% - 87.5% */
213 while ((num_seg1 * 1000U) / num_tq < samplepoint_min) {
214 ++num_seg1;
215 --num_seg2;
216 }
217
218 if ((num_seg1 * 1000U) / num_tq > samplepoint_max) {
219 break;
220 }
221
222 if ((num_seg2 >= tbl->seg2_min) && (num_seg1 <= tbl->seg1_max)) {
223 has_found = true;
224 } else {
225 start_prescaler = current_prescaler + 1U;
226 }
227 }
228
229 if (has_found) {
230 uint32_t num_sjw = MIN(tbl->sjw_max, num_seg2);
231 timing_param->num_seg1 = num_seg1;
232 timing_param->num_seg2 = num_seg2;
233 timing_param->num_sjw = num_sjw;
234 timing_param->prescaler = current_prescaler;
235 status = status_success;
236 }
237 } while (false);
238
239 return status;
240 }
241
242
can_set_bit_timing(CAN_Type * base,can_bit_timing_option_t option,uint32_t src_clk_freq,uint32_t baudrate,uint16_t samplepoint_min,uint16_t samplepoint_max)243 hpm_stat_t can_set_bit_timing(CAN_Type *base, can_bit_timing_option_t option,
244 uint32_t src_clk_freq, uint32_t baudrate,
245 uint16_t samplepoint_min, uint16_t samplepoint_max)
246 {
247 hpm_stat_t status = status_invalid_argument;
248
249 do {
250 if (base == NULL) {
251 break;
252 }
253
254 can_bit_timing_param_t timing_param;
255 status = can_calculate_bit_timing(src_clk_freq, option, baudrate, samplepoint_min, samplepoint_max, &timing_param);
256
257 if (status == status_success) {
258 if (option < can_bit_timing_canfd_data) {
259 base->S_PRESC = CAN_S_PRESC_S_PRESC_SET(timing_param.prescaler - 1U) | CAN_S_PRESC_S_SEG_1_SET(timing_param.num_seg1 - 2U) |
260 CAN_S_PRESC_S_SEG_2_SET(timing_param.num_seg2 - 1U) | CAN_S_PRESC_S_SJW_SET(timing_param.num_sjw - 1U);
261 } else {
262 base->F_PRESC = CAN_F_PRESC_F_PRESC_SET(timing_param.prescaler - 1U) | CAN_F_PRESC_F_SEG_1_SET(timing_param.num_seg1 - 2U) |
263 CAN_F_PRESC_F_SEG_2_SET(timing_param.num_seg2 - 1U) | CAN_F_PRESC_F_SJW_SET(timing_param.num_sjw - 1U);
264
265 }
266 status = status_success;
267 }
268
269 } while (false);
270
271 return status;
272 }
273
can_set_filter(CAN_Type * base,const can_filter_config_t * config)274 hpm_stat_t can_set_filter(CAN_Type *base, const can_filter_config_t *config)
275 {
276 hpm_stat_t status = status_invalid_argument;
277
278 do {
279 if ((base == NULL) || (config == NULL)) {
280 break;
281 }
282 if (config->index > CAN_FILTER_INDEX_MAX) {
283 status = status_can_filter_index_invalid;
284 break;
285 }
286
287 /* Configure acceptance code */
288 base->ACFCTRL = CAN_ACFCTRL_ACFADR_SET(config->index);
289 base->ACF = CAN_ACF_CODE_MASK_SET(config->code);
290
291 /* Configure acceptance mask */
292 uint32_t acf_value = CAN_ACF_CODE_MASK_SET(config->mask);
293 if (config->id_mode == can_filter_id_mode_standard_frames) {
294 acf_value |= CAN_ACF_AIDEE_MASK;
295 } else if (config->id_mode == can_filter_id_mode_extended_frames) {
296 acf_value |= CAN_ACF_AIDEE_MASK | CAN_ACF_AIDE_MASK;
297 } else {
298 /* Treat it as the default mode */
299 acf_value |= 0;
300 }
301
302 base->ACFCTRL = CAN_ACFCTRL_SELMASK_MASK | CAN_ACFCTRL_ACFADR_SET(config->index);
303 base->ACF = acf_value;
304
305 if (config->enable) {
306 base->ACF_EN |= (1U << config->index);
307 } else {
308 base->ACF_EN &= (uint16_t) ~(1U << config->index);
309 }
310 status = status_success;
311 } while (false);
312
313 return status;
314 }
315
can_get_data_words_from_dlc(uint32_t dlc)316 static uint8_t can_get_data_words_from_dlc(uint32_t dlc)
317 {
318 uint32_t copy_words = 0;
319
320 dlc &= 0xFU;
321 if (dlc <= 8U) {
322 copy_words = (dlc + 3U) / sizeof(uint32_t);
323 } else {
324 switch (dlc) {
325 case can_payload_size_12:
326 copy_words = 3U;
327 break;
328 case can_payload_size_16:
329 copy_words = 4U;
330 break;
331 case can_payload_size_20:
332 copy_words = 5U;
333 break;
334 case can_payload_size_24:
335 copy_words = 6U;
336 break;
337 case can_payload_size_32:
338 copy_words = 8U;
339 break;
340 case can_payload_size_48:
341 copy_words = 12U;
342 break;
343 case can_payload_size_64:
344 copy_words = 16U;
345 break;
346 default:
347 /* Code should never touch here */
348 break;
349 }
350 }
351
352 return copy_words;
353 }
354
can_fill_tx_buffer(CAN_Type * base,const can_transmit_buf_t * message)355 static void can_fill_tx_buffer(CAN_Type *base, const can_transmit_buf_t *message)
356 {
357 base->TBUF[0] = message->buffer[0];
358 base->TBUF[1] = message->buffer[1];
359
360 uint32_t copy_words = can_get_data_words_from_dlc(message->dlc);
361 for (uint32_t i = 0U; i < copy_words; i++) {
362 base->TBUF[2U + i] = message->buffer[2U + i];
363 }
364 }
365
can_send_message_blocking(CAN_Type * base,const can_transmit_buf_t * message)366 hpm_stat_t can_send_message_blocking(CAN_Type *base, const can_transmit_buf_t *message)
367 {
368 hpm_stat_t status = status_invalid_argument;
369
370 do {
371
372 if ((base == NULL) || (message == NULL)) {
373 break;
374 }
375
376 status = status_success;
377 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
378
379 can_fill_tx_buffer(base, message);
380
381 /* Wait until STB is not full */
382 int32_t timeout_cnt = CAN_TIMEOUT_CNT;
383 while (CAN_CMD_STA_CMD_CTRL_TSSTAT_GET(base->CMD_STA_CMD_CTRL) == CAN_STB_IS_FULL) {
384 timeout_cnt--;
385 if (timeout_cnt <= 0) {
386 status = status_timeout;
387 break;
388 }
389 }
390 if (status != status_success) {
391 break;
392 }
393
394 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSNEXT_MASK | CAN_CMD_STA_CMD_CTRL_TSONE_MASK;
395 timeout_cnt = CAN_TIMEOUT_CNT;
396 while (CAN_CMD_STA_CMD_CTRL_TSSTAT_GET(base->CMD_STA_CMD_CTRL) != CAN_STB_IS_EMPTY) {
397 timeout_cnt--;
398 if (timeout_cnt <= 0) {
399 status = status_timeout;
400 break;
401 }
402 }
403
404 } while (false);
405
406 return status;
407 }
408
can_send_high_priority_message_blocking(CAN_Type * base,const can_transmit_buf_t * message)409 hpm_stat_t can_send_high_priority_message_blocking(CAN_Type *base, const can_transmit_buf_t *message)
410 {
411 hpm_stat_t status = status_invalid_argument;
412
413 do {
414 HPM_BREAK_IF((base == NULL) || (message == NULL));
415 status = status_success;
416
417 /* Select the high-priority buffer */
418 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
419
420 can_fill_tx_buffer(base, message);
421
422 /* Send the data out */
423 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPE_MASK;
424 /* Wait until the data is sent out */
425 int32_t timeout_cnt = CAN_TIMEOUT_CNT;
426 while (IS_HPM_BITMASK_SET(base->CMD_STA_CMD_CTRL, CAN_CMD_STA_CMD_CTRL_TPE_MASK)) {
427 timeout_cnt--;
428 if (timeout_cnt <= 0) {
429 status = status_timeout;
430 break;
431 }
432 }
433 } while (false);
434
435 return status;
436 }
437
can_send_message_nonblocking(CAN_Type * base,const can_transmit_buf_t * message)438 hpm_stat_t can_send_message_nonblocking(CAN_Type *base, const can_transmit_buf_t *message)
439 {
440 hpm_stat_t status = status_invalid_argument;
441
442 do {
443
444 if ((base == NULL) || (message == NULL)) {
445 break;
446 }
447
448 if (CAN_CMD_STA_CMD_CTRL_TSSTAT_GET(base->CMD_STA_CMD_CTRL) == CAN_STB_IS_FULL) {
449 status = status_can_tx_fifo_full;
450 break;
451 }
452
453 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
454 can_fill_tx_buffer(base, message);
455 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSNEXT_MASK | CAN_CMD_STA_CMD_CTRL_TSONE_MASK;
456
457 status = status_success;
458
459 } while (false);
460
461 return status;
462 }
463
can_send_high_priority_message_nonblocking(CAN_Type * base,const can_transmit_buf_t * message)464 hpm_stat_t can_send_high_priority_message_nonblocking(CAN_Type *base, const can_transmit_buf_t *message)
465 {
466 hpm_stat_t status = status_invalid_argument;
467
468 do {
469 HPM_BREAK_IF((base == NULL) || (message == NULL));
470 status = status_success;
471
472 if (IS_HPM_BITMASK_SET(base->CMD_STA_CMD_CTRL, CAN_CMD_STA_CMD_CTRL_TPE_MASK)) {
473 status = status_can_tx_fifo_full;
474 break;
475 }
476 /* Select the high-priority buffer */
477 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
478
479 can_fill_tx_buffer(base, message);
480
481 /* Send the data out */
482 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPE_MASK;
483 } while (false);
484
485 return status;
486 }
487
can_receive_message_blocking(CAN_Type * base,can_receive_buf_t * message)488 hpm_stat_t can_receive_message_blocking(CAN_Type *base, can_receive_buf_t *message)
489 {
490 hpm_stat_t status = status_invalid_argument;
491
492 do {
493 HPM_BREAK_IF((base == NULL) || (message == NULL));
494
495 while (CAN_CMD_STA_CMD_CTRL_RSTAT_GET(base->CMD_STA_CMD_CTRL) == CAN_RXBUF_IS_EMPTY) {
496
497 }
498
499 /* Get the first 2 words (including CAN ID, Data length and other control bits) */
500 message->buffer[0] = base->RBUF[0];
501 message->buffer[1] = base->RBUF[1];
502
503 if (message->error_type != 0U) {
504 switch (message->error_type) {
505 case 1:
506 status = status_can_bit_error;
507 break;
508 case 2:
509 status = status_can_form_error;
510 break;
511 case 3:
512 status = status_can_stuff_error;
513 break;
514 case 4:
515 status = status_can_ack_error;
516 break;
517 case 5:
518 status = status_can_crc_error;
519 break;
520 default:
521 status = status_can_other_error;
522 break;
523 }
524 break;
525 }
526
527 if (message->remote_frame == 0U) {
528 uint32_t copy_words = can_get_data_words_from_dlc(message->dlc);
529
530 for (uint32_t i = 0; i < copy_words; i++) {
531 message->buffer[2U + i] = base->RBUF[2U + i];
532 }
533 }
534 /* Release the current buffer */
535 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_RREL_MASK;
536
537 status = status_success;
538
539 } while (false);
540
541 return status;
542 }
543
can_read_received_message(CAN_Type * base,can_receive_buf_t * message)544 hpm_stat_t can_read_received_message(CAN_Type *base, can_receive_buf_t *message)
545 {
546 hpm_stat_t status;
547
548 assert((base != NULL) && (message != NULL));
549
550 do {
551 /* Get the first 2 words (including CAN ID, Data length and other control bits) */
552 message->buffer[0] = base->RBUF[0];
553 message->buffer[1] = base->RBUF[1];
554
555 if (message->error_type != 0U) {
556 switch (message->error_type) {
557 case 1:
558 status = status_can_bit_error;
559 break;
560 case 2:
561 status = status_can_form_error;
562 break;
563 case 3:
564 status = status_can_stuff_error;
565 break;
566 case 4:
567 status = status_can_ack_error;
568 break;
569 case 5:
570 status = status_can_crc_error;
571 break;
572 default:
573 status = status_can_other_error;
574 break;
575 }
576 break;
577 }
578
579 if (message->remote_frame == 0U) {
580 uint32_t copy_words = can_get_data_words_from_dlc(message->dlc);
581
582 for (uint32_t i = 0; i < copy_words; i++) {
583 message->buffer[2U + i] = base->RBUF[2U + i];
584 }
585 }
586 /* Release the current buffer */
587 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_RREL_MASK;
588
589 status = status_success;
590
591 } while (false);
592
593 return status;
594 }
595
can_get_default_config(can_config_t * config)596 hpm_stat_t can_get_default_config(can_config_t *config)
597 {
598 hpm_stat_t status = status_invalid_argument;
599 if (config != NULL) {
600
601 /* Default timing mode */
602 config->baudrate = 1000000UL; /* 1Mbit/s */
603 config->baudrate_fd = 0U;
604 config->use_lowlevel_timing_setting = false;
605 config->can20_samplepoint_min = CAN_SAMPLEPOINT_MIN;
606 config->can20_samplepoint_max = CAN_SAMPLEPOINT_MAX;
607 config->canfd_samplepoint_min = CAN_SAMPLEPOINT_MIN;
608 config->canfd_samplepoint_max = CAN_SAMPLEPOINT_MAX;
609 config->enable_canfd = false;
610 config->enable_can_fd_iso_mode = true;
611
612 config->mode = can_mode_normal;
613 config->enable_self_ack = false;
614 config->disable_re_transmission_for_stb = false;
615 config->disable_re_transmission_for_ptb = false;
616 config->enable_tx_buffer_priority_mode = false;
617 config->enable_tdc = false;
618
619 /* Default filter settings */
620 config->filter_list_num = 0;
621 config->filter_list = NULL;
622
623 /* Default Interrupt enable settings */
624 config->irq_txrx_enable_mask = 0;
625 config->irq_error_enable_mask = 0;
626
627 status = status_success;
628 }
629
630 return status;
631 }
632
can_init(CAN_Type * base,can_config_t * config,uint32_t src_clk_freq)633 hpm_stat_t can_init(CAN_Type *base, can_config_t *config, uint32_t src_clk_freq)
634 {
635 hpm_stat_t status = status_invalid_argument;
636
637 do {
638
639 HPM_BREAK_IF((base == NULL) || (config == NULL) || (src_clk_freq == 0U) || (config->filter_list_num > 16U));
640
641 can_reset(base, true);
642
643 base->TTCFG &= ~CAN_TTCFG_TTEN_MASK;
644 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TTTBM_MASK;
645
646 if (!config->use_lowlevel_timing_setting) {
647 if (config->enable_canfd) {
648 status = can_set_bit_timing(base, can_bit_timing_canfd_norminal,
649 src_clk_freq, config->baudrate,
650 config->can20_samplepoint_min, config->can20_samplepoint_max);
651 HPM_BREAK_IF(status != status_success);
652 status = can_set_bit_timing(base, can_bit_timing_canfd_data,
653 src_clk_freq, config->baudrate_fd,
654 config->canfd_samplepoint_min, config->canfd_samplepoint_max);
655 } else {
656 status = can_set_bit_timing(base, can_bit_timing_can2_0,
657 src_clk_freq, config->baudrate,
658 config->can20_samplepoint_min, config->can20_samplepoint_max);
659 }
660 } else {
661 can_set_slow_speed_timing(base, &config->can_timing);
662 if (config->enable_canfd) {
663 can_set_fast_speed_timing(base, &config->canfd_timing);
664 }
665 status = status_success;
666 }
667
668 /* Enable Transmitter Delay Compensation as needed */
669 uint32_t ssp_offset = CAN_F_PRESC_F_SEG_1_GET(base->F_PRESC) + 2U;
670 can_set_transmitter_delay_compensation(base, ssp_offset, config->enable_tdc);
671
672 HPM_BREAK_IF(status != status_success);
673
674 if (config->disable_re_transmission_for_ptb) {
675 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPSS_MASK;
676 } else {
677 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TPSS_MASK;
678 }
679
680 if (config->disable_re_transmission_for_stb) {
681 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSSS_MASK;
682 } else {
683 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TSSS_MASK;
684 }
685
686 /* Configure CAN filters */
687 if (config->filter_list_num > CAN_FILTER_NUM_MAX) {
688 status = status_can_filter_num_invalid;
689 break;
690 } else if (config->filter_list_num == 0) {
691 can_filter_config_t default_filter = CAN_DEFAULT_FILTER_SETTING;
692 for (uint32_t i = 0; i < CAN_FILTER_NUM_MAX; i++) {
693 can_disable_filter(base, i);
694 }
695 (void) can_set_filter(base, &default_filter);
696 } else {
697 for (uint32_t i = 0; i < CAN_FILTER_NUM_MAX; i++) {
698 can_disable_filter(base, i);
699 }
700 for (uint32_t i = 0; i < config->filter_list_num; i++) {
701 status = can_set_filter(base, &config->filter_list[i]);
702 if (status != status_success) {
703 return status;
704 }
705 }
706 }
707
708 /* Set CAN FD standard */
709 can_enable_can_fd_iso_mode(base, config->enable_can_fd_iso_mode);
710
711 can_reset(base, false);
712
713 /* Set Self-ack mode*/
714 can_enable_self_ack(base, config->enable_self_ack);
715
716 /* Set CAN work mode */
717 can_set_node_mode(base, config->mode);
718
719 /* Configure TX Buffer priority mode */
720 can_select_tx_buffer_priority_mode(base, config->enable_tx_buffer_priority_mode);
721
722 /* Configure interrupt */
723 can_disable_tx_rx_irq(base, 0xFFU);
724 can_disable_error_irq(base, 0xFFU);
725 can_enable_tx_rx_irq(base, config->irq_txrx_enable_mask);
726 can_enable_error_irq(base, config->irq_error_enable_mask);
727
728 status = status_success;
729 } while (false);
730
731 return status;
732 }
733
can_deinit(CAN_Type * base)734 void can_deinit(CAN_Type *base)
735 {
736 do {
737 HPM_BREAK_IF(base == NULL);
738 can_reset(base, true);
739 } while (false);
740 }