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  */
12 
13 #ifndef __DEV_CAN_H_
14 #define __DEV_CAN_H_
15 
16 #include <rtthread.h>
17 
18 #ifndef RT_CANMSG_BOX_SZ
19 #define RT_CANMSG_BOX_SZ    16
20 #endif
21 #ifndef RT_CANSND_BOX_NUM
22 #define RT_CANSND_BOX_NUM   1
23 #endif
24 #ifndef RT_CANSND_MSG_TIMEOUT
25 #define RT_CANSND_MSG_TIMEOUT 100
26 #endif
27 
28 enum CAN_DLC
29 {
30     CAN_MSG_0BYTE = 0,
31     CAN_MSG_1BYTE,
32     CAN_MSG_2BYTES,
33     CAN_MSG_3BYTES,
34     CAN_MSG_4BYTES,
35     CAN_MSG_5BYTES,
36     CAN_MSG_6BYTES,
37     CAN_MSG_7BYTES,
38     CAN_MSG_8BYTES,
39     CAN_MSG_12BYTES,
40     CAN_MSG_16BYTES,
41     CAN_MSG_20BYTES,
42     CAN_MSG_24BYTES,
43     CAN_MSG_32BYTES,
44     CAN_MSG_48BYTES,
45     CAN_MSG_64BYTES,
46 };
47 
48 enum CANBAUD
49 {
50     CAN1MBaud   = 1000UL * 1000,/* 1 MBit/sec   */
51     CAN800kBaud = 1000UL * 800, /* 800 kBit/sec */
52     CAN500kBaud = 1000UL * 500, /* 500 kBit/sec */
53     CAN250kBaud = 1000UL * 250, /* 250 kBit/sec */
54     CAN125kBaud = 1000UL * 125, /* 125 kBit/sec */
55     CAN100kBaud = 1000UL * 100, /* 100 kBit/sec */
56     CAN50kBaud  = 1000UL * 50,  /* 50 kBit/sec  */
57     CAN20kBaud  = 1000UL * 20,  /* 20 kBit/sec  */
58     CAN10kBaud  = 1000UL * 10   /* 10 kBit/sec  */
59 };
60 
61 #define RT_CAN_MODE_NORMAL              0
62 #define RT_CAN_MODE_LISTEN              1
63 #define RT_CAN_MODE_LOOPBACK            2
64 #define RT_CAN_MODE_LOOPBACKANLISTEN    3
65 
66 #define RT_CAN_MODE_PRIV                0x01
67 #define RT_CAN_MODE_NOPRIV              0x00
68 
69 /**
70  * @defgroup    group_drivers_can CAN Driver
71  * @brief       CAN driver api
72  * @ingroup     group_device_driver
73  *
74  * <b>Example</b>
75  * @code {.c}
76  * #include <rtthread.h>
77  * #include "rtdevice.h"
78  *
79  * #define CAN_DEV_NAME       "can1"      // CAN 设备名称
80  *
81  * static struct rt_semaphore rx_sem;     // 用于接收消息的信号量
82  * static rt_device_t can_dev;            // CAN 设备句柄
83  *
84  * // 接收数据回调函数
85  * static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
86  * {
87  *     // CAN 接收到数据后产生中断,调用此回调函数,然后发送接收信号量
88  *     rt_sem_release(&rx_sem);
89  *
90  *     return RT_EOK;
91  * }
92  *
93  * static void can_rx_thread(void *parameter)
94  * {
95  *     int i;
96  *     rt_err_t res;
97  *     struct rt_can_msg rxmsg = {0};
98  *
99  *     // 设置接收回调函数
100  *     rt_device_set_rx_indicate(can_dev, can_rx_call);
101  *
102  * #ifdef RT_CAN_USING_HDR
103  *     struct rt_can_filter_item items[5] =
104  *     {
105  *         RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), // std,match ID:0x100~0x1ff,hdr 为 - 1,设置默认过滤表
106  *         RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), // std,match ID:0x300~0x3ff,hdr 为 - 1
107  *         RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), // std,match ID:0x211,hdr 为 - 1
108  *         RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL),                  // std,match ID:0x486,hdr 为 - 1
109  *         {0x555, 0, 0, 0, 0x7ff, 7,}                                       // std,match ID:0x555,hdr 为 7,指定设置 7 号过滤表
110  *     };
111  *     struct rt_can_filter_config cfg = {5, 1, items}; // 一共有 5 个过滤表
112  *     // 设置硬件过滤表
113  *     res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
114  *     RT_ASSERT(res == RT_EOK);
115  * #endif
116  *     res = RT_TRUE;
117  *     res = rt_device_control(can_dev, RT_CAN_CMD_START, &res);
118  *     while (1)
119  *     {
120  *         // hdr 值为 - 1,表示直接从 uselist 链表读取数据
121  *         rxmsg.hdr = -1;
122  *         // 阻塞等待接收信号量
123  *         rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
124  *         // 从 CAN 读取一帧数据
125  *         rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
126  *         // 打印数据 ID 及内容
127  *         rt_kprintf("ID:%x", rxmsg.id);
128  *         for (i = 0; i < 8; i++)
129  *         {
130  *             rt_kprintf("%2x", rxmsg.data[i]);
131  *         }
132  *
133  *         rt_kprintf("\n");
134  *     }
135  * }
136  *
137  * int can_sample(int argc, char *argv[])
138  * {
139  *     struct rt_can_msg msg = {0};
140  *     rt_err_t res;
141  *     rt_size_t  size;
142  *     rt_thread_t thread;
143  *     char can_name[RT_NAME_MAX];
144  *
145  *     if (argc == 2)
146  *     {
147  *         rt_strncpy(can_name, argv[1], RT_NAME_MAX);
148  *     }
149  *     else
150  *     {
151  *         rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
152  *     }
153  *     // 查找 CAN 设备
154  *     can_dev = rt_device_find(can_name);
155  *     if (!can_dev)
156  *     {
157  *         rt_kprintf("find %s failed!\n", can_name);
158  *         return -RT_ERROR;
159  *     }
160  *
161  *     // 初始化 CAN 接收信号量
162  *     rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
163  *
164  *     // 以中断接收及发送方式打开 CAN 设备
165  *     res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
166  *     RT_ASSERT(res == RT_EOK);
167  *     // 创建数据接收线程
168  *     thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10);
169  *     if (thread != RT_NULL)
170  *     {
171  *         rt_thread_startup(thread);
172  *     }
173  *     else
174  *     {
175  *         rt_kprintf("create can_rx thread failed!\n");
176  *     }
177  *
178  *     msg.id = 0x78;              // ID 为 0x78
179  *     msg.ide = RT_CAN_STDID;     // 标准格式
180  *     msg.rtr = RT_CAN_DTR;       // 数据帧
181  *     msg.len = 8;                // 数据长度为 8
182  *     // 待发送的 8 字节数据
183  *     msg.data[0] = 0x00;
184  *     msg.data[1] = 0x11;
185  *     msg.data[2] = 0x22;
186  *     msg.data[3] = 0x33;
187  *     msg.data[4] = 0x44;
188  *     msg.data[5] = 0x55;
189  *     msg.data[6] = 0x66;
190  *     msg.data[7] = 0x77;
191  *     // 发送一帧 CAN 数据
192  *     size = rt_device_write(can_dev, 0, &msg, sizeof(msg));
193  *     if (size == 0)
194  *     {
195  *         rt_kprintf("can dev write data failed!\n");
196  *     }
197  *
198  *     return res;
199  * }
200  * // 导出到 msh 命令列表中
201  * MSH_CMD_EXPORT(can_sample, can device sample);
202  * @endcode
203  */
204 
205 
206 /*!
207  * @addtogroup group_drivers_can
208  * @{
209  */
210 #define CAN_RX_FIFO0                (0x00000000U)  /*!< CAN receive FIFO 0 */
211 #define CAN_RX_FIFO1                (0x00000001U)  /*!< CAN receive FIFO 1 */
212 
213 /**
214  * @brief CAN filter item
215  */
216 struct rt_can_filter_item
217 {
218     rt_uint32_t id  : 29;
219     rt_uint32_t ide : 1;
220     rt_uint32_t rtr : 1;
221     rt_uint32_t mode : 1;
222     rt_uint32_t mask;
223     rt_int32_t  hdr_bank;/*Should be defined as:rx.FilterBank,which should be changed to rt_int32_t hdr_bank*/
224     rt_uint32_t rxfifo;/*Add a configuration item that CAN_RX_FIFO0/CAN_RX_FIFO1*/
225 #ifdef RT_CAN_USING_HDR
226     rt_err_t (*ind)(rt_device_t dev, void *args , rt_int32_t hdr, rt_size_t size);
227     void *args;
228 #endif /*RT_CAN_USING_HDR*/
229 };
230 
231 
232 #ifdef RT_CAN_USING_HDR
233 #define RT_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask,ind,args) \
234       {(id), (ide), (rtr), (mode),(mask), -1, CAN_RX_FIFO0,(ind), (args)}/*0:CAN_RX_FIFO0*/
235 #define RT_CAN_FILTER_STD_INIT(id,ind,args) \
236      RT_CAN_FILTER_ITEM_INIT(id,0,0,0,0xFFFFFFFF,ind,args)
237 #define RT_CAN_FILTER_EXT_INIT(id,ind,args) \
238      RT_CAN_FILTER_ITEM_INIT(id,1,0,0,0xFFFFFFFF,ind,args)
239 #define RT_CAN_STD_RMT_FILTER_INIT(id,ind,args) \
240      RT_CAN_FILTER_ITEM_INIT(id,0,1,0,0xFFFFFFFF,ind,args)
241 #define RT_CAN_EXT_RMT_FILTER_INIT(id,ind,args) \
242      RT_CAN_FILTER_ITEM_INIT(id,1,1,0,0xFFFFFFFF,ind,args)
243 #define RT_CAN_STD_RMT_DATA_FILTER_INIT(id,ind,args) \
244      RT_CAN_FILTER_ITEM_INIT(id,0,0,1,0xFFFFFFFF,ind,args)
245 #define RT_CAN_EXT_RMT_DATA_FILTER_INIT(id,ind,args) \
246      RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF,ind,args)
247 #else
248 
249 #define RT_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask) \
250       {(id), (ide), (rtr), (mode), (mask), -1, CAN_RX_FIFO0 }/*0:CAN_RX_FIFO0*/
251 #define RT_CAN_FILTER_STD_INIT(id) \
252      RT_CAN_FILTER_ITEM_INIT(id,0,0,0,0xFFFFFFFF)
253 #define RT_CAN_FILTER_EXT_INIT(id) \
254      RT_CAN_FILTER_ITEM_INIT(id,1,0,0,0xFFFFFFFF)
255 #define RT_CAN_STD_RMT_FILTER_INIT(id) \
256      RT_CAN_FILTER_ITEM_INIT(id,0,1,0,0xFFFFFFFF)
257 #define RT_CAN_EXT_RMT_FILTER_INIT(id) \
258      RT_CAN_FILTER_ITEM_INIT(id,1,1,0,0xFFFFFFFF)
259 #define RT_CAN_STD_RMT_DATA_FILTER_INIT(id) \
260      RT_CAN_FILTER_ITEM_INIT(id,0,0,1,0xFFFFFFFF)
261 #define RT_CAN_EXT_RMT_DATA_FILTER_INIT(id) \
262      RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF)
263 #endif
264 
265 
266 /**
267  * @brief CAN filter configuration
268  */
269 struct rt_can_filter_config
270 {
271     rt_uint32_t count;
272     rt_uint32_t actived;
273     struct rt_can_filter_item *items;
274 };
275 
276 /**
277  * @brief CAN timing configuration
278  */
279 struct rt_can_bit_timing
280 {
281     rt_uint16_t prescaler;  /* Pre-scaler */
282     rt_uint16_t num_seg1;   /* Bit Timing Segment 1, in terms of Tq */
283     rt_uint16_t num_seg2;   /* Bit Timing Segment 2, in terms of Tq */
284     rt_uint8_t num_sjw;     /* Synchronization Jump Width, in terms of Tq */
285     rt_uint8_t num_sspoff;  /* Secondary Sample Point Offset, in terms of Tq */
286 };
287 
288 /**
289  * @brief CAN bit timing configuration list
290  * @note
291  *  items[0] always for CAN2.0/CANFD Arbitration Phase
292  *  items[1] always for CANFD (if it exists)
293  */
294 struct rt_can_bit_timing_config
295 {
296     rt_uint32_t count;
297     struct rt_can_bit_timing *items;
298 };
299 
300 
301 /**
302  * @brief CAN configuration
303  */
304 struct can_configure
305 {
306     rt_uint32_t baud_rate;
307     rt_uint32_t msgboxsz;
308     rt_uint32_t sndboxnumber;
309     rt_uint32_t mode      : 8;
310     rt_uint32_t privmode  : 8;
311     rt_uint32_t reserved  : 16;
312     rt_uint32_t ticks;
313 #ifdef RT_CAN_USING_HDR
314     rt_uint32_t maxhdr;
315 #endif
316 
317 #ifdef RT_CAN_USING_CANFD
318     rt_uint32_t baud_rate_fd;       /* CANFD data bit rate*/
319     rt_uint32_t use_bit_timing: 8;  /* Use the bit timing for CAN timing configuration */
320     rt_uint32_t enable_canfd : 8;   /* Enable CAN-FD mode */
321     rt_uint32_t reserved1 : 16;
322 
323     /* The below fields take effect only if use_bit_timing is non-zero */
324     struct rt_can_bit_timing can_timing;    /* CAN bit-timing /CANFD bit-timing for arbitration phase */
325     struct rt_can_bit_timing canfd_timing;  /* CANFD bit-timing for datat phase */
326 #endif
327 };
328 
329 #define CANDEFAULTCONFIG \
330 {\
331         CAN1MBaud,\
332         RT_CANMSG_BOX_SZ,\
333         RT_CANSND_BOX_NUM,\
334         RT_CAN_MODE_NORMAL,\
335 };
336 
337 struct rt_can_ops;
338 #define RT_CAN_CMD_SET_FILTER       0x13
339 #define RT_CAN_CMD_SET_BAUD         0x14
340 #define RT_CAN_CMD_SET_MODE         0x15
341 #define RT_CAN_CMD_SET_PRIV         0x16
342 #define RT_CAN_CMD_GET_STATUS       0x17
343 #define RT_CAN_CMD_SET_STATUS_IND   0x18
344 #define RT_CAN_CMD_SET_BUS_HOOK     0x19
345 #define RT_CAN_CMD_SET_CANFD        0x1A
346 #define RT_CAN_CMD_SET_BAUD_FD      0x1B
347 #define RT_CAN_CMD_SET_BITTIMING    0x1C
348 #define RT_CAN_CMD_START            0x1D
349 
350 #define RT_DEVICE_CAN_INT_ERR       0x1000
351 
352 enum RT_CAN_STATUS_MODE
353 {
354     NORMAL = 0,
355     ERRWARNING = 1,
356     ERRPASSIVE = 2,
357     BUSOFF = 4,
358 };
359 enum RT_CAN_BUS_ERR
360 {
361     RT_CAN_BUS_NO_ERR = 0,
362     RT_CAN_BUS_BIT_PAD_ERR = 1,
363     RT_CAN_BUS_FORMAT_ERR = 2,
364     RT_CAN_BUS_ACK_ERR = 3,
365     RT_CAN_BUS_IMPLICIT_BIT_ERR = 4,
366     RT_CAN_BUS_EXPLICIT_BIT_ERR = 5,
367     RT_CAN_BUS_CRC_ERR = 6,
368 };
369 
370 /**
371  * @brief CAN status
372  */
373 struct rt_can_status
374 {
375     rt_uint32_t rcverrcnt;
376     rt_uint32_t snderrcnt;
377     rt_uint32_t errcode;
378     rt_uint32_t rcvpkg;
379     rt_uint32_t dropedrcvpkg;
380     rt_uint32_t sndpkg;
381     rt_uint32_t dropedsndpkg;
382     rt_uint32_t bitpaderrcnt;
383     rt_uint32_t formaterrcnt;
384     rt_uint32_t ackerrcnt;
385     rt_uint32_t biterrcnt;
386     rt_uint32_t crcerrcnt;
387     rt_uint32_t rcvchange;
388     rt_uint32_t sndchange;
389     rt_uint32_t lasterrtype;
390 };
391 
392 #ifdef RT_CAN_USING_HDR
393 struct rt_can_hdr
394 {
395     rt_uint32_t connected;
396     rt_uint32_t msgs;
397     struct rt_can_filter_item filter;
398     struct rt_list_node list;
399 };
400 #endif
401 struct rt_can_device;
402 typedef rt_err_t (*rt_canstatus_ind)(struct rt_can_device *, void *);
403 
404 typedef struct rt_can_status_ind_type
405 {
406     rt_canstatus_ind ind;
407     void *args;
408 } *rt_can_status_ind_type_t;
409 typedef void (*rt_can_bus_hook)(struct rt_can_device *);
410 struct rt_can_device
411 {
412     struct rt_device parent;
413 
414     const struct rt_can_ops *ops;
415     struct can_configure config;
416     struct rt_can_status status;
417 
418     rt_uint32_t timerinitflag;
419     struct rt_timer timer;
420 
421     struct rt_can_status_ind_type status_indicate;
422 #ifdef RT_CAN_USING_HDR
423     struct rt_can_hdr *hdr;
424 #endif
425 #ifdef RT_CAN_USING_BUS_HOOK
426     rt_can_bus_hook bus_hook;
427 #endif /*RT_CAN_USING_BUS_HOOK*/
428     struct rt_mutex lock;
429     void *can_rx;
430     void *can_tx;
431 };
432 typedef struct rt_can_device *rt_can_t;
433 
434 #define RT_CAN_STDID 0
435 #define RT_CAN_EXTID 1
436 #define RT_CAN_DTR   0
437 #define RT_CAN_RTR   1
438 
439 typedef struct rt_can_status *rt_can_status_t;
440 
441 struct rt_can_msg
442 {
443     rt_uint32_t id  : 29;
444     rt_uint32_t ide : 1;
445     rt_uint32_t rtr : 1;
446     rt_uint32_t rsv : 1;
447     rt_uint32_t len : 8;
448     rt_uint32_t priv : 8;
449     rt_int32_t hdr_index : 8;/*Should be defined as:rx.FilterMatchIndex,which should be changed to rt_int32_t hdr_index : 8*/
450 #ifdef RT_CAN_USING_CANFD
451     rt_uint32_t fd_frame : 1;
452     rt_uint32_t brs : 1;
453     rt_uint32_t rxfifo : 2;/*Redefined to return :CAN RX FIFO0/CAN RX FIFO1*/
454     rt_uint32_t reserved : 4;
455 #else
456     rt_uint32_t rxfifo : 2;/*Redefined to return :CAN RX FIFO0/CAN RX FIFO1*/
457     rt_uint32_t reserved : 6;
458 #endif
459 #ifdef RT_CAN_USING_CANFD
460     rt_uint8_t data[64];
461 #else
462     rt_uint8_t data[8];
463 #endif
464 };
465 typedef struct rt_can_msg *rt_can_msg_t;
466 
467 struct rt_can_msg_list
468 {
469     struct rt_list_node list;
470 #ifdef RT_CAN_USING_HDR
471     struct rt_list_node hdrlist;
472     struct rt_can_hdr *owner;
473 #endif
474     struct rt_can_msg data;
475 };
476 
477 struct rt_can_rx_fifo
478 {
479     /* software fifo */
480     struct rt_can_msg_list *buffer;
481     rt_uint32_t freenumbers;
482     struct rt_list_node freelist;
483     struct rt_list_node uselist;
484 };
485 
486 #define RT_CAN_SND_RESULT_OK        0
487 #define RT_CAN_SND_RESULT_ERR       1
488 #define RT_CAN_SND_RESULT_WAIT      2
489 
490 #define RT_CAN_EVENT_RX_IND         0x01    /* Rx indication */
491 #define RT_CAN_EVENT_TX_DONE        0x02    /* Tx complete   */
492 #define RT_CAN_EVENT_TX_FAIL        0x03    /* Tx fail   */
493 #define RT_CAN_EVENT_RX_TIMEOUT     0x05    /* Rx timeout    */
494 #define RT_CAN_EVENT_RXOF_IND       0x06    /* Rx overflow */
495 
496 struct rt_can_sndbxinx_list
497 {
498     struct rt_list_node list;
499     struct rt_completion completion;
500     rt_uint32_t result;
501 };
502 
503 struct rt_can_tx_fifo
504 {
505     struct rt_can_sndbxinx_list *buffer;
506     struct rt_semaphore sem;
507     struct rt_list_node freelist;
508 };
509 
510 /**
511  * @brief CAN operators
512  */
513 struct rt_can_ops
514 {
515     rt_err_t (*configure)(struct rt_can_device *can, struct can_configure *cfg);
516     rt_err_t (*control)(struct rt_can_device *can, int cmd, void *arg);
517     rt_ssize_t (*sendmsg)(struct rt_can_device *can, const void *buf, rt_uint32_t boxno);
518     rt_ssize_t (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t boxno);
519 };
520 
521 /**
522  * @brief Register a CAN device to device list
523  *
524  * @param can   the CAN device object
525  * @param name  the name of CAN device
526  * @param ops   the CAN device operators
527  * @param data  the private data of CAN device
528  *
529  * @return the error code, RT_EOK on successfully
530  */
531 rt_err_t rt_hw_can_register(struct rt_can_device    *can,
532                             const char              *name,
533                             const struct rt_can_ops *ops,
534                             void                    *data);
535 
536 /**
537  * @brief CAN interrupt service routine
538  *
539  * @param can    the CAN device
540  * @param event  the event mask
541  */
542 void rt_hw_can_isr(struct rt_can_device *can, int event);
543 
544 /*! @}*/
545 
546 #endif /*__DEV_CAN_H*/
547 
548