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