1 /*
2 * Copyright (c) 2021-2024 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_NOMINAL (2U)
20 #define TSEG1_MAX_FOR_CANFD_NOMINAL (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_NOMINAL (1U)
29 #define TSEG2_MAX_FOR_CANFD_NOMINAL (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_NOMINAL (1U)
38 #define TSJW_MAX_FOR_CANFD_NOMINAL (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_NOMINAL + TSEG2_MAX_FOR_CANFD_NOMINAL)
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 CAN_TIMEOUT_CNT (0xFFFFFFUL)
60
61 #define CAN_SAMPLEPOINT_MIN (750U)
62 #define CAN_SAMPLEPOINT_MAX (875U)
63
64
65 #define CAN_DEFAULT_FILTER_SETTING {0, can_filter_id_mode_both_frames, true, 0, (1UL << 29) - 1U }
66
67 /*
68 * @brief CAN bit-timing table
69 */
70 typedef struct {
71 uint8_t tq_min;
72 uint8_t tq_max;
73 uint8_t seg1_min;
74 uint8_t seg1_max;
75 uint8_t seg2_min;
76 uint8_t seg2_max;
77 uint8_t sjw_min;
78 uint8_t sjw_max;
79 uint8_t min_diff_seg1_minus_seg2;
80 } can_bit_timing_table_t;
81
82 /**
83 * @brief CAN bit timing list for all supported bit timing modes
84 */
85 static const can_bit_timing_table_t s_can_bit_timing_tbl[3] = {
86 {
87 .tq_min = NUM_TQ_MIN_FOR_CAN2_0,
88 .tq_max = NUM_TQ_MAX_FOR_CAN2_0,
89 .seg1_min = TSEG1_MIN_FOR_CAN2_0,
90 .seg1_max = TSEG1_MAX_FOR_CAN2_0,
91 .seg2_min = TSEG2_MIN_FOR_CAN2_0,
92 .seg2_max = TSEG2_MAX_FOR_CAN2_0,
93 .sjw_min = TSJW_MIN_FOR_CAN2_0,
94 .sjw_max = TSJW_MAX_FOR_CAN2_0,
95 .min_diff_seg1_minus_seg2 = 2,
96 },
97 {
98 .tq_min = NUM_TQ_MIN_FOR_CANFD_NOMINAL,
99 .tq_max = NUM_TQ_MAX_FOR_CANFD_NOMINAL,
100 .seg1_min = TSEG1_MIN_FOR_CANFD_NOMINAL,
101 .seg1_max = TSEG1_MAX_FOR_CANFD_NOMINAL,
102 .seg2_min = TSEG2_MIN_FOR_CANFD_NOMINAL,
103 .seg2_max = TSEG2_MAX_FOR_CANFD_NOMINAL,
104 .sjw_min = TSJW_MIN_FOR_CANFD_NOMINAL,
105 .sjw_max = TSJW_MAX_FOR_CANFD_NOMINAL,
106 .min_diff_seg1_minus_seg2 = 2,
107 },
108 {
109 .tq_min = NUM_TQ_MIN_FOR_CANFD_DATA,
110 .tq_max = NUM_TQ_MAX_FOR_CANFD_DATA,
111 .seg1_min = TSEG1_MIN_FOR_CANFD_DATA,
112 .seg1_max = TSEG1_MAX_FOR_CANFD_DATA,
113 .seg2_min = TSEG2_MIN_FOR_CANFD_DATA,
114 .seg2_max = TSEG2_MAX_FOR_CANFD_DATA,
115 .sjw_min = TSJW_MIN_FOR_CANFD_DATA,
116 .sjw_max = TSJW_MAX_FOR_CANFD_DATA,
117 .min_diff_seg1_minus_seg2 = 1,
118 }
119 };
120
121 /***********************************************************************************************************************
122 *
123 * Prototypes
124 */
125 static uint32_t find_optimal_prescaler(uint32_t num_tq_mul_prescaler, uint32_t start_prescaler,
126 uint32_t max_tq, uint32_t min_tq);
127
128 static uint8_t can_get_data_words_from_dlc(uint32_t dlc);
129
130 static void can_fill_tx_buffer(CAN_Type *base, const can_transmit_buf_t *message);
131
132 static bool is_can_bit_timing_param_valid(can_bit_timing_option_t option, const can_bit_timing_param_t *param);
133
134
135 /***********************************************************************************************************************
136 *
137 * Codes
138 */
find_optimal_prescaler(uint32_t num_tq_mul_prescaler,uint32_t start_prescaler,uint32_t max_tq,uint32_t min_tq)139 static uint32_t find_optimal_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_optimal_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
is_can_bit_timing_param_valid(can_bit_timing_option_t option,const can_bit_timing_param_t * param)242 static bool is_can_bit_timing_param_valid(can_bit_timing_option_t option, const can_bit_timing_param_t *param)
243 {
244 bool result = false;
245 const can_bit_timing_table_t *tbl = &s_can_bit_timing_tbl[(uint8_t) option];
246 do {
247 if ((param->num_seg1 < tbl->seg1_min) || (param->num_seg1 > tbl->seg1_max)) {
248 break;
249 }
250 if ((param->num_seg2 < tbl->seg2_min) || (param->num_seg2 > tbl->seg2_max)) {
251 break;
252 }
253 if ((param->num_sjw < tbl->sjw_min) || (param->num_sjw > tbl->sjw_max)) {
254 break;
255 }
256 if (param->prescaler > NUM_PRESCALE_MAX) {
257 break;
258 }
259 result = true;
260 } while (false);
261
262 return result;
263 }
264
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)265 hpm_stat_t can_set_bit_timing(CAN_Type *base, can_bit_timing_option_t option,
266 uint32_t src_clk_freq, uint32_t baudrate,
267 uint16_t samplepoint_min, uint16_t samplepoint_max)
268 {
269 hpm_stat_t status = status_invalid_argument;
270
271 do {
272 if (base == NULL) {
273 break;
274 }
275
276 can_bit_timing_param_t timing_param;
277 status = can_calculate_bit_timing(src_clk_freq, option, baudrate, samplepoint_min, samplepoint_max, &timing_param);
278
279 if (status == status_success) {
280 if (option < can_bit_timing_canfd_data) {
281 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) |
282 CAN_S_PRESC_S_SEG_2_SET(timing_param.num_seg2 - 1U) | CAN_S_PRESC_S_SJW_SET(timing_param.num_sjw - 1U);
283 } else {
284 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) |
285 CAN_F_PRESC_F_SEG_2_SET(timing_param.num_seg2 - 1U) | CAN_F_PRESC_F_SJW_SET(timing_param.num_sjw - 1U);
286
287 }
288 status = status_success;
289 }
290
291 } while (false);
292
293 return status;
294 }
295
can_set_filter(CAN_Type * base,const can_filter_config_t * config)296 hpm_stat_t can_set_filter(CAN_Type *base, const can_filter_config_t *config)
297 {
298 hpm_stat_t status = status_invalid_argument;
299
300 do {
301 if ((base == NULL) || (config == NULL)) {
302 break;
303 }
304 if (config->index > CAN_FILTER_INDEX_MAX) {
305 status = status_can_filter_index_invalid;
306 break;
307 }
308
309 /* Configure acceptance code */
310 base->ACFCTRL = CAN_ACFCTRL_ACFADR_SET(config->index);
311 base->ACF = CAN_ACF_CODE_MASK_SET(config->code);
312
313 /* Configure acceptance mask */
314 uint32_t acf_value = CAN_ACF_CODE_MASK_SET(config->mask);
315 if (config->id_mode == can_filter_id_mode_standard_frames) {
316 acf_value |= CAN_ACF_AIDEE_MASK;
317 } else if (config->id_mode == can_filter_id_mode_extended_frames) {
318 acf_value |= CAN_ACF_AIDEE_MASK | CAN_ACF_AIDE_MASK;
319 } else {
320 /* Treat it as the default mode */
321 acf_value |= 0;
322 }
323
324 base->ACFCTRL = CAN_ACFCTRL_SELMASK_MASK | CAN_ACFCTRL_ACFADR_SET(config->index);
325 base->ACF = acf_value;
326
327 if (config->enable) {
328 base->ACF_EN |= (1U << config->index);
329 } else {
330 base->ACF_EN &= (uint16_t) ~(1U << config->index);
331 }
332 status = status_success;
333 } while (false);
334
335 return status;
336 }
337
can_get_data_words_from_dlc(uint32_t dlc)338 static uint8_t can_get_data_words_from_dlc(uint32_t dlc)
339 {
340 uint32_t copy_words = 0;
341
342 dlc &= 0xFU;
343 if (dlc <= 8U) {
344 copy_words = (dlc + 3U) / sizeof(uint32_t);
345 } else {
346 switch (dlc) {
347 case can_payload_size_12:
348 copy_words = 3U;
349 break;
350 case can_payload_size_16:
351 copy_words = 4U;
352 break;
353 case can_payload_size_20:
354 copy_words = 5U;
355 break;
356 case can_payload_size_24:
357 copy_words = 6U;
358 break;
359 case can_payload_size_32:
360 copy_words = 8U;
361 break;
362 case can_payload_size_48:
363 copy_words = 12U;
364 break;
365 case can_payload_size_64:
366 copy_words = 16U;
367 break;
368 default:
369 /* Code should never touch here */
370 break;
371 }
372 }
373
374 return copy_words;
375 }
376
can_fill_tx_buffer(CAN_Type * base,const can_transmit_buf_t * message)377 static void can_fill_tx_buffer(CAN_Type *base, const can_transmit_buf_t *message)
378 {
379 base->TBUF[0] = message->buffer[0];
380 base->TBUF[1] = message->buffer[1];
381
382 uint32_t copy_words = can_get_data_words_from_dlc(message->dlc);
383 for (uint32_t i = 0U; i < copy_words; i++) {
384 base->TBUF[2U + i] = message->buffer[2U + i];
385 }
386 }
387
can_send_message_blocking(CAN_Type * base,const can_transmit_buf_t * message)388 hpm_stat_t can_send_message_blocking(CAN_Type *base, const can_transmit_buf_t *message)
389 {
390 hpm_stat_t status = status_invalid_argument;
391
392 do {
393
394 if ((base == NULL) || (message == NULL)) {
395 break;
396 }
397
398 status = status_success;
399 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
400
401 can_fill_tx_buffer(base, message);
402
403 /* Wait until STB is not full */
404 int32_t timeout_cnt = CAN_TIMEOUT_CNT;
405 while (CAN_CMD_STA_CMD_CTRL_TSSTAT_GET(base->CMD_STA_CMD_CTRL) == CAN_STB_IS_FULL) {
406 timeout_cnt--;
407 if (timeout_cnt <= 0) {
408 status = status_timeout;
409 break;
410 }
411 }
412 if (status != status_success) {
413 break;
414 }
415
416 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSNEXT_MASK | CAN_CMD_STA_CMD_CTRL_TSONE_MASK;
417 timeout_cnt = CAN_TIMEOUT_CNT;
418 while (CAN_CMD_STA_CMD_CTRL_TSSTAT_GET(base->CMD_STA_CMD_CTRL) != CAN_STB_IS_EMPTY) {
419 timeout_cnt--;
420 if (timeout_cnt <= 0) {
421 status = status_timeout;
422 break;
423 }
424 }
425
426 } while (false);
427
428 return status;
429 }
430
can_send_high_priority_message_blocking(CAN_Type * base,const can_transmit_buf_t * message)431 hpm_stat_t can_send_high_priority_message_blocking(CAN_Type *base, const can_transmit_buf_t *message)
432 {
433 hpm_stat_t status = status_invalid_argument;
434
435 do {
436 HPM_BREAK_IF((base == NULL) || (message == NULL));
437 status = status_success;
438
439 /* Select the high-priority buffer */
440 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
441
442 can_fill_tx_buffer(base, message);
443
444 /* Send the data out */
445 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPE_MASK;
446 /* Wait until the data is sent out */
447 int32_t timeout_cnt = CAN_TIMEOUT_CNT;
448 while (IS_HPM_BITMASK_SET(base->CMD_STA_CMD_CTRL, CAN_CMD_STA_CMD_CTRL_TPE_MASK)) {
449 timeout_cnt--;
450 if (timeout_cnt <= 0) {
451 status = status_timeout;
452 break;
453 }
454 }
455 } while (false);
456
457 return status;
458 }
459
can_send_message_nonblocking(CAN_Type * base,const can_transmit_buf_t * message)460 hpm_stat_t can_send_message_nonblocking(CAN_Type *base, const can_transmit_buf_t *message)
461 {
462 hpm_stat_t status = status_invalid_argument;
463
464 do {
465
466 if ((base == NULL) || (message == NULL)) {
467 break;
468 }
469
470 if (CAN_CMD_STA_CMD_CTRL_TSSTAT_GET(base->CMD_STA_CMD_CTRL) == CAN_STB_IS_FULL) {
471 status = status_can_tx_fifo_full;
472 break;
473 }
474
475 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
476 can_fill_tx_buffer(base, message);
477 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSNEXT_MASK | CAN_CMD_STA_CMD_CTRL_TSONE_MASK;
478
479 status = status_success;
480
481 } while (false);
482
483 return status;
484 }
485
can_send_high_priority_message_nonblocking(CAN_Type * base,const can_transmit_buf_t * message)486 hpm_stat_t can_send_high_priority_message_nonblocking(CAN_Type *base, const can_transmit_buf_t *message)
487 {
488 hpm_stat_t status = status_invalid_argument;
489
490 do {
491 HPM_BREAK_IF((base == NULL) || (message == NULL));
492 status = status_success;
493
494 if (IS_HPM_BITMASK_SET(base->CMD_STA_CMD_CTRL, CAN_CMD_STA_CMD_CTRL_TPE_MASK)) {
495 status = status_can_tx_fifo_full;
496 break;
497 }
498 /* Select the high-priority buffer */
499 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
500
501 can_fill_tx_buffer(base, message);
502
503 /* Send the data out */
504 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPE_MASK;
505 } while (false);
506
507 return status;
508 }
509
can_receive_message_blocking(CAN_Type * base,can_receive_buf_t * message)510 hpm_stat_t can_receive_message_blocking(CAN_Type *base, can_receive_buf_t *message)
511 {
512 hpm_stat_t status = status_invalid_argument;
513
514 do {
515 HPM_BREAK_IF((base == NULL) || (message == NULL));
516
517 while (CAN_CMD_STA_CMD_CTRL_RSTAT_GET(base->CMD_STA_CMD_CTRL) == CAN_RXBUF_IS_EMPTY) {
518
519 }
520
521 /* Get the first 2 words (including CAN ID, Data length and other control bits) */
522 message->buffer[0] = base->RBUF[0];
523 message->buffer[1] = base->RBUF[1];
524
525 if (message->error_type != 0U) {
526 switch (message->error_type) {
527 case 1:
528 status = status_can_bit_error;
529 break;
530 case 2:
531 status = status_can_form_error;
532 break;
533 case 3:
534 status = status_can_stuff_error;
535 break;
536 case 4:
537 status = status_can_ack_error;
538 break;
539 case 5:
540 status = status_can_crc_error;
541 break;
542 default:
543 status = status_can_other_error;
544 break;
545 }
546 break;
547 }
548
549 if (message->remote_frame == 0U) {
550 uint32_t copy_words = can_get_data_words_from_dlc(message->dlc);
551
552 for (uint32_t i = 0; i < copy_words; i++) {
553 message->buffer[2U + i] = base->RBUF[2U + i];
554 }
555 }
556 /* Release the current buffer */
557 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_RREL_MASK;
558
559 status = status_success;
560
561 } while (false);
562
563 return status;
564 }
565
can_read_received_message(CAN_Type * base,can_receive_buf_t * message)566 hpm_stat_t can_read_received_message(CAN_Type *base, can_receive_buf_t *message)
567 {
568 hpm_stat_t status;
569
570 assert((base != NULL) && (message != NULL));
571
572 do {
573 /* Get the first 2 words (including CAN ID, Data length and other control bits) */
574 message->buffer[0] = base->RBUF[0];
575 message->buffer[1] = base->RBUF[1];
576
577 if (message->error_type != 0U) {
578 switch (message->error_type) {
579 case 1:
580 status = status_can_bit_error;
581 break;
582 case 2:
583 status = status_can_form_error;
584 break;
585 case 3:
586 status = status_can_stuff_error;
587 break;
588 case 4:
589 status = status_can_ack_error;
590 break;
591 case 5:
592 status = status_can_crc_error;
593 break;
594 default:
595 status = status_can_other_error;
596 break;
597 }
598 break;
599 }
600
601 if (message->remote_frame == 0U) {
602 uint32_t copy_words = can_get_data_words_from_dlc(message->dlc);
603
604 for (uint32_t i = 0; i < copy_words; i++) {
605 message->buffer[2U + i] = base->RBUF[2U + i];
606 }
607 }
608 /* Release the current buffer */
609 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_RREL_MASK;
610
611 status = status_success;
612
613 } while (false);
614
615 return status;
616 }
617
can_get_default_config(can_config_t * config)618 hpm_stat_t can_get_default_config(can_config_t *config)
619 {
620 hpm_stat_t status = status_invalid_argument;
621 if (config != NULL) {
622
623 /* Default timing mode */
624 config->baudrate = 1000000UL; /* 1Mbit/s */
625 config->baudrate_fd = 0U;
626 config->use_lowlevel_timing_setting = false;
627 config->can20_samplepoint_min = CAN_SAMPLEPOINT_MIN;
628 config->can20_samplepoint_max = CAN_SAMPLEPOINT_MAX;
629 config->canfd_samplepoint_min = CAN_SAMPLEPOINT_MIN;
630 config->canfd_samplepoint_max = CAN_SAMPLEPOINT_MAX;
631 config->enable_canfd = false;
632 config->enable_can_fd_iso_mode = true;
633
634 config->mode = can_mode_normal;
635 config->enable_self_ack = false;
636 config->disable_stb_retransmission = false;
637 config->disable_ptb_retransmission = false;
638 config->enable_tx_buffer_priority_mode = false;
639 config->enable_tdc = false;
640
641 /* Default filter settings */
642 config->filter_list_num = 0;
643 config->filter_list = NULL;
644
645 /* Default Interrupt enable settings */
646 config->irq_txrx_enable_mask = 0;
647 config->irq_error_enable_mask = 0;
648
649 status = status_success;
650 }
651
652 return status;
653 }
654
can_init(CAN_Type * base,can_config_t * config,uint32_t src_clk_freq)655 hpm_stat_t can_init(CAN_Type *base, can_config_t *config, uint32_t src_clk_freq)
656 {
657 hpm_stat_t status = status_invalid_argument;
658
659 do {
660
661 HPM_BREAK_IF((base == NULL) || (config == NULL) || (src_clk_freq == 0U) || (config->filter_list_num > 16U));
662
663 can_reset(base, true);
664
665 base->TTCFG &= ~CAN_TTCFG_TTEN_MASK;
666 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TTTBM_MASK;
667
668 if (!config->use_lowlevel_timing_setting) {
669 if (config->enable_canfd) {
670 status = can_set_bit_timing(base,
671 can_bit_timing_canfd_nominal,
672 src_clk_freq,
673 config->baudrate,
674 config->can20_samplepoint_min,
675 config->can20_samplepoint_max);
676 HPM_BREAK_IF(status != status_success);
677 status = can_set_bit_timing(base,
678 can_bit_timing_canfd_data,
679 src_clk_freq,
680 config->baudrate_fd,
681 config->canfd_samplepoint_min,
682 config->canfd_samplepoint_max);
683 } else {
684 status = can_set_bit_timing(base,
685 can_bit_timing_can2_0,
686 src_clk_freq,
687 config->baudrate,
688 config->can20_samplepoint_min,
689 config->can20_samplepoint_max);
690 }
691 } else {
692 if (config->enable_canfd) {
693 bool param_valid = is_can_bit_timing_param_valid(can_bit_timing_canfd_nominal, &config->can_timing);
694 if (!param_valid) {
695 status = status_can_invalid_bit_timing;
696 break;
697 }
698 param_valid = is_can_bit_timing_param_valid(can_bit_timing_canfd_data, &config->canfd_timing);
699 if (!param_valid) {
700 status = status_can_invalid_bit_timing;
701 break;
702 }
703 can_set_slow_speed_timing(base, &config->can_timing);
704 can_set_fast_speed_timing(base, &config->canfd_timing);
705 } else {
706 bool param_valid = is_can_bit_timing_param_valid(can_bit_timing_can2_0, &config->can_timing);
707 if (!param_valid) {
708 status = status_can_invalid_bit_timing;
709 break;
710 }
711 can_set_slow_speed_timing(base, &config->can_timing);
712 }
713 status = status_success;
714 }
715
716 /* Enable Transmitter Delay Compensation as needed */
717 uint32_t ssp_offset = CAN_F_PRESC_F_SEG_1_GET(base->F_PRESC) + 2U;
718 can_set_transmitter_delay_compensation(base, ssp_offset, config->enable_tdc);
719
720 HPM_BREAK_IF(status != status_success);
721
722
723 /* Configure the CAN filters */
724 if (config->filter_list_num > CAN_FILTER_NUM_MAX) {
725 status = status_can_filter_num_invalid;
726 break;
727 } else if (config->filter_list_num == 0) {
728 can_filter_config_t default_filter = CAN_DEFAULT_FILTER_SETTING;
729 for (uint32_t i = 0; i < CAN_FILTER_NUM_MAX; i++) {
730 can_disable_filter(base, i);
731 }
732 (void) can_set_filter(base, &default_filter);
733 } else {
734 for (uint32_t i = 0; i < CAN_FILTER_NUM_MAX; i++) {
735 can_disable_filter(base, i);
736 }
737 for (uint32_t i = 0; i < config->filter_list_num; i++) {
738 status = can_set_filter(base, &config->filter_list[i]);
739 if (status != status_success) {
740 return status;
741 }
742 }
743 }
744
745 /* Set CAN FD standard */
746 can_enable_can_fd_iso_mode(base, config->enable_can_fd_iso_mode);
747
748 can_reset(base, false);
749
750 /* The following mode must be set when the CAN controller is not in reset mode */
751
752 /* Disable re-transmission on PTB on demand */
753 can_disable_ptb_retransmission(base, config->disable_ptb_retransmission);
754 /* Disable re-transmission on STB on demand */
755 can_disable_stb_retransmission(base, config->disable_stb_retransmission);
756
757 /* Set Self-ack mode*/
758 can_enable_self_ack(base, config->enable_self_ack);
759
760 /* Set CAN work mode */
761 can_set_node_mode(base, config->mode);
762
763 /* Configure TX Buffer priority mode */
764 can_select_tx_buffer_priority_mode(base, config->enable_tx_buffer_priority_mode);
765
766 /* Configure interrupt */
767 can_disable_tx_rx_irq(base, 0xFFU);
768 can_disable_error_irq(base, 0xFFU);
769 can_enable_tx_rx_irq(base, config->irq_txrx_enable_mask);
770 can_enable_error_irq(base, config->irq_error_enable_mask);
771
772 status = status_success;
773 } while (false);
774
775 return status;
776 }
777
can_deinit(CAN_Type * base)778 void can_deinit(CAN_Type *base)
779 {
780 do {
781 HPM_BREAK_IF(base == NULL);
782 can_force_bus_off(base);
783 can_reset(base, true);
784 } while (false);
785 }