hpm_can_drv.h 33 KB

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