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