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