dev_can.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2015-05-14 aubrcool@qq.com first version
  9. * 2015-07-06 Bernard remove RT_CAN_USING_LED.
  10. * 2022-05-08 hpmicro add CANFD support, fixed typos
  11. * 2025-09-20 wdfk_prog Added non-blocking send mechanism APIs and data structures.
  12. */
  13. #ifndef __DEV_CAN_H_
  14. #define __DEV_CAN_H_
  15. #include <rtthread.h>
  16. #include <rtdevice.h>
  17. #ifndef RT_CANMSG_BOX_SZ
  18. #define RT_CANMSG_BOX_SZ 16
  19. #endif
  20. #ifndef RT_CANSND_BOX_NUM
  21. #define RT_CANSND_BOX_NUM 1
  22. #endif
  23. #ifndef RT_CANSND_MSG_TIMEOUT
  24. #define RT_CANSND_MSG_TIMEOUT 100
  25. #endif
  26. enum CAN_DLC
  27. {
  28. CAN_MSG_0BYTE = 0,
  29. CAN_MSG_1BYTE,
  30. CAN_MSG_2BYTES,
  31. CAN_MSG_3BYTES,
  32. CAN_MSG_4BYTES,
  33. CAN_MSG_5BYTES,
  34. CAN_MSG_6BYTES,
  35. CAN_MSG_7BYTES,
  36. CAN_MSG_8BYTES,
  37. CAN_MSG_12BYTES,
  38. CAN_MSG_16BYTES,
  39. CAN_MSG_20BYTES,
  40. CAN_MSG_24BYTES,
  41. CAN_MSG_32BYTES,
  42. CAN_MSG_48BYTES,
  43. CAN_MSG_64BYTES,
  44. };
  45. enum CANBAUD
  46. {
  47. CAN1MBaud = 1000UL * 1000,/* 1 MBit/sec */
  48. CAN800kBaud = 1000UL * 800, /* 800 kBit/sec */
  49. CAN500kBaud = 1000UL * 500, /* 500 kBit/sec */
  50. CAN250kBaud = 1000UL * 250, /* 250 kBit/sec */
  51. CAN125kBaud = 1000UL * 125, /* 125 kBit/sec */
  52. CAN100kBaud = 1000UL * 100, /* 100 kBit/sec */
  53. CAN50kBaud = 1000UL * 50, /* 50 kBit/sec */
  54. CAN20kBaud = 1000UL * 20, /* 20 kBit/sec */
  55. CAN10kBaud = 1000UL * 10 /* 10 kBit/sec */
  56. };
  57. #define RT_CAN_MODE_NORMAL 0
  58. #define RT_CAN_MODE_LISTEN 1
  59. #define RT_CAN_MODE_LOOPBACK 2
  60. #define RT_CAN_MODE_LOOPBACKANLISTEN 3
  61. #define RT_CAN_MODE_PRIV 0x01
  62. #define RT_CAN_MODE_NOPRIV 0x00
  63. /**
  64. * @defgroup group_drivers_can CAN Driver
  65. * @brief CAN driver api
  66. * @ingroup group_device_driver
  67. *
  68. * <b>Example: Demonstrating CAN RX, Filters, and Blocking/Non-Blocking TX</b>
  69. * @code {.c}
  70. * #include <rtthread.h>
  71. * #include <rtdevice.h>
  72. *
  73. * #define CAN_DEV_NAME "can1" // The name of the CAN device
  74. *
  75. * static rt_device_t can_dev; // CAN device handle
  76. * static struct rt_semaphore rx_sem; // Semaphore for message reception
  77. *
  78. * // Callback function for CAN reception
  79. * static rt_err_t can_rx_callback(rt_device_t dev, rt_size_t size)
  80. * {
  81. * // The CAN interrupt calls this callback when data is received.
  82. * // Release the semaphore to notify the receiving thread.
  83. * rt_sem_release(&rx_sem);
  84. * return RT_EOK;
  85. * }
  86. *
  87. * static void can_rx_thread(void *parameter)
  88. * {
  89. * rt_err_t res;
  90. * struct rt_can_msg rx_msg = {0};
  91. *
  92. * // Set the receive callback function
  93. * rt_device_set_rx_indicate(can_dev, can_rx_callback);
  94. *
  95. * #ifdef RT_CAN_USING_HDR
  96. * // Example of configuring multiple hardware filters
  97. * struct rt_can_filter_item items[] =
  98. * {
  99. * // Filter 1: Match standard frames with IDs from 0x100 to 0x1FF. hdr_index will be -1.
  100. * RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL),
  101. * // Filter 2: Match standard frames with IDs from 0x300 to 0x3FF. hdr_index will be -1.
  102. * RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL),
  103. * // Filter 3: Exactly match standard frame with ID 0x211. hdr_index will be -1.
  104. * RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7FF, RT_NULL, RT_NULL),
  105. * // Filter 4: Exactly match standard frame with ID 0x486 using a helper macro. hdr_index will be -1.
  106. * RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL),
  107. * // Filter 5: Exactly match standard frame with ID 0x555 and explicitly assign it to filter bank #7.
  108. * // This uses direct struct initialization: {id, ide, rtr, mode, mask, hdr_bank}.
  109. * {0x555, 0, 0, 0, 0x7FF, 7}
  110. * };
  111. * // Create the filter configuration structure with 5 active filters.
  112. * struct rt_can_filter_config cfg = {sizeof(items)/sizeof(items[0]), 1, items};
  113. * // Set the hardware filters for the CAN device.
  114. * res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
  115. * RT_ASSERT(res == RT_EOK);
  116. * #endif
  117. *
  118. * // Some drivers might require an explicit start command.
  119. * // This is driver-specific.
  120. * rt_uint32_t cmd_arg = 1; // Argument to enable the controller
  121. * res = rt_device_control(can_dev, RT_CAN_CMD_START, &cmd_arg);
  122. * RT_ASSERT(res == RT_EOK);
  123. *
  124. * while (1)
  125. * {
  126. * // Block and wait for the semaphore, which is released by the receive callback.
  127. * rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
  128. *
  129. * // Read one frame of data from the CAN device's general message queue.
  130. * rx_msg.hdr_index = -1;
  131. * rt_device_read(can_dev, 0, &rx_msg, sizeof(rx_msg));
  132. *
  133. * // Print the received message's ID and data.
  134. * rt_kprintf("Received a message. ID: 0x%x, Data: ", rx_msg.id);
  135. * for (int i = 0; i < rx_msg.len; i++)
  136. * {
  137. * rt_kprintf("%02x ", rx_msg.data[i]);
  138. * }
  139. * rt_kprintf("\n");
  140. * }
  141. * }
  142. *
  143. * int can_sample(int argc, char *argv[])
  144. * {
  145. * rt_err_t res;
  146. * rt_thread_t thread;
  147. * char can_name[RT_NAME_MAX];
  148. *
  149. * // Allow specifying the CAN device name from the command line, e.g., "can_sample can2"
  150. * if (argc == 2)
  151. * {
  152. * rt_strncpy(can_name, argv[1], RT_NAME_MAX);
  153. * }
  154. * else
  155. * {
  156. * rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
  157. * }
  158. *
  159. * // Find the CAN device by name
  160. * can_dev = rt_device_find(can_name);
  161. * if (!can_dev)
  162. * {
  163. * rt_kprintf("find device %s failed!\n", can_name);
  164. * return -RT_ERROR;
  165. * }
  166. *
  167. * // Initialize the receive semaphore
  168. * rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
  169. *
  170. * // Open the CAN device in interrupt-driven TX/RX mode
  171. * res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
  172. * RT_ASSERT(res == RT_EOK);
  173. *
  174. * // Create and start the data receiving thread
  175. * thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10);
  176. * if (thread != RT_NULL)
  177. * {
  178. * rt_thread_startup(thread);
  179. * }
  180. * else
  181. * {
  182. * rt_kprintf("create can_rx thread failed!\n");
  183. * return -RT_ERROR;
  184. * }
  185. *
  186. * rt_kprintf("CAN device %s opened successfully.\n", can_name);
  187. *
  188. * // --- Demonstrate Blocking Send ---
  189. * struct rt_can_msg blocking_msg = {0};
  190. * blocking_msg.id = 0x78;
  191. * blocking_msg.ide = RT_CAN_STDID;
  192. * blocking_msg.rtr = RT_CAN_DTR;
  193. * blocking_msg.len = 8;
  194. * // The `nonblocking` flag is 0 by default for blocking mode.
  195. * for(int i = 0; i < 8; i++) blocking_msg.data[i] = i;
  196. *
  197. * rt_kprintf("Attempting to send a message in BLOCKING mode...\n");
  198. * if (rt_device_write(can_dev, 0, &blocking_msg, sizeof(blocking_msg)) == sizeof(blocking_msg))
  199. * {
  200. * rt_kprintf("Blocking message sent successfully.\n");
  201. * }
  202. * else
  203. * {
  204. * rt_kprintf("Blocking message send failed.\n");
  205. * }
  206. *
  207. * rt_thread_mdelay(100); // Wait a moment for clarity in the log
  208. *
  209. * // --- Demonstrate Non-Blocking Send ---
  210. * struct rt_can_msg nonblocking_msg = {0};
  211. * nonblocking_msg.id = 0x79;
  212. * nonblocking_msg.ide = RT_CAN_STDID;
  213. * nonblocking_msg.rtr = RT_CAN_DTR;
  214. * nonblocking_msg.len = 4;
  215. * nonblocking_msg.data[0] = 0xDE;
  216. * nonblocking_msg.data[1] = 0xAD;
  217. * nonblocking_msg.data[2] = 0xBE;
  218. * nonblocking_msg.data[3] = 0xEF;
  219. * nonblocking_msg.nonblocking = 1; // <-- Key: Set the non-blocking flag
  220. *
  221. * rt_kprintf("Attempting to send a message in NON-BLOCKING mode...\n");
  222. * if (rt_device_write(can_dev, 0, &nonblocking_msg, sizeof(nonblocking_msg)) == sizeof(nonblocking_msg))
  223. * {
  224. * rt_kprintf("Non-blocking message was accepted (sent or enqueued).\n");
  225. * }
  226. * else
  227. * {
  228. * rt_kprintf("Non-blocking send failed (buffer was full).\n");
  229. * }
  230. *
  231. * return res;
  232. * }
  233. * // Export the function to the MSH command line
  234. * MSH_CMD_EXPORT(can_sample, can device usage example);
  235. * @endcode
  236. */
  237. /*!
  238. * @addtogroup group_drivers_can
  239. * @{
  240. */
  241. #define CAN_RX_FIFO0 (0x00000000U) /*!< CAN receive FIFO 0 */
  242. #define CAN_RX_FIFO1 (0x00000001U) /*!< CAN receive FIFO 1 */
  243. /**
  244. * @brief CAN filter item structure
  245. */
  246. struct rt_can_filter_item
  247. {
  248. rt_uint32_t id : 29; /**< The CAN ID to be filtered. */
  249. rt_uint32_t ide : 1; /**< Identifier type. 0 for Standard ID, 1 for Extended ID. */
  250. rt_uint32_t rtr : 1; /**< Frame type. 0 for Data Frame, 1 for Remote Frame. */
  251. rt_uint32_t mode : 1; /**< Filter mode. 0 for Mask Mode, 1 for List Mode. */
  252. rt_uint32_t mask; /**< The filter mask. In Mask Mode, a '1' bit means the corresponding ID bit must match. */
  253. rt_int32_t hdr_bank; /**< The specific hardware filter bank index to use. A value of -1 allows the driver to auto-assign. */
  254. rt_uint32_t rxfifo; /**< The target RX FIFO for matched messages (CAN_RX_FIFO0 or CAN_RX_FIFO1). */
  255. #ifdef RT_CAN_USING_HDR
  256. /**
  257. * @brief Callback function for a specific filter.
  258. * @param[in] dev The CAN device that triggered the callback.
  259. * @param[in] args User-provided arguments.
  260. * @param[in] hdr The hardware filter index that matched the message.
  261. * @param[in] size The size of the received data in bytes.
  262. * @return The operation status.
  263. */
  264. rt_err_t (*ind)(rt_device_t dev, void *args , rt_int32_t hdr, rt_size_t size);
  265. void *args; /**< User arguments for the indication callback. */
  266. #endif /*RT_CAN_USING_HDR*/
  267. };
  268. #ifdef RT_CAN_USING_HDR
  269. /**
  270. * @def RT_CAN_FILTER_ITEM_INIT
  271. * @brief A helper macro to initialize a `rt_can_filter_item` structure for Mask Mode.
  272. *
  273. * @param[in] id The CAN ID for the filter.
  274. * @param[in] ide Identifier type (0 for Standard, 1 for Extended).
  275. * @param[in] rtr Frame type (0 for Data, 1 for Remote).
  276. * @param[in] mode Filter mode (0 for Mask, 1 for List).
  277. * @param[in] mask The mask to be applied.
  278. * @param[in] ind Optional callback function (can be RT_NULL).
  279. * @param[in] args Optional arguments for the callback (can be RT_NULL).
  280. */
  281. #define RT_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask,ind,args) \
  282. {(id), (ide), (rtr), (mode),(mask), -1, CAN_RX_FIFO0,(ind), (args)}
  283. #define RT_CAN_FILTER_STD_INIT(id,ind,args) \
  284. RT_CAN_FILTER_ITEM_INIT(id,0,0,0,0xFFFFFFFF,ind,args)
  285. #define RT_CAN_FILTER_EXT_INIT(id,ind,args) \
  286. RT_CAN_FILTER_ITEM_INIT(id,1,0,0,0xFFFFFFFF,ind,args)
  287. #define RT_CAN_STD_RMT_FILTER_INIT(id,ind,args) \
  288. RT_CAN_FILTER_ITEM_INIT(id,0,1,0,0xFFFFFFFF,ind,args)
  289. #define RT_CAN_EXT_RMT_FILTER_INIT(id,ind,args) \
  290. RT_CAN_FILTER_ITEM_INIT(id,1,1,0,0xFFFFFFFF,ind,args)
  291. #define RT_CAN_STD_RMT_DATA_FILTER_INIT(id,ind,args) \
  292. RT_CAN_FILTER_ITEM_INIT(id,0,0,1,0xFFFFFFFF,ind,args)
  293. #define RT_CAN_EXT_RMT_DATA_FILTER_INIT(id,ind,args) \
  294. RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF,ind,args)
  295. #else
  296. /**
  297. * @def RT_CAN_FILTER_ITEM_INIT
  298. * @brief A helper macro to initialize a `rt_can_filter_item` structure for Mask Mode.
  299. *
  300. * @param[in] id The CAN ID for the filter.
  301. * @param[in] ide Identifier type (0 for Standard, 1 for Extended).
  302. * @param[in] rtr Frame type (0 for Data, 1 for Remote).
  303. * @param[in] mode Filter mode (0 for Mask, 1 for List).
  304. * @param[in] mask The mask to be applied.
  305. */
  306. #define RT_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask) \
  307. {(id), (ide), (rtr), (mode), (mask), -1, CAN_RX_FIFO0 }
  308. #define RT_CAN_FILTER_STD_INIT(id) \
  309. RT_CAN_FILTER_ITEM_INIT(id,0,0,0,0xFFFFFFFF)
  310. #define RT_CAN_FILTER_EXT_INIT(id) \
  311. RT_CAN_FILTER_ITEM_INIT(id,1,0,0,0xFFFFFFFF)
  312. #define RT_CAN_STD_RMT_FILTER_INIT(id) \
  313. RT_CAN_FILTER_ITEM_INIT(id,0,1,0,0xFFFFFFFF)
  314. #define RT_CAN_EXT_RMT_FILTER_INIT(id) \
  315. RT_CAN_FILTER_ITEM_INIT(id,1,1,0,0xFFFFFFFF)
  316. #define RT_CAN_STD_RMT_DATA_FILTER_INIT(id) \
  317. RT_CAN_FILTER_ITEM_INIT(id,0,0,1,0xFFFFFFFF)
  318. #define RT_CAN_EXT_RMT_DATA_FILTER_INIT(id) \
  319. RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF)
  320. #endif
  321. /**
  322. * @brief CAN hardware filter configuration structure.
  323. * This structure is passed to the driver via `rt_device_control` with the `RT_CAN_CMD_SET_FILTER` command.
  324. */
  325. struct rt_can_filter_config
  326. {
  327. rt_uint32_t count; /**< The number of filter items in the `items` array. */
  328. rt_uint32_t actived; /**< A flag to activate (1) or deactivate (0) the filters. */
  329. struct rt_can_filter_item *items; /**< A pointer to an array of filter items. */
  330. };
  331. /**
  332. * @brief CAN bit-timing parameters structure.
  333. */
  334. struct rt_can_bit_timing
  335. {
  336. rt_uint16_t prescaler; /**< Baud rate prescaler. */
  337. rt_uint16_t num_seg1; /**< Bit Timing Segment 1, in terms of Time Quanta (Tq). */
  338. rt_uint16_t num_seg2; /**< Bit Timing Segment 2, in terms of Time Quanta (Tq). */
  339. rt_uint8_t num_sjw; /**< Synchronization Jump Width, in terms of Time Quanta (Tq). */
  340. rt_uint8_t num_sspoff; /**< Secondary Sample Point Offset, in terms of Time Quanta (Tq) for CAN-FD. */
  341. };
  342. /**
  343. * @brief CAN bit timing configuration list structure.
  344. * @note items[0] is for CAN 2.0 / CAN-FD Arbitration Phase.
  345. * items[1] is for CAN-FD Data Phase (if applicable).
  346. */
  347. struct rt_can_bit_timing_config
  348. {
  349. rt_uint32_t count; /**< The number of bit-timing configurations (typically 1 for CAN, 2 for CAN-FD). */
  350. struct rt_can_bit_timing *items; /**< A pointer to an array of bit-timing structures. */
  351. };
  352. /**
  353. * @brief CAN device configuration structure.
  354. */
  355. struct can_configure
  356. {
  357. rt_uint32_t baud_rate; /**< The baud rate for the arbitration phase (e.g., CAN500kBaud). */
  358. rt_uint32_t msgboxsz; /**< The size of the software receive buffer (in number of messages). */
  359. rt_uint32_t sndboxnumber; /**< The number of hardware mailboxes used for blocking send operations. */
  360. rt_uint32_t mode : 8; /**< The CAN operation mode (e.g., RT_CAN_MODE_NORMAL, RT_CAN_MODE_LOOPBACK). */
  361. rt_uint32_t privmode : 8; /**< Private mode flag. If set, the `priv` field of `rt_can_msg` specifies the hardware mailbox. */
  362. rt_uint32_t reserved : 16; /**< Reserved for future use. */
  363. rt_uint32_t ticks; /**< The period in OS ticks for the status-checking timer. */
  364. #ifdef RT_CAN_USING_HDR
  365. rt_uint32_t maxhdr; /**< The maximum number of hardware filters supported by the controller. */
  366. #endif
  367. #ifdef RT_CAN_USING_CANFD
  368. rt_uint32_t baud_rate_fd; /**< The baud rate for the CAN-FD data phase. */
  369. rt_uint32_t use_bit_timing: 8; /**< A flag to indicate that `can_timing` and `canfd_timing` should be used instead of `baud_rate`. */
  370. rt_uint32_t enable_canfd : 8; /**< A flag to enable CAN-FD functionality. */
  371. rt_uint32_t reserved1 : 16; /**< Reserved for future use. */
  372. /* The below fields take effect only if use_bit_timing is non-zero */
  373. struct rt_can_bit_timing can_timing; /**< Custom bit-timing for the arbitration phase. */
  374. struct rt_can_bit_timing canfd_timing; /**< Custom bit-timing for the data phase. */
  375. #endif
  376. };
  377. #define CANDEFAULTCONFIG \
  378. {\
  379. CAN1MBaud,\
  380. RT_CANMSG_BOX_SZ,\
  381. RT_CANSND_BOX_NUM,\
  382. RT_CAN_MODE_NORMAL,\
  383. };
  384. struct rt_can_ops;
  385. #define RT_CAN_CMD_SET_FILTER 0x13
  386. #define RT_CAN_CMD_SET_BAUD 0x14
  387. #define RT_CAN_CMD_SET_MODE 0x15
  388. #define RT_CAN_CMD_SET_PRIV 0x16
  389. #define RT_CAN_CMD_GET_STATUS 0x17
  390. #define RT_CAN_CMD_SET_STATUS_IND 0x18
  391. #define RT_CAN_CMD_SET_BUS_HOOK 0x19
  392. #define RT_CAN_CMD_SET_CANFD 0x1A
  393. #define RT_CAN_CMD_SET_BAUD_FD 0x1B
  394. #define RT_CAN_CMD_SET_BITTIMING 0x1C
  395. #define RT_CAN_CMD_START 0x1D
  396. #define RT_DEVICE_CAN_INT_ERR 0x1000
  397. enum RT_CAN_STATUS_MODE
  398. {
  399. NORMAL = 0,
  400. ERRWARNING = 1,
  401. ERRPASSIVE = 2,
  402. BUSOFF = 4,
  403. };
  404. enum RT_CAN_BUS_ERR
  405. {
  406. RT_CAN_BUS_NO_ERR = 0,
  407. RT_CAN_BUS_BIT_PAD_ERR = 1,
  408. RT_CAN_BUS_FORMAT_ERR = 2,
  409. RT_CAN_BUS_ACK_ERR = 3,
  410. RT_CAN_BUS_IMPLICIT_BIT_ERR = 4,
  411. RT_CAN_BUS_EXPLICIT_BIT_ERR = 5,
  412. RT_CAN_BUS_CRC_ERR = 6,
  413. };
  414. /**
  415. * @brief CAN device status and error statistics structure.
  416. */
  417. struct rt_can_status
  418. {
  419. rt_uint32_t rcverrcnt; /**< Receive Error Counter (REC). */
  420. rt_uint32_t snderrcnt; /**< Transmit Error Counter (TEC). */
  421. rt_uint32_t errcode; /**< The current bus error code (see `enum RT_CAN_BUS_ERR`). */
  422. rt_uint32_t rcvpkg; /**< Total number of successfully received packages. */
  423. rt_uint32_t dropedrcvpkg; /**< Number of received packages dropped due to full buffers. */
  424. rt_uint32_t sndpkg; /**< Total number of successfully sent packages. */
  425. rt_uint32_t dropedsndpkg; /**< Number of sent packages dropped due to full buffers or errors. */
  426. rt_uint32_t bitpaderrcnt; /**< Bit stuffing error count. */
  427. rt_uint32_t formaterrcnt; /**< Format error count. */
  428. rt_uint32_t ackerrcnt; /**< Acknowledgment error count. */
  429. rt_uint32_t biterrcnt; /**< Bit error (recessive/dominant) count. */
  430. rt_uint32_t crcerrcnt; /**< CRC error count. */
  431. rt_uint32_t rcvchange; /**< A flag indicating that the RX buffer status has changed. */
  432. rt_uint32_t sndchange; /**< A bitmask indicating which TX mailboxes have changed status. */
  433. rt_uint32_t lasterrtype; /**< The type of the last error that occurred. */
  434. };
  435. #ifdef RT_CAN_USING_HDR
  436. /**
  437. * @brief CAN hardware filter list entry.
  438. * @internal
  439. */
  440. struct rt_can_hdr
  441. {
  442. rt_uint32_t connected; /**< Flag indicating if the filter is connected to a specific list. */
  443. rt_uint32_t msgs; /**< The number of messages currently buffered for this filter. */
  444. struct rt_can_filter_item filter; /**< A copy of the filter configuration item. */
  445. struct rt_list_node list; /**< The list head for messages matched by this filter. */
  446. };
  447. #endif
  448. struct rt_can_device;
  449. /**
  450. * @brief Typedef for the CAN status indication callback function.
  451. * @param[in] can A pointer to the CAN device.
  452. * @param[in] args User-provided arguments.
  453. * @return The operation status.
  454. */
  455. typedef rt_err_t (*rt_canstatus_ind)(struct rt_can_device *can, void *args);
  456. /**
  457. * @brief Structure to hold the status indication callback and its arguments.
  458. */
  459. typedef struct rt_can_status_ind_type
  460. {
  461. rt_canstatus_ind ind; /**< Pointer to the status indication callback function. */
  462. void *args; /**< Pointer to user arguments for the callback. */
  463. } *rt_can_status_ind_type_t;
  464. /**
  465. * @brief Typedef for the periodic bus hook function.
  466. * @param[in] can A pointer to the CAN device.
  467. * @return void
  468. */
  469. typedef void (*rt_can_bus_hook)(struct rt_can_device *can);
  470. /**
  471. * @brief The CAN message structure.
  472. */
  473. struct rt_can_msg
  474. {
  475. rt_uint32_t id : 29; /**< CAN ID (Standard or Extended). */
  476. rt_uint32_t ide : 1; /**< Identifier type: 0=Standard ID, 1=Extended ID. */
  477. rt_uint32_t rtr : 1; /**< Frame type: 0=Data Frame, 1=Remote Frame. */
  478. rt_uint32_t rsv : 1; /**< Reserved bit. */
  479. rt_uint32_t len : 8; /**< Data Length Code (DLC) from 0 to 8. */
  480. rt_uint32_t priv : 8; /**< Private data, used to specify the hardware mailbox in private mode. */
  481. rt_int32_t hdr_index : 8; /**< For received messages, the index of the hardware filter that matched the message. */
  482. #ifdef RT_CAN_USING_CANFD
  483. rt_uint32_t fd_frame : 1; /**< CAN-FD frame indicator. */
  484. rt_uint32_t brs : 1; /**< Bit-rate switching indicator for CAN-FD. */
  485. rt_uint32_t rxfifo : 2; /**< The RX FIFO where the message was received. */
  486. rt_uint32_t reserved : 3;
  487. #else
  488. rt_uint32_t rxfifo : 2; /**< The RX FIFO where the message was received. */
  489. rt_uint32_t reserved : 5;
  490. #endif
  491. rt_uint32_t nonblocking : 1; /**< Send mode: 0=Blocking (default), 1=Non-blocking. */
  492. #ifdef RT_CAN_USING_CANFD
  493. rt_uint8_t data[64]; /**< CAN-FD message payload (up to 64 bytes). */
  494. #else
  495. rt_uint8_t data[8]; /**< CAN message payload (up to 8 bytes). */
  496. #endif
  497. };
  498. typedef struct rt_can_msg *rt_can_msg_t;
  499. #ifndef RT_CAN_NB_TX_FIFO_SIZE
  500. #define RT_CAN_NB_TX_FIFO_SIZE (RT_CANMSG_BOX_SZ * sizeof(struct rt_can_msg))
  501. #endif
  502. /**
  503. * @brief The core CAN device structure.
  504. */
  505. struct rt_can_device
  506. {
  507. struct rt_device parent; /**< Inherits from the base RT-Thread device structure. */
  508. const struct rt_can_ops *ops; /**< A pointer to the low-level driver operations. */
  509. struct can_configure config; /**< The current configuration of the CAN device. */
  510. struct rt_can_status status; /**< The current status and error statistics of the CAN device. */
  511. rt_uint32_t timerinitflag; /**< A flag to indicate if the status timer has been initialized. */
  512. struct rt_timer timer; /**< A timer for periodically checking the CAN bus status. */
  513. struct rt_can_status_ind_type status_indicate; /**< The user-registered status indication callback. */
  514. #ifdef RT_CAN_USING_HDR
  515. struct rt_can_hdr *hdr; /**< A pointer to an array of hardware filter list entries. */
  516. #endif
  517. #ifdef RT_CAN_USING_BUS_HOOK
  518. rt_can_bus_hook bus_hook; /**< The user-registered periodic bus hook function. */
  519. #endif /*RT_CAN_USING_BUS_HOOK*/
  520. struct rt_mutex lock; /**< A mutex for thread-safe access to the device. */
  521. void *can_rx; /**< A pointer to the software receive FIFO structure (`rt_can_rx_fifo`). */
  522. void *can_tx; /**< A pointer to the software transmit FIFO structure (`rt_can_tx_fifo`). */
  523. struct rt_ringbuffer nb_tx_rb; /**< The ring buffer for non-blocking transmissions. */
  524. #ifdef RT_CAN_MALLOC_NB_TX_BUFFER
  525. rt_uint8_t *nb_tx_rb_pool; /**< A pointer to the dynamically allocated pool for the non-blocking TX ring buffer. */
  526. #else
  527. rt_uint8_t nb_tx_rb_pool[RT_CAN_NB_TX_FIFO_SIZE]; /**< The statically allocated pool for the non-blocking TX ring buffer. */
  528. #endif /* RT_CAN_MALLOC_NB_TX_BUFFER */
  529. };
  530. typedef struct rt_can_device *rt_can_t;
  531. #define RT_CAN_STDID 0
  532. #define RT_CAN_EXTID 1
  533. #define RT_CAN_DTR 0
  534. #define RT_CAN_RTR 1
  535. typedef struct rt_can_status *rt_can_status_t;
  536. /**
  537. * @internal
  538. * @brief List node for a single CAN message in a software FIFO.
  539. */
  540. struct rt_can_msg_list
  541. {
  542. struct rt_list_node list; /**< List node to link into a free/used list. */
  543. #ifdef RT_CAN_USING_HDR
  544. struct rt_list_node hdrlist; /**< List node to link into a specific hardware filter's list. */
  545. struct rt_can_hdr *owner; /**< Pointer to the hardware filter that owns this message. */
  546. #endif
  547. struct rt_can_msg data; /**< The actual CAN message data. */
  548. };
  549. /**
  550. * @internal
  551. * @brief Software receive FIFO structure.
  552. */
  553. struct rt_can_rx_fifo
  554. {
  555. struct rt_can_msg_list *buffer; /**< A pointer to the buffer pool of message list nodes. */
  556. rt_uint32_t freenumbers; /**< The number of free nodes in the buffer pool. */
  557. struct rt_list_node freelist; /**< The list of free message nodes. */
  558. struct rt_list_node uselist; /**< The list of used message nodes (containing received messages). */
  559. };
  560. #define RT_CAN_SND_RESULT_OK 0
  561. #define RT_CAN_SND_RESULT_ERR 1
  562. #define RT_CAN_SND_RESULT_WAIT 2
  563. #define RT_CAN_EVENT_RX_IND 0x01 /* Rx indication */
  564. #define RT_CAN_EVENT_TX_DONE 0x02 /* Tx complete */
  565. #define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx fail */
  566. #define RT_CAN_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */
  567. #define RT_CAN_EVENT_RXOF_IND 0x06 /* Rx overflow */
  568. /**
  569. * @internal
  570. * @brief List node for a blocking send operation, corresponding to one hardware mailbox.
  571. */
  572. struct rt_can_sndbxinx_list
  573. {
  574. struct rt_list_node list; /**< List node to link into the free list. */
  575. struct rt_completion completion;/**< A completion object to block the sending thread. */
  576. rt_uint32_t result; /**< The result of the transmission (OK, ERR, WAIT). */
  577. };
  578. /**
  579. * @internal
  580. * @brief Software transmit FIFO structure for blocking sends.
  581. */
  582. struct rt_can_tx_fifo
  583. {
  584. struct rt_can_sndbxinx_list *buffer; /**< A pointer to the buffer of sendbox nodes. */
  585. struct rt_semaphore sem; /**< A counting semaphore representing available hardware mailboxes. */
  586. struct rt_list_node freelist; /**< The list of free sendbox nodes. */
  587. };
  588. /**
  589. * @brief The CAN device driver operations structure.
  590. *
  591. * This structure contains pointers to the low-level functions that implement the CAN functionality.
  592. * It must be provided when registering a CAN device.
  593. */
  594. struct rt_can_ops
  595. {
  596. /**
  597. * @brief Configures the CAN controller with the specified settings.
  598. * @param[in] can A pointer to the CAN device structure.
  599. * @param[in] cfg A pointer to the configuration structure.
  600. * @return `RT_EOK` on success, or a negative error code on failure.
  601. */
  602. rt_err_t (*configure)(struct rt_can_device *can, struct can_configure *cfg);
  603. /**
  604. * @brief Sends control commands to the CAN device.
  605. * @param[in] can A pointer to the CAN device structure.
  606. * @param[in] cmd The control command (e.g., RT_CAN_CMD_SET_FILTER).
  607. * @param[in] arg A pointer to the arguments for the command.
  608. * @return `RT_EOK` on success, or a negative error code on failure.
  609. */
  610. rt_err_t (*control)(struct rt_can_device *can, int cmd, void *arg);
  611. /**
  612. * @brief Low-level blocking function to send a CAN message.
  613. * @param[in] can A pointer to the CAN device structure.
  614. * @param[in] buf A pointer to the `rt_can_msg` to be sent.
  615. * @param[in] boxno The hardware mailbox number to use for transmission.
  616. * @return The number of bytes sent on success, or a negative error code on failure.
  617. */
  618. rt_ssize_t (*sendmsg)(struct rt_can_device *can, const void *buf, rt_uint32_t boxno);
  619. /**
  620. * @brief Low-level function to receive a CAN message.
  621. * @param[in,out] can A pointer to the CAN device structure.
  622. * @param[out] buf A pointer to the buffer to store the received `rt_can_msg`.
  623. * @param[in] fifo The hardware FIFO number to read from.
  624. * @return The number of bytes received on success, or a negative error code on failure.
  625. */
  626. rt_ssize_t (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t fifo);
  627. /**
  628. * @brief Low-level, hardware-specific function to send a CAN message non-blockingly.
  629. *
  630. * This function attempts to place a message into a hardware transmission mailbox
  631. * and returns immediately without waiting for the transmission to complete.
  632. *
  633. * @param[in] can A pointer to the CAN device structure.
  634. * @param[in] buf A pointer to the `rt_can_msg` to be sent.
  635. *
  636. * @return
  637. * - `RT_EOK` if the message was successfully accepted by the hardware.
  638. * - `-RT_EBUSY` if all hardware mailboxes are currently full.
  639. * - Other negative error codes for different failures.
  640. */
  641. rt_ssize_t (*sendmsg_nonblocking)(struct rt_can_device *can, const void *buf);
  642. };
  643. /**
  644. * @brief This function registers a CAN device with the device framework.
  645. *
  646. * @param[in] can A pointer to the CAN device object to be registered.
  647. * @param[in] name The name that the device will be registered with.
  648. * @param[in] ops A pointer to the structure containing the low-level CAN driver operations.
  649. * @param[in] data A pointer to a user-defined data structure, which can be accessed
  650. * via `can->parent.user_data`.
  651. *
  652. * @return `RT_EOK` on successful registration, or a negative error code on failure.
  653. */
  654. rt_err_t rt_hw_can_register(struct rt_can_device *can,
  655. const char *name,
  656. const struct rt_can_ops *ops,
  657. void *data);
  658. /**
  659. * @brief The framework-level ISR handler for CAN devices.
  660. *
  661. * This function is called by the low-level BSP ISR and acts as the central
  662. * dispatcher for all CAN-related interrupt events. It handles both receive
  663. * events and transmission-complete events.
  664. *
  665. * @param[in] can A pointer to the CAN device structure.
  666. * @param[in] event The interrupt event mask, indicating the cause of the interrupt.
  667. */
  668. void rt_hw_can_isr(struct rt_can_device *can, int event);
  669. /*! @}*/
  670. #endif /*__DEV_CAN_H*/