dev_can.h 29 KB

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