1 /*
2 * Copyright (c) 2021-2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_CAN_DRV_H
9 #define HPM_CAN_DRV_H
10
11 #include "hpm_common.h"
12 #include "hpm_can_regs.h"
13 #include "hpm_soc_feature.h"
14
15 /**
16 * @brief CAN driver APIs
17 * @defgroup can_interface CAN driver APIs
18 * @ingroup can_interfaces
19 * @{
20 *
21 */
22
23 /***********************************************************************************************************************
24 *
25 * Definitions
26 *
27 **********************************************************************************************************************/
28
29 /**
30 * @brief CAN error codes
31 */
32 enum {
33 status_can_bit_error = MAKE_STATUS(status_group_can, 0), /**< CAN bit error */
34 status_can_form_error = MAKE_STATUS(status_group_can, 1), /**< CAN Form error */
35 status_can_stuff_error = MAKE_STATUS(status_group_can, 2), /**< CAN stuff error */
36 status_can_ack_error = MAKE_STATUS(status_group_can, 3), /**< CAN ACK error */
37 status_can_crc_error = MAKE_STATUS(status_group_can, 4), /**< CAN CRC error */
38 status_can_other_error = MAKE_STATUS(status_group_can, 5), /**< CAN other error */
39 status_can_tx_fifo_full = MAKE_STATUS(status_group_can, 6), /**< CAN TX fifo full */
40 status_can_filter_index_invalid = MAKE_STATUS(status_group_can, 7), /**< CAN filter index is invalid */
41 status_can_filter_num_invalid = MAKE_STATUS(status_group_can, 8), /**< CAN filter number is invalid */
42 };
43
44 /**
45 * @brief CAN Event definitions
46 */
47 #define CAN_EVENT_RECEIVE (CAN_RTIF_RIF_MASK) /**< CAN Receive event */
48 #define CAN_EVENT_RX_BUF_OVERRUN (CAN_RTIF_ROIF_MASK) /**< CAN RX buffer overrun event */
49 #define CAN_EVENT_RX_BUF_FULL (CAN_RTIF_RFIF_MASK) /**< CAN RX buffer full event */
50 #define CAN_EVENT_RX_BUF_ALMOST_FULL (CAN_RTIF_RAFIF_MASK) /**< CAN RX buffer almost full event */
51 #define CAN_EVENT_TX_PRIMARY_BUF (CAN_RTIF_TPIF_MASK) /**< CAN TX primary buffer event */
52 #define CAN_EVENT_TX_SECONDARY_BUF (CAN_RTIF_TSIF_MASK) /**< CAN TX secondary buffer event */
53 #define CAN_EVENT_ERROR (CAN_RTIF_EIF_MASK) /**< CAN error event */
54 #define CAN_EVENT_ABORT (CAN_RTIF_AIF_MASK) /**< CAN abort event */
55
56 /**
57 * @brief CAN Secondary Transmit buffer Status
58 */
59 #define CAN_STB_IS_EMPTY (0U) /**< CAN Sencondary Transmit buffer is empty */
60 #define CAN_STB_LESS_EQUAL_HALF_FULL (1U) /**< CAN Sencondary Transmit buffer <= 1/2 * FULL */
61 #define CAN_STB_MORE_THAN_HALF_FULL (2U) /**< CAN Sencondary Transmit buffer > 1/2 * FULL */
62 #define CAN_STB_IS_FULL (3U) /**< CAN Sencondary Transmit buffer is full */
63
64 /**
65 * @brief CAN Receive Buffer States
66 */
67 #define CAN_RXBUF_IS_EMPTY (0U) /**< CAN Receive buffer is empty */
68 #define CAN_RXBUF_HAS_DATA (1U) /**< CAN Receive buffer has data */
69 #define CAN_RXBUF_ALMOST_FULL (2U) /**< CAN Receive buffer is almost full */
70 #define CAN_RXBUF_IS_FULL (3U) /**< CAN Receive buffer is full */
71
72 /**
73 * @brief CAN Error interrupts/flags
74 *
75 */
76 #define CAN_ERROR_WARNING_LIMIT_FLAG (CAN_ERRINT_EWARN_MASK) /**< CAN Error Limit reached */
77 #define CAN_ERROR_PASSIVE_MODE_ACTIVE_FLAG (CAN_ERRINT_EPASS_MASK) /**< CAN Passive mode active */
78 #define CAN_ERROR_PASSIVE_INT_ENABLE (CAN_ERRINT_EPIE_MASK) /**< CAN Passive Interrupt Enable */
79 #define CAN_ERROR_PASSIVE_INT_FLAG (CAN_ERRINT_EPIF_MASK) /**< CAN Passive Interrupt Flag */
80 #define CAN_ERROR_ARBITRAITION_LOST_INT_ENABLE (CAN_ERRINT_ALIE_MASK) /**< CAN Abitration Lost Interrupt Enable */
81 #define CAN_ERROR_ARBITRAITION_LOST_INT_FLAG (CAN_ERRINT_ALIE_MASK) /**< CAN arbitration Lost Interrupt Flag */
82 #define CAN_ERROR_BUS_ERROR_INT_ENABLE (CAN_ERRINT_BEIE_MASK) /**< CAN BUS error Interrupt Enable */
83 #define CAN_ERROR_BUS_ERROR_INT_FLAG (CAN_ERRINT_BEIF_MASK) /**< CAN BUS error Interrupt flag */
84
85 /**
86 * @brief CAN Error Kinds
87 *
88 */
89 #define CAN_KIND_OF_ERROR_NO_ERROR (0U) /**< No error */
90 #define CAN_KIND_OF_ERROR_BIT_ERROR (1U) /**< Bit error */
91 #define CAN_KIND_OF_ERROR_FORM_ERROR (2U) /**< Form error */
92 #define CAN_KIND_OF_ERROR_STUFF_ERROR (3U) /**< Stuff error */
93 #define CAN_KIND_OF_ERROR_ACK_ERROR (4U) /**< Acknowledgment error */
94 #define CAN_KIND_OF_ERROR_CRC_ERROR (5U) /**< CRC error */
95 #define CAN_KIND_OF_ERROR_OTHER_ERROR (6U) /**< Other errors */
96 #define CAN_KIND_OF_ERROR_BUS_OFF (7U) /**< BUS off error */
97
98 /**
99 * @brief CAN loopback types
100 */
101 typedef enum _can_mode {
102 can_mode_normal, /**< Non-loopback mode */
103 can_mode_loopback_internal, /**< Internal loopback mode */
104 can_mode_loopback_external, /**< External loopback mode */
105 can_mode_listen_only, /**< CAN listen mode */
106 } can_node_mode_t;
107
108 /**
109 * @brief CAN bit timing options
110 */
111 typedef enum _can_bit_timing_option {
112 can_bit_timing_can2_0, /**< CAN 2.0 bit timing option */
113 can_bit_timing_canfd_norminal, /**< CANFD norminal timing option */
114 can_bit_timing_canfd_data, /**< CANFD data timing option */
115 } can_bit_timing_option_t;
116
117 /**
118 * @brief CAN DLC definitions
119 */
120 enum {
121 can_payload_size_0 = 0, /**< Payload size is 0 */
122 can_payload_size_1, /**< Payload size is 1 */
123 can_payload_size_2, /**< Payload size is 2 */
124 can_payload_size_3, /**< Payload size is 3 */
125 can_payload_size_4, /**< Payload size is 4 */
126 can_payload_size_5, /**< Payload size is 5 */
127 can_payload_size_6, /**< Payload size is 6 */
128 can_payload_size_7, /**< Payload size is 7 */
129 can_payload_size_8, /**< Payload size is 8 */
130 can_payload_size_12, /**< Payload size is 12 */
131 can_payload_size_16, /**< Payload size is 16 */
132 can_payload_size_20, /**< Payload size is 20 */
133 can_payload_size_24, /**< Payload size is 24 */
134 can_payload_size_32, /**< Payload size is 32 */
135 can_payload_size_48, /**< Payload size is 48 */
136 can_payload_size_64, /**< Payload size is 64 */
137 can_payload_size_max = can_payload_size_64,
138 };
139
140 /**
141 * @brief CAN Bit timing parameters
142 */
143 typedef struct {
144 uint16_t prescaler; /**< Prescaler value */
145 uint16_t num_seg1; /**< Seg1 value */
146 uint16_t num_seg2; /**< Seg2 value */
147 uint16_t num_sjw; /**< SJW value */
148 } can_bit_timing_param_t;
149
150 /**
151 * @brief CAN receive buffer data structure
152 */
153 typedef union _can_rx_buf {
154 uint32_t buffer[20]; /**< CAN buffer size */
155 struct {
156 struct {
157 uint32_t id: 29; /**< CAN ID */
158 uint32_t : 1;
159 uint32_t error_state_indicator: 1; /**< Error state indicator */
160 };
161 struct {
162 uint32_t dlc: 4; /**< Data length option */
163 uint32_t bitrate_switch: 1; /**< bitrate switch flag */
164 uint32_t canfd_frame: 1; /**< CANFD frame flag */
165 uint32_t remote_frame: 1; /**< Remote frame flag */
166 uint32_t extend_id: 1; /**< Extended ID flag */
167 uint32_t : 4;
168 uint32_t loopback_message: 1; /**< Loopback message flag */
169 uint32_t error_type: 3; /**< Error type */
170 uint32_t cycle_time: 16; /**< Cycle time */
171 };
172 uint8_t data[]; /**< Data pointer */
173 };
174 } can_receive_buf_t;
175
176 /**
177 * @brief CAN transmit buffer data structure
178 */
179 typedef union _can_tx_buf {
180 uint32_t buffer[18]; /**< CAN transmit buffer */
181 struct {
182 struct {
183 uint32_t id: 29; /**< CAN ID */
184 uint32_t : 2;
185 uint32_t transmit_timestamp_enable: 1; /**< Timestamp enable flag */
186 };
187 struct {
188 uint32_t dlc: 4; /**< Data length option */
189 uint32_t bitrate_switch: 1; /**< bitrate switch flag */
190 uint32_t canfd_frame: 1; /**< CANFD frame flag */
191 uint32_t remote_frame: 1; /**< remote_frame flag */
192 uint32_t extend_id: 1; /**< Extended ID flag */
193 uint32_t : 24;
194 };
195 uint8_t data[]; /**< Data pointer */
196 };
197 } can_transmit_buf_t;
198
199 /**
200 * @brief CAN acceptance filter modes
201 */
202 typedef enum _can_filter_id_mode {
203 can_filter_id_mode_both_frames, /**< Accept both standard frame and extended frame */
204 can_filter_id_mode_standard_frames, /**< Accept standard frame only */
205 can_filter_id_mode_extended_frames, /**< Accept extended frame only */
206 } can_filter_id_mode_t;
207
208 /**
209 * @brief CAN acceptance filter configuration
210 */
211 typedef struct {
212 uint16_t index; /**< CAN filter index */
213 can_filter_id_mode_t id_mode; /**< CAN filter id mode */
214 bool enable; /**< CAN filter enable flag */
215 uint32_t code; /**< CAN filter code */
216 uint32_t mask; /**< CAN filter mask */
217 } can_filter_config_t;
218
219 /**
220 * @brief CAN configuration
221 */
222 typedef struct {
223 union {
224 struct {
225 uint32_t baudrate; /**< CAN2.0 baudrate / CANFD nominal baudrate */
226 uint32_t baudrate_fd; /**< CANFD data baudrate */
227 /**< minimum sampling point, value range (0-1000), samplepoint_min/1000 will be used in driver */
228 uint16_t can20_samplepoint_min;
229 /**< maximum sampling point, value range (0-1000), samplepoint_max/1000 will be used in driver */
230 uint16_t can20_samplepoint_max;
231 /**< minimum sampling point, value range (0-1000), samplepoint_min/1000 will be used in driver */
232 uint16_t canfd_samplepoint_min;
233 /**< maximum sampling point, value range (0-1000), samplepoint_max/1000 will be used in driver */
234 uint16_t canfd_samplepoint_max;
235 };
236 struct {
237 can_bit_timing_param_t can_timing; /**< CAN2.0 /CANFD nominal low-level bit timing parameters */
238 can_bit_timing_param_t canfd_timing;/**< CANFD low-level bit timing parameters */
239 };
240 };
241
242 can_node_mode_t mode; /**< CAN work mode */
243 bool use_lowlevel_timing_setting; /**< Use low-level timing setting */
244 bool enable_canfd; /**< Enable CAN FD */
245 bool enable_self_ack; /**< CAN self-ack flag */
246 bool disable_re_transmission_for_ptb; /**< disable re-transmission for primary transmit buffer */
247 bool disable_re_transmission_for_stb; /**< disable re-transmission for secondary transmit buffer */
248 bool enable_tdc; /**< Enable transmittor delay compensation */
249
250 uint8_t filter_list_num; /**< element number of CAN filters in filter list */
251 can_filter_config_t *filter_list; /**< CAN filter list pointer */
252
253 uint8_t irq_txrx_enable_mask; /**< CAN TX and RX IRQ Enable Mask */
254 uint8_t irq_error_enable_mask; /**< CAN Error IRQ Enable Mask */
255 bool enable_tx_buffer_priority_mode; /**< Enable Priority-based priority */
256 bool enable_can_fd_iso_mode; /**< Enable CAN-FD ISO mode */
257 } can_config_t;
258
259
260 #ifdef __cplusplus
261 extern "C" {
262 #endif
263
264
265 /**
266 * @brief Reset CAN controller
267 *
268 * @param [in] base CAN base address
269 * @param [in] enable reset flag for CAN controller
270 * @arg true reset the CAN controller
271 * @arg false clear the CAN controller reset flag
272 */
can_reset(CAN_Type * base,bool enable)273 static inline void can_reset(CAN_Type *base, bool enable)
274 {
275 if (enable) {
276 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_RESET_MASK;
277 } else {
278 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_RESET_MASK;
279 }
280 }
281
282 /**
283 * @brief Set CAN mode
284 *
285 * @param [in] base CAN base address
286 * @param [in] mode CAN loopback mode
287 * @arg can_mode_normal Normal work mode
288 * @arg can_mode_loopback_internal internal loopback mode
289 * @arg can_mode_loopback_external external loopback mode
290 * @arg can_mode_listen_only CAN listen-only mode
291 */
can_set_node_mode(CAN_Type * base,can_node_mode_t mode)292 static inline void can_set_node_mode(CAN_Type *base, can_node_mode_t mode)
293 {
294 uint32_t cfg_stat = base->CMD_STA_CMD_CTRL & ~(CAN_CMD_STA_CMD_CTRL_LBME_MASK | CAN_CMD_STA_CMD_CTRL_LBMI_MASK | CAN_CMD_STA_CMD_CTRL_LOM_MASK);
295 if (mode == can_mode_loopback_internal) {
296 cfg_stat |= CAN_CMD_STA_CMD_CTRL_LBMI_MASK;
297 } else if (mode == can_mode_loopback_external) {
298 cfg_stat |= CAN_CMD_STA_CMD_CTRL_LBME_MASK;
299 } else if (mode == can_mode_listen_only) {
300 cfg_stat |= CAN_CMD_STA_CMD_CTRL_LOM_MASK;
301 } else {
302 /* CAN normal work mode, no change needed here */
303 }
304 base->CMD_STA_CMD_CTRL = cfg_stat;
305 }
306
307 /**
308 * @brief Enable CAN listen-only mode
309 * @param [in] base CAN base address
310 * @param [in] enable CAN listen-only mode enable flag
311 * @arg true enable listen-only mode
312 * @arg false disable listen-only mode
313 */
can_enable_listen_only_mode(CAN_Type * base,bool enable)314 static inline void can_enable_listen_only_mode(CAN_Type *base, bool enable)
315 {
316 if (enable) {
317 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_LOM_MASK;
318 } else {
319 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_LOM_MASK;
320 }
321 }
322
323 /**
324 * @brief Enter CAN standby mode
325 * @param [in] base CAN base address
326 * @param [in] enable Can standby mode enable flag
327 * @arg true enable standby mode
328 * @arg false disable standby mode
329 */
can_enter_standby_mode(CAN_Type * base,bool enable)330 static inline void can_enter_standby_mode(CAN_Type *base, bool enable)
331 {
332 if (enable) {
333 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_STBY_MASK;
334 } else {
335 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_STBY_MASK;
336 }
337 }
338
339 /**
340 * @brief Select CAN TX buffer
341 * @param [in] base CAN base address
342 * @param [in] select_secondary_buffer CAN secondary transmit buffer selection flag
343 * @arg true Select the secondary transmit buffer
344 * @arg false Select the primary transmit buffer
345 */
can_select_tx_buffer(CAN_Type * base,bool select_secondary_buffer)346 static inline void can_select_tx_buffer(CAN_Type *base, bool select_secondary_buffer)
347 {
348 if (select_secondary_buffer) {
349 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
350 } else {
351 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TBSEL_MASK;
352 }
353 }
354
355 /**
356 * @brief Start CAN high priority message transmit
357 * @param [in] base CAN base address
358 *
359 */
can_start_high_priority_message_transmit(CAN_Type * base)360 static inline void can_start_high_priority_message_transmit(CAN_Type *base)
361 {
362 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPE_MASK;
363 }
364
365 /**
366 * @brief Abort CAN high priority message transmit
367 * @param [in] base CAN base address
368 */
can_abort_high_priority_message_transmit(CAN_Type * base)369 static inline void can_abort_high_priority_message_transmit(CAN_Type *base)
370 {
371 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPA_MASK;
372 }
373
374 /**
375 * @brief Start CAN message transmit
376 * @param [in] base CAN base address
377 */
can_start_message_transmit(CAN_Type * base)378 static inline void can_start_message_transmit(CAN_Type *base)
379 {
380 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSONE_MASK;
381 }
382
383 /**
384 * @brief Start CAN all messages transmit
385 * @param [in] base CAN base address
386 */
can_start_all_message_transmit(CAN_Type * base)387 static inline void can_start_all_message_transmit(CAN_Type *base)
388 {
389 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSALL_MASK;
390 }
391
392 /**
393 * @brief Abort CAN message transmit
394 * @param [in] base CAN base address
395 */
can_abort_message_transmit(CAN_Type * base)396 static inline void can_abort_message_transmit(CAN_Type *base)
397 {
398 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSA_MASK;
399 }
400
401 /**
402 * @brief Switch to next CAN tx buffer
403 * @param [in] base CAN base address
404 */
can_switch_to_next_tx_buffer(CAN_Type * base)405 static inline void can_switch_to_next_tx_buffer(CAN_Type *base)
406 {
407 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSNEXT_MASK;
408 }
409
410 /**
411 * @brief Select CAN tx buffer priority mode
412 * @param [in] base CAN base address
413 * @param [in] enable_priority_decision CAN tx buffer priority mode selection flag
414 * @arg true priority decision mode
415 * @arg false FIFO mode
416 */
can_select_tx_buffer_priority_mode(CAN_Type * base,bool enable_priority_decision)417 static inline void can_select_tx_buffer_priority_mode(CAN_Type *base, bool enable_priority_decision)
418 {
419 if (enable_priority_decision) {
420 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSMODE_MASK;
421 } else {
422 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TSMODE_MASK;
423 }
424 }
425
426 /**
427 * @brief Get CAN secondary transmit buffer status
428 * @param [in] base CAN base address
429 * @retval secondary transmit buffer status, 0: empty, 1: <= 1/2 full, 2: > 1/2 full, 3: full
430 *
431 */
can_get_secondary_transmit_buffer_status(CAN_Type * base)432 static inline uint8_t can_get_secondary_transmit_buffer_status(CAN_Type *base)
433 {
434 return CAN_CMD_STA_CMD_CTRL_TSSTAT_GET(base->CMD_STA_CMD_CTRL);
435 }
436
437 /**
438 * @brief Check whether the primary transmit buffer is full
439 * @param [in] base CAN base address
440 * @return true for full
441 */
can_is_primary_transmit_buffer_full(CAN_Type * base)442 static inline bool can_is_primary_transmit_buffer_full(CAN_Type *base)
443 {
444 return ((base->CMD_STA_CMD_CTRL & CAN_CMD_STA_CMD_CTRL_TPE_MASK) != 0U);
445 }
446
447 /**
448 * @brief Check whether the secondary transmit buffer is full
449 * @param [in] base CAN base address
450 * @return true for full
451 */
can_is_secondary_transmit_buffer_full(CAN_Type * base)452 static inline bool can_is_secondary_transmit_buffer_full(CAN_Type *base)
453 {
454 return (CAN_CMD_STA_CMD_CTRL_TSSTAT_GET(base->CMD_STA_CMD_CTRL) == CAN_STB_IS_FULL);
455 }
456
457 /**
458 * @brief Check whether the CAN is in BUS off mode
459 *
460 * @param [in] base CAN base address
461 * @return true for bus off mode
462 * @return false for non-bus off mode
463 */
can_is_in_bus_off_mode(CAN_Type * base)464 static inline bool can_is_in_bus_off_mode(CAN_Type *base)
465 {
466 return ((base->CMD_STA_CMD_CTRL & CAN_CMD_STA_CMD_CTRL_BUSOFF_MASK) != 0U);
467 }
468
469 /**
470 * @brief Enable can self ack
471 * @param [in] base CAN base address
472 * @param [in] enable Self-ack enable flag, true or false
473 *
474 */
can_enable_self_ack(CAN_Type * base,bool enable)475 static inline void can_enable_self_ack(CAN_Type *base, bool enable)
476 {
477 if (enable) {
478 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_SACK_MASK;
479 } else {
480 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_SACK_MASK;
481 }
482 }
483
484 /**
485 * @brief Set CAN receive buffer overflow mode
486 * @param [in] base CAN base address
487 * @param [in] override_enable receive buffer overflow mode option
488 * @arg true the oldest message will be overwritten
489 * @arg false the new message will not be stored
490 */
can_set_receive_buffer_overflow_mode(CAN_Type * base,bool override_enable)491 static inline void can_set_receive_buffer_overflow_mode(CAN_Type *base, bool override_enable)
492 {
493 if (override_enable) {
494 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_ROM_MASK;
495 } else {
496 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_ROM_MASK;
497 }
498 }
499
500 /**
501 * @brief Check whether CAN receive buffer is overflow
502 * @param [in] base CAN base address
503 * @retval true or false
504 */
can_is_receive_buffer_overflow(CAN_Type * base)505 static inline bool can_is_receive_buffer_overflow(CAN_Type *base)
506 {
507 return IS_HPM_BITMASK_SET(base->CMD_STA_CMD_CTRL, CAN_CMD_STA_CMD_CTRL_ROV_MASK);
508 }
509
510 /**
511 * @brief Release CAN receive buffer
512 *
513 * @param [in] base CAN base address
514 */
can_release_receive_buffer(CAN_Type * base)515 static inline void can_release_receive_buffer(CAN_Type *base)
516 {
517 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_RREL_MASK;
518 }
519
520 /**
521 * @brief Allow can store all date in receive buffer
522 * @param [in] base CAN base address
523 * @param [in] allow flag to determine whether to store error data frame
524 */
can_allow_store_all_data_in_receive_buffer(CAN_Type * base,bool allow)525 static inline void can_allow_store_all_data_in_receive_buffer(CAN_Type *base, bool allow)
526 {
527 if (allow) {
528 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_RBALL_MASK;
529 } else {
530 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_RBALL_MASK;
531 }
532 }
533
534 /**
535 * @brief Get CAN receive buffer status
536 * @param [in] base CAN base address
537 * @retval Receive buffer status, 0: empty, 1: > empty, < almost full, 2: >= almost full, 3: full
538 */
can_get_receive_buffer_status(CAN_Type * base)539 static inline uint8_t can_get_receive_buffer_status(CAN_Type *base)
540 {
541 return CAN_CMD_STA_CMD_CTRL_RSTAT_GET(base->CMD_STA_CMD_CTRL);
542 }
543
544 /**
545 * @brief Check whether there are data available in receive buffer
546 * @param [in] base CAN base address
547 * @return true if the receive buffer is not empty
548 */
can_is_data_available_in_receive_buffer(CAN_Type * base)549 static inline bool can_is_data_available_in_receive_buffer(CAN_Type *base)
550 {
551 return (CAN_CMD_STA_CMD_CTRL_RSTAT_GET(base->CMD_STA_CMD_CTRL) != CAN_RXBUF_IS_EMPTY);
552 }
553
554
555 /**
556 * @brief Enable CAN FD ISO mode
557 * @param [in] base CAN base address
558 * @param enable CAN-FD ISO mode enable flag
559 */
can_enable_can_fd_iso_mode(CAN_Type * base,bool enable)560 static inline void can_enable_can_fd_iso_mode(CAN_Type *base, bool enable)
561 {
562 if (enable) {
563 base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_FD_ISO_MASK;
564 } else {
565 base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_FD_ISO_MASK;
566 }
567 }
568
569 /**
570 * @brief Enable CAN TX/RX interrupt
571 * @param [in] base CAN base address
572 * @param [in] mask CAN interrupt mask
573 */
can_enable_tx_rx_irq(CAN_Type * base,uint8_t mask)574 static inline void can_enable_tx_rx_irq(CAN_Type *base, uint8_t mask)
575 {
576 base->RTIE |= mask;
577 }
578
579 /**
580 * @brief Disable CAN TX/RX interrupt
581 * @param [in] base CAN base address
582 * @param [in] mask CAN interrupt mask
583 */
can_disable_tx_rx_irq(CAN_Type * base,uint8_t mask)584 static inline void can_disable_tx_rx_irq(CAN_Type *base, uint8_t mask)
585 {
586 base->RTIE &= ~mask;
587 }
588
589 /**
590 * @brief Clear CAN TX/RX flags
591 * @param [in] base CAN base address
592 * @param [in] flags CAN TX/RX interrupt flags
593 */
can_clear_tx_rx_flags(CAN_Type * base,uint8_t flags)594 static inline void can_clear_tx_rx_flags(CAN_Type *base, uint8_t flags)
595 {
596 base->RTIF = flags;
597 }
598
599 /**
600 * @brief Get CAN TX/RX flags
601 *
602 * @param [in] base CAN base address
603 * @retval CAN Tx/RX interrupt flags
604 */
can_get_tx_rx_flags(CAN_Type * base)605 static inline uint8_t can_get_tx_rx_flags(CAN_Type *base)
606 {
607 return base->RTIF;
608 }
609
610 /**
611 * @brief Enable CAN error interrupt
612 * @param [in] base CAN base address
613 * @param [in] mask CAN error interrupt mask
614 */
can_enable_error_irq(CAN_Type * base,uint8_t mask)615 static inline void can_enable_error_irq(CAN_Type *base, uint8_t mask)
616 {
617 base->ERRINT |= mask;
618 }
619
620 /**
621 * @brief Disable CAN error interrupt
622 *
623 * @param [in] base CAN base address
624 * @param [in] mask CAN error interrupt mask
625 */
can_disable_error_irq(CAN_Type * base,uint8_t mask)626 static inline void can_disable_error_irq(CAN_Type *base, uint8_t mask)
627 {
628 base->ERRINT &= ~mask;
629 }
630
631 /**
632 * @brief Get CAN error interrupt flags
633 * @param [in] base CAN base address
634 * @retval CAN error interrupt flags
635 */
can_get_error_interrupt_flags(CAN_Type * base)636 static inline uint8_t can_get_error_interrupt_flags(CAN_Type *base)
637 {
638 return (base->ERRINT & (uint8_t) ~(CAN_ERRINT_EPIE_MASK | CAN_ERRINT_ALIE_MASK | CAN_ERRINT_BEIE_MASK));
639 }
640
641 /**
642 * @brief Get CAN clear interrupt flags
643 * @param [in] base CAN base address
644 * @param [in] flags CAN error interrupt flags
645 */
can_clear_error_interrupt_flags(CAN_Type * base,uint8_t flags)646 static inline void can_clear_error_interrupt_flags(CAN_Type *base, uint8_t flags)
647 {
648 flags &= (uint8_t)~(CAN_ERRINT_EPIE_MASK | CAN_ERRINT_ALIE_MASK | CAN_ERRINT_BEIE_MASK);
649 base->ERRINT |= flags;
650 }
651
652 /**
653 * @brief Get last CAN error kind
654 * @param [in] base CAN base address
655 * @retval CAN last error kind
656 */
can_get_last_error_kind(CAN_Type * base)657 static inline uint8_t can_get_last_error_kind(CAN_Type *base)
658 {
659 return CAN_EALCAP_KOER_GET(base->EALCAP);
660 }
661
662 /**
663 * @brief Get CAN last arbitrary lost position
664 * @param [in] base CAN base address
665 * @retval CAN last arbitrary lost position
666 */
can_get_last_arbitration_lost_position(CAN_Type * base)667 static inline uint8_t can_get_last_arbitration_lost_position(CAN_Type *base)
668 {
669 return CAN_EALCAP_ALC_GET(base->EALCAP);
670 }
671
672 /**
673 * @brief Set CAN transmitter delay compensation
674 *
675 * @param [in] base CAN base address
676 * @param [in] sample_point delay compensation sample point
677 * @param [in] enable delay compensation enable flag
678 */
can_set_transmitter_delay_compensation(CAN_Type * base,uint8_t sample_point,bool enable)679 static inline void can_set_transmitter_delay_compensation(CAN_Type *base, uint8_t sample_point, bool enable)
680 {
681 #if defined(CAN_SOC_CANFD_TDC_REQUIRE_STUFF_EXCEPTION_WORKAROUND) && (CAN_SOC_CANFD_TDC_REQUIRE_STUFF_EXCEPTION_WORKAROUND == 1)
682 (void) sample_point;
683 (void) enable;
684 base->TDC = CAN_TDC_TDCEN_SET((uint8_t) enable);
685 #else
686 base->TDC = CAN_TDC_SSPOFF_SET(sample_point) | CAN_TDC_TDCEN_SET((uint8_t) enable);
687 #endif
688 }
689
690 /**
691 * @brief Set CAN warning limits
692 * @param [in] base CAN base address
693 * @param [in] almost_full_limit
694 * @param [in] error_warning_limit
695 */
can_set_warning_limits(CAN_Type * base,uint8_t almost_full_limit,uint8_t error_warning_limit)696 static inline void can_set_warning_limits(CAN_Type *base, uint8_t almost_full_limit, uint8_t error_warning_limit)
697 {
698 base->LIMIT = CAN_LIMIT_AFWL_SET(almost_full_limit) | CAN_LIMIT_EWL_SET(error_warning_limit);
699 }
700
701 /**
702 * @brief Get CAN receive error count
703 * @param [in] base CAN base address
704 * @retval CAN receive error count
705 */
can_get_receive_error_count(CAN_Type * base)706 static inline uint8_t can_get_receive_error_count(CAN_Type *base)
707 {
708 return base->RECNT;
709 }
710
711 /**
712 * @brief Get CAN transmit error count
713 * @param [in] base CAN base address
714 * @retval CAN transmit error count
715 */
can_get_transmit_error_count(CAN_Type * base)716 static inline uint8_t can_get_transmit_error_count(CAN_Type *base)
717 {
718 return base->TECNT;
719 }
720
721 /**
722 * @brief Enable a specified CAN filter
723 *
724 * @param [in] base CAN base address
725 * @param index CAN filter index
726 */
can_enable_filter(CAN_Type * base,uint32_t index)727 static inline void can_enable_filter(CAN_Type *base, uint32_t index)
728 {
729 base->ACF_EN |= (uint16_t) (1U << index);
730 }
731
732 /**
733 * @brief Disable a specified CAN filter
734 *
735 * @param [in] base CAN base address
736 * @param index CAN filter index
737 */
can_disable_filter(CAN_Type * base,uint32_t index)738 static inline void can_disable_filter(CAN_Type *base, uint32_t index)
739 {
740 base->ACF_EN &= (uint16_t) ~(1U << index);
741 }
742
743 /**
744 * @brief Get default CAN configuration parameters
745 * @param [out] config CAN configuration structure
746 * @retval API execution status, status_success or status_invalid_argument
747 */
748 hpm_stat_t can_get_default_config(can_config_t *config);
749
750 /**
751 * @brief Initialize the CAN controller
752 * @param [in] base CAN base address
753 * @param [in] config CAN configuration
754 * @param [in] src_clk_freq CAN IP source clock frequency
755 * @retval API execution status, status_success or status_invalid_argument
756 */
757 hpm_stat_t can_init(CAN_Type *base, can_config_t *config, uint32_t src_clk_freq);
758
759
760 /**
761 * @brief De-initialize the CAN controller
762 *
763 * @param [in] base CAN base address
764 */
765 void can_deinit(CAN_Type *base);
766
767
768 /**
769 * @brief Configure the Slow Speed Bit timing using low-level interface
770 * @param [in] base CAN base address
771 * @param [in] param CAN bit timing parameter
772 */
can_set_slow_speed_timing(CAN_Type * base,const can_bit_timing_param_t * param)773 static inline void can_set_slow_speed_timing(CAN_Type *base, const can_bit_timing_param_t *param)
774 {
775 base->S_PRESC = CAN_S_PRESC_S_PRESC_SET(param->prescaler - 1U) | CAN_S_PRESC_S_SEG_1_SET(param->num_seg1 - 2U) |
776 CAN_S_PRESC_S_SEG_2_SET(param->num_seg2 - 1U) | CAN_S_PRESC_S_SJW_SET(param->num_sjw - 1U);
777 }
778
779 /**
780 * @brief Configure the Fast Speed Bit timing using low-level interface
781 * @param [in] base CAN base address
782 * @param [in] param CAN bit timing parameter
783 */
can_set_fast_speed_timing(CAN_Type * base,const can_bit_timing_param_t * param)784 static inline void can_set_fast_speed_timing(CAN_Type *base, const can_bit_timing_param_t *param)
785 {
786 base->F_PRESC = CAN_F_PRESC_F_PRESC_SET(param->prescaler - 1U) | CAN_F_PRESC_F_SEG_1_SET(param->num_seg1 - 2U) |
787 CAN_F_PRESC_F_SEG_2_SET(param->num_seg2 - 1U) | CAN_F_PRESC_F_SJW_SET(param->num_sjw - 1U);
788 }
789
790 /**
791 * @brief Configure the CAN bit timing for CAN BUS
792 * @param [in] base CAN base address
793 * @param [in] option CAN bit timing option
794 * @param [in] src_clk_freq CAN IP source clock frequency
795 * @param [in] baudrate CAN baudrate in MHz
796 * @param [in] samplepoint_min Minimum Sample point, range(0-1000), samplepoint_min / 1000 will be used in calculation
797 * @param [in] samplepoint_max Maximum Sample point, range(0-1000), samplepoint_max / 1000 will be used in calculation
798 * @retval API execution status, status_success or status_invalid_argument
799 */
800 hpm_stat_t can_set_bit_timing(CAN_Type *base, can_bit_timing_option_t option,
801 uint32_t src_clk_freq, uint32_t baudrate,
802 uint16_t samplepoint_min, uint16_t samplepoint_max);
803
804
805 /**
806 * @brief Calculate the CAN bit timing for CAN BUS
807 * @param [in] src_clk_freq CAN IP source clock frequency
808 * @param [in] option CAN bit timing option
809 * @param [in] baudrate CAN baudrate in MHz
810 * @param [in] samplepoint_min Minimum Sample point, range(0-1000), samplepoint_min / 1000 will be used in calculation
811 * @param [in] samplepoint_max Maximum Sample point, range(0-1000), samplepoint_max / 1000 will be used in calculation
812 * @param [out] timing_param Calculated CAN bit timing parameter
813 * @retval API execution status, status_success or status_invalid_argument
814 */
815 hpm_stat_t can_calculate_bit_timing(uint32_t src_clk_freq, can_bit_timing_option_t option, uint32_t baudrate,
816 uint16_t samplepoint_min, uint16_t samplepoint_max,
817 can_bit_timing_param_t *timing_param);
818
819
820
821 /**
822 * @brief Configure the acceptable filter
823 * @param [in] base CAN base address
824 * @param [in] config CAN filter configuration
825 * @retval API execution status, status_success or status_invalid_argument
826 */
827 hpm_stat_t can_set_filter(CAN_Type *base, const can_filter_config_t *config);
828
829 /**
830 * @brief Send CAN message using blocking transfer
831 * @param [in] base CAN base address
832 * @param [in] message CAN message to be sent out
833 * @retval API execution status, status_success or status_invalid_argument
834 */
835 hpm_stat_t can_send_message_blocking(CAN_Type *base, const can_transmit_buf_t *message);
836
837 /**
838 * @brief Send high-priority message using blocking transfer
839 * @param [in] base CAN base address
840 * @param [in] message CAN message to be sent out
841 * @retval API execution status, status_success or status_invalid_argument
842 */
843 hpm_stat_t can_send_high_priority_message_blocking(CAN_Type *base, const can_transmit_buf_t *message);
844
845
846 /**
847 * @brief Send CAN message using non-blocking transfer
848 * @param [in] base CAN base address
849 * @param [in] message CAN message to be sent out
850 * @retval API execution status, status_success or status_invalid_argument
851 */
852 hpm_stat_t can_send_message_nonblocking(CAN_Type *base, const can_transmit_buf_t *message);
853
854 /**
855 * @brief Send high-priority message using non-blocking transfer
856 * @param [in] base CAN base address
857 * @param [in] message CAN message to be sent out
858 * @retval API execution status, status_success or status_invalid_argument
859 */
860 hpm_stat_t can_send_high_priority_message_nonblocking(CAN_Type *base, const can_transmit_buf_t *message);
861
862 /**
863 * @brief Receive CAN message using blocking transfer
864 *
865 * @param [in] base CAN base address
866 * @param [out] message CAN message buffer
867 *
868 * @retval status_success API exection is successful
869 * @retval status_invalid_argument Invalid parameters
870 * @retval status_can_bit_error CAN bit error happened during receiving message
871 * @retval status_can_form_error CAN form error happened during receiving message
872 * @retval status_can_stuff_error CAN stuff error happened during receiving message
873 * @retval status_can_ack_error CAN ack error happened during receiving message
874 * @retval status_can_crc_error CAN crc error happened during receiving message
875 * @retval status_can_other_error Other error happened during receiving message
876 */
877 hpm_stat_t can_receive_message_blocking(CAN_Type *base, can_receive_buf_t *message);
878
879
880 /**
881 * @brief Read Received CAN message
882 *
883 * @note This API assumes that the received CAN message is available.
884 * It can be used in the interrupt handler
885 * @param [in] base CAN base address
886 * @param [out] message CAN message buffer
887 *
888 * @retval status_success API exection is successful
889 * @retval status_invalid_argument Invalid parameters
890 * @retval status_can_bit_error CAN bit error happened during receiving message
891 * @retval status_can_form_error CAN form error happened during receiving message
892 * @retval status_can_stuff_error CAN stuff error happened during receiving message
893 * @retval status_can_ack_error CAN ack error happened during receiving message
894 * @retval status_can_crc_error CAN crc error happened during receiving message
895 * @retval status_can_other_error Other error happened during receiving message
896 */
897 hpm_stat_t can_read_received_message(CAN_Type *base, can_receive_buf_t *message);
898
899 /**
900 * @}
901 *
902 */
903
904
905 #ifdef __cplusplus
906 }
907 #endif
908
909
910 #endif /* HPM_CAN_DRV_H */
911