• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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