drv_can.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Email: opensource_embedded@phytium.com.cn
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2023-03-20 zhangyan first version
  11. *
  12. */
  13. #include "rtconfig.h"
  14. #ifdef BSP_USING_CAN
  15. #include "drv_can.h"
  16. #define LOG_TAG "can_drv"
  17. #include "drv_log.h"
  18. #include "fcan.h"
  19. #include "fio_mux.h"
  20. #include "interrupt.h"
  21. struct phytium_can
  22. {
  23. const char *name;
  24. FCanCtrl can_handle;
  25. FCanIdMaskConfig filter;
  26. struct rt_can_device device; /* inherit from can device */
  27. };
  28. static struct phytium_can drv_can[FCAN_NUM] =
  29. {
  30. {
  31. .name = "CAN0",
  32. .can_handle.config.instance_id = 0,
  33. },
  34. {
  35. .name = "CAN1",
  36. .can_handle.config.instance_id = 1,
  37. },
  38. };
  39. static void CanRxIrqCallback(void *args)
  40. {
  41. FCanCtrl *instance_p = (FCanCtrl *)args;
  42. rt_hw_can_isr(&drv_can[instance_p->config.instance_id].device, RT_CAN_EVENT_RX_IND);
  43. LOG_D("CAN%d irq recv frame callback.", instance_p->config.instance_id);
  44. }
  45. static void CanErrorCallback(void *args)
  46. {
  47. FCanCtrl *instance_p = (FCanCtrl *)args;
  48. uintptr base_addr = instance_p->config.base_address;
  49. LOG_D("CAN %d is under error.", instance_p->config.instance_id);
  50. LOG_D("error_status is %x.", FCAN_READ_REG32(base_addr, FCAN_INTR_OFFSET));
  51. LOG_D("rxerr_cnt is %x.", FCAN_ERR_CNT_RFN_GET(FCAN_READ_REG32(base_addr, FCAN_ERR_CNT_OFFSET)));
  52. LOG_D("txerr_cnt is %x.", FCAN_ERR_CNT_TFN_GET(FCAN_READ_REG32(base_addr, FCAN_ERR_CNT_OFFSET)));
  53. }
  54. static void CanTxIrqCallback(void *args)
  55. {
  56. FCanCtrl *instance_p = (FCanCtrl *)args;
  57. rt_hw_can_isr(&drv_can[instance_p->config.instance_id].device, RT_CAN_EVENT_TX_DONE);
  58. LOG_D("CAN%d irq send frame callback.", instance_p->config.instance_id);
  59. }
  60. static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg)
  61. {
  62. RT_ASSERT(can);
  63. RT_ASSERT(cfg);
  64. struct phytium_can *drv_can;
  65. drv_can = (struct phytium_can *)can->parent.user_data;
  66. RT_ASSERT(drv_can);
  67. FError status = FT_SUCCESS;
  68. rt_kprintf("CAN%d begin to config.\n", drv_can->can_handle.config.instance_id);
  69. FIOPadSetCanMux(drv_can->can_handle.config.instance_id);
  70. /*CAN config init*/
  71. status = FCanCfgInitialize(&(drv_can->can_handle), FCanLookupConfig(drv_can->can_handle.config.instance_id));
  72. if (status != FT_SUCCESS)
  73. {
  74. LOG_D("CAN %d initialize error, status = %#x.", drv_can->can_handle.config.instance_id, status);
  75. return RT_ERROR;
  76. }
  77. /*Set the baudrate*/
  78. FCanBaudrateConfig arb_segment_config;
  79. FCanBaudrateConfig data_segment_config;
  80. memset(&arb_segment_config, 0, sizeof(arb_segment_config));
  81. memset(&data_segment_config, 0, sizeof(data_segment_config));
  82. #if defined(RT_CAN_USING_CANFD)
  83. FCanFdEnable(&(drv_can->can_handle), TRUE);
  84. arb_segment_config.auto_calc = TRUE;
  85. arb_segment_config.baudrate = CAN1MBaud; /*CANFD arb baud defaults to 1M ,allowed to be modified*/
  86. arb_segment_config.segment = FCAN_ARB_SEGMENT;
  87. status = FCanBaudrateSet(&(drv_can->can_handle), &arb_segment_config);
  88. if (status != RT_EOK)
  89. {
  90. LOG_D("CAN%d set arb segment baudrate failed.", drv_can->can_handle.config.instance_id);
  91. return RT_ERROR;
  92. }
  93. data_segment_config.auto_calc = TRUE;
  94. data_segment_config.baudrate = cfg->baud_rate_fd;
  95. data_segment_config.segment = FCAN_DATA_SEGMENT;
  96. status = FCanBaudrateSet(&(drv_can->can_handle), &data_segment_config);
  97. if (status != RT_EOK)
  98. {
  99. LOG_D("CAN%d set data segment baudrate failed.", drv_can->can_handle.config.instance_id);
  100. return RT_ERROR;
  101. }
  102. #else
  103. arb_segment_config.auto_calc = TRUE;
  104. arb_segment_config.baudrate = cfg->baud_rate;
  105. arb_segment_config.segment = FCAN_ARB_SEGMENT;
  106. status = FCanBaudrateSet(&(drv_can->can_handle), &arb_segment_config);
  107. if (status != FT_SUCCESS)
  108. {
  109. LOG_D("CAN%d set arb segment baudrate failed.", drv_can->can_handle.config.instance_id);
  110. return RT_ERROR;
  111. }
  112. data_segment_config.auto_calc = TRUE;
  113. data_segment_config.baudrate = cfg->baud_rate;
  114. data_segment_config.segment = FCAN_DATA_SEGMENT;
  115. status = FCanBaudrateSet(&(drv_can->can_handle), &data_segment_config);
  116. if (status != FT_SUCCESS)
  117. {
  118. LOG_D("CAN%d set data segment baudrate failed.", drv_can->can_handle.config.instance_id);
  119. return RT_ERROR;
  120. }
  121. #endif
  122. /*CAN filter function init*/
  123. for (int i = 0; i < FCAN_ACC_ID_REG_NUM; i++)
  124. {
  125. drv_can->filter.filter_index = i;
  126. drv_can->filter.id = 0;
  127. drv_can->filter.mask = FCAN_ACC_IDN_MASK;
  128. status |= FCanIdMaskFilterSet(&(drv_can->can_handle), &(drv_can->filter));
  129. }
  130. if (status != FT_SUCCESS)
  131. {
  132. LOG_E("CAN%d set mask filter failed.", drv_can->can_handle.config.instance_id);
  133. return RT_ERROR;
  134. }
  135. /* Identifier mask enable */
  136. FCanIdMaskFilterEnable(&(drv_can->can_handle));
  137. /* Transmit mode init , the default setting is normal mode */
  138. FCanSetMode(&(drv_can->can_handle), FCAN_PROBE_NORMAL_MODE);
  139. /* enable can transfer */
  140. FCanEnable(&(drv_can->can_handle), RT_TRUE);
  141. return RT_EOK;
  142. }
  143. static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
  144. {
  145. RT_ASSERT(can);
  146. rt_uint32_t argval;
  147. struct phytium_can *drv_can;
  148. drv_can = (struct phytium_can *)can->parent.user_data;
  149. RT_ASSERT(drv_can != RT_NULL);
  150. rt_uint32_t cpu_id;
  151. FCanIntrEventConfig intr_event;
  152. FError status = FT_SUCCESS;
  153. #ifdef RT_CAN_USING_HDR
  154. struct rt_can_filter_config *filter_cfg;
  155. #endif
  156. switch (cmd)
  157. {
  158. case RT_DEVICE_CTRL_SET_INT:
  159. GetCpuId(&cpu_id);
  160. rt_hw_interrupt_set_target_cpus(drv_can->can_handle.config.irq_num, cpu_id);
  161. argval = (rt_uint32_t) arg;
  162. /*Open different interrupts*/
  163. if (argval == RT_DEVICE_CAN_INT_ERR)
  164. {
  165. intr_event.type = FCAN_INTR_EVENT_ERROR;
  166. intr_event.handler = CanErrorCallback;
  167. intr_event.param = (void *)(&(drv_can->can_handle));
  168. FCanRegisterInterruptHandler(&(drv_can->can_handle), &intr_event);
  169. FCanInterruptEnable(&(drv_can->can_handle), intr_event.type);
  170. }
  171. if (argval == RT_DEVICE_FLAG_INT_TX)
  172. {
  173. intr_event.type = FCAN_INTR_EVENT_SEND;
  174. intr_event.handler = CanTxIrqCallback;
  175. intr_event.param = (void *)(&(drv_can->can_handle));
  176. FCanRegisterInterruptHandler(&(drv_can->can_handle), &intr_event);
  177. FCanInterruptEnable(&(drv_can->can_handle), intr_event.type);
  178. }
  179. if (argval == RT_DEVICE_FLAG_INT_RX)
  180. {
  181. intr_event.type = FCAN_INTR_EVENT_RECV;
  182. intr_event.handler = CanRxIrqCallback;
  183. intr_event.param = (void *)(&(drv_can->can_handle));
  184. FCanRegisterInterruptHandler(&(drv_can->can_handle), &intr_event);
  185. FCanInterruptEnable(&(drv_can->can_handle), intr_event.type);
  186. }
  187. rt_hw_interrupt_set_priority(drv_can->can_handle.config.irq_num, 16);
  188. rt_hw_interrupt_install(drv_can->can_handle.config.irq_num, FCanIntrHandler, &(drv_can->can_handle), drv_can->name);
  189. rt_hw_interrupt_umask(drv_can->can_handle.config.irq_num);
  190. break;
  191. case RT_CAN_CMD_SET_MODE:
  192. argval = (rt_uint32_t) arg;
  193. FCanEnable(&(drv_can->can_handle), RT_FALSE);
  194. if (argval == RT_CAN_MODE_LISTEN)
  195. {
  196. FCanSetMode(&(drv_can->can_handle), FCAN_PROBE_MONITOR_MODE);
  197. drv_can->device.config.mode = RT_CAN_MODE_LISTEN;
  198. }
  199. else if (argval == RT_CAN_MODE_NORMAL)
  200. {
  201. FCanSetMode(&(drv_can->can_handle), FCAN_PROBE_NORMAL_MODE);
  202. drv_can->device.config.mode = RT_CAN_MODE_NORMAL;
  203. }
  204. FCanEnable(&(drv_can->can_handle), RT_TRUE);
  205. break;
  206. case RT_CAN_CMD_SET_BAUD:
  207. argval = (rt_uint32_t) arg;
  208. if (argval != CAN1MBaud &&
  209. argval != CAN800kBaud &&
  210. argval != CAN500kBaud &&
  211. argval != CAN250kBaud &&
  212. argval != CAN125kBaud &&
  213. argval != CAN100kBaud &&
  214. argval != CAN50kBaud &&
  215. argval != CAN20kBaud &&
  216. argval != CAN10kBaud)
  217. {
  218. return RT_ERROR;
  219. }
  220. if (argval != drv_can->device.config.baud_rate)
  221. {
  222. FCanBaudrateConfig arb_segment_config;
  223. FCanBaudrateConfig data_segment_config;
  224. memset(&arb_segment_config, 0, sizeof(arb_segment_config));
  225. memset(&data_segment_config, 0, sizeof(data_segment_config));
  226. drv_can->device.config.baud_rate = argval;
  227. FCanEnable(&(drv_can->can_handle), RT_FALSE);
  228. arb_segment_config.auto_calc = TRUE;
  229. arb_segment_config.baudrate = drv_can->device.config.baud_rate;
  230. arb_segment_config.segment = FCAN_ARB_SEGMENT;
  231. status = FCanBaudrateSet(&(drv_can->can_handle), &arb_segment_config);
  232. if (status != FT_SUCCESS)
  233. {
  234. LOG_D("CAN%d set arb segment baudrate failed.", drv_can->can_handle.config.instance_id);
  235. return RT_ERROR;
  236. }
  237. data_segment_config.auto_calc = TRUE;
  238. data_segment_config.baudrate = drv_can->device.config.baud_rate;
  239. data_segment_config.segment = FCAN_DATA_SEGMENT;
  240. status = FCanBaudrateSet(&(drv_can->can_handle), &data_segment_config);
  241. if (status != FT_SUCCESS)
  242. {
  243. LOG_D("CAN%d set data segment baudrate failed.", drv_can->can_handle.config.instance_id);
  244. return RT_ERROR;
  245. }
  246. FCanEnable(&(drv_can->can_handle), RT_TRUE);
  247. }
  248. break;
  249. case RT_CAN_CMD_SET_BAUD_FD:
  250. #if defined RT_CAN_USING_CANFD
  251. argval = (rt_uint32_t) arg;
  252. if (argval != drv_can->device.config.baud_rate_fd)
  253. {
  254. FCanBaudrateConfig arb_segment_config;
  255. FCanBaudrateConfig data_segment_config;
  256. memset(&arb_segment_config, 0, sizeof(arb_segment_config));
  257. memset(&data_segment_config, 0, sizeof(data_segment_config));
  258. drv_can->device.config.baud_rate = argval;
  259. FCanEnable(&(drv_can->can_handle), RT_FALSE);
  260. arb_segment_config.auto_calc = TRUE;
  261. arb_segment_config.baudrate = CAN1MBaud;
  262. arb_segment_config.segment = FCAN_ARB_SEGMENT;
  263. status = FCanBaudrateSet(&(drv_can->can_handle), &arb_segment_config);
  264. if (status != FT_SUCCESS)
  265. {
  266. LOG_D("CAN%d set arb segment baudrate failed.", drv_can->can_handle.config.instance_id);
  267. return RT_ERROR;
  268. }
  269. data_segment_config.auto_calc = TRUE;
  270. data_segment_config.baudrate = drv_can->device.config.baud_rate_fd;
  271. data_segment_config.segment = FCAN_DATA_SEGMENT;
  272. status = FCanBaudrateSet(&(drv_can->can_handle), &data_segment_config);
  273. if (status != FT_SUCCESS)
  274. {
  275. LOG_D("CAN%d set data segment baudrate failed.", drv_can->can_handle.config.instance_id);
  276. return RT_ERROR;
  277. }
  278. FCanEnable(&(drv_can->can_handle), RT_TRUE);
  279. }
  280. #endif
  281. break;
  282. case RT_CAN_CMD_SET_FILTER:
  283. #ifdef RT_CAN_USING_HDR
  284. filter_cfg = (struct rt_can_filter_config *)arg;
  285. FCanEnable(&(drv_can->can_handle), RT_FALSE);
  286. for (int i = 0; i < filter_cfg->count; i++)
  287. {
  288. drv_can->filter.filter_index = i;
  289. drv_can->filter.mask = filter_cfg->items[i].mask;
  290. drv_can->filter.id = filter_cfg->items[i].id;
  291. drv_can->filter.type = FCAN_STANDARD_FRAME;
  292. status = FCanIdMaskFilterSet(&(drv_can->can_handle), &(drv_can->filter));
  293. if (status != FT_SUCCESS)
  294. {
  295. LOG_E("CAN%d set mask filter failed.", drv_can->can_handle.config.instance_id);
  296. return RT_ERROR;
  297. }
  298. }
  299. FCanEnable(&(drv_can->can_handle), RT_TRUE);
  300. #endif
  301. break;
  302. }
  303. return RT_EOK;
  304. }
  305. static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
  306. {
  307. RT_ASSERT(can);
  308. RT_ASSERT(buf);
  309. struct phytium_can *drv_can;
  310. drv_can = (struct phytium_can *)can->parent.user_data;
  311. RT_ASSERT(drv_can);
  312. struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
  313. FCanFrame can_frame = {0};
  314. /* Check the parameters */
  315. RT_ASSERT(pmsg->len <= 8U);
  316. if (RT_CAN_STDID == pmsg->ide)
  317. {
  318. can_frame.canid = pmsg->id;
  319. }
  320. else
  321. {
  322. can_frame.canid = pmsg->id;
  323. can_frame.canid |= CAN_EFF_FLAG;
  324. }
  325. if (RT_CAN_DTR == pmsg->rtr)
  326. {
  327. }
  328. else
  329. {
  330. can_frame.canid |= CAN_RTR_FLAG;
  331. }
  332. can_frame.candlc = pmsg->len ;
  333. memcpy(can_frame.data, pmsg->data, 8);
  334. return (FCanSend(&drv_can->can_handle, &can_frame) == RT_EOK) ? RT_EOK : -RT_ERROR;
  335. }
  336. static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
  337. {
  338. RT_ASSERT(can);
  339. RT_ASSERT(buf);
  340. struct phytium_can *drv_can;
  341. drv_can = (struct phytium_can *)can->parent.user_data;
  342. RT_ASSERT(drv_can);
  343. struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
  344. FCanFrame recv_frame;
  345. FError status = FT_SUCCESS;
  346. status = FCanRecv(&(drv_can->can_handle), &recv_frame);
  347. if (status != FT_SUCCESS)
  348. {
  349. LOG_D("CAN%d recv data failed.", drv_can->can_handle.config.instance_id);
  350. return RT_ERROR;
  351. }
  352. if (CAN_EFF_FLAG & recv_frame.canid)
  353. {
  354. pmsg->ide = RT_CAN_EXTID;
  355. pmsg->id = (recv_frame.canid & ~(RT_CAN_EXTID));
  356. }
  357. else
  358. {
  359. pmsg->ide = RT_CAN_STDID;
  360. pmsg->id = recv_frame.canid;
  361. }
  362. if (CAN_RTR_FLAG & recv_frame.canid)
  363. {
  364. pmsg->id &= ~CAN_RTR_FLAG;
  365. pmsg->rtr = RT_CAN_RTR;
  366. }
  367. else
  368. {
  369. pmsg->rtr = RT_CAN_DTR;
  370. }
  371. /* get len */
  372. pmsg->len = recv_frame.candlc;
  373. for (int i = 0; i < pmsg->len; i++)
  374. {
  375. pmsg->data[i] = recv_frame.data[i];
  376. }
  377. /* get hdr */
  378. pmsg->hdr_index = 0;
  379. return RT_EOK;
  380. }
  381. static const struct rt_can_ops _can_ops =
  382. {
  383. _can_config,
  384. _can_control,
  385. _can_sendmsg,
  386. _can_recvmsg,
  387. };
  388. static int can_init(u32 can_id)
  389. {
  390. rt_err_t ret = RT_EOK;
  391. drv_can[can_id].device.config.ticks = 20000;
  392. drv_can[can_id].device.config.baud_rate = 800000;
  393. #ifdef RT_CAN_USING_CANFD
  394. drv_can[can_id].device.config.baud_rate_fd = 800000;
  395. #endif
  396. drv_can[can_id].device.config.mode = RT_CAN_MODE_NORMAL;
  397. drv_can[can_id].device.config.sndboxnumber = 1;
  398. drv_can[can_id].device.config.msgboxsz = 1;
  399. #ifdef RT_CAN_USING_HDR
  400. drv_can[can_id].device.config.maxhdr = 1;
  401. #endif
  402. ret = rt_hw_can_register(&drv_can[can_id].device,
  403. drv_can[can_id].name,
  404. &_can_ops,
  405. &drv_can[can_id]);
  406. RT_ASSERT(ret == RT_EOK);
  407. return ret;
  408. }
  409. int rt_hw_can_init(void)
  410. {
  411. #if defined(RT_USING_CAN0)
  412. can_init(FCAN0_ID);
  413. #endif
  414. #if defined(RT_USING_CAN1)
  415. can_init(FCAN1_ID);
  416. #endif
  417. #if defined(RT_USING_CAN2)
  418. can_init(FCAN2_ID);
  419. #endif
  420. return 0;
  421. }
  422. INIT_BOARD_EXPORT(rt_hw_can_init);
  423. /*can test example*/
  424. static rt_device_t can_dev; /* CAN device handle */
  425. static struct rt_semaphore rx_sem;
  426. static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
  427. {
  428. /* The CAN generates an interrupt after receiving data, calls this callback function, and then sends the received semaphore */
  429. rt_sem_release(&rx_sem);
  430. return RT_EOK;
  431. }
  432. static void can_rx_thread(void *parameter)
  433. {
  434. int i;
  435. rt_err_t res = RT_EOK;
  436. struct rt_can_msg rxmsg = {0};
  437. rt_device_set_rx_indicate(can_dev, can_rx_call);
  438. while (1)
  439. {
  440. /* The hdr value is - 1, which means reading data directly from the uselist */
  441. rxmsg.hdr_index = -1;
  442. /* Blocking waiting to receive semaphore */
  443. res = rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
  444. RT_ASSERT(res == RT_EOK);
  445. /* Read a frame of data from CAN */
  446. rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
  447. /* Print data ID and conten */
  448. rt_kprintf("ID:%x\n", rxmsg.id);
  449. rt_kprintf("DATA: ");
  450. for (i = 0; i < 8; i++)
  451. {
  452. rt_kprintf("%2x ", rxmsg.data[i]);
  453. }
  454. rt_kprintf("\n");
  455. }
  456. }
  457. int can_sample(int argc, char *argv[])
  458. {
  459. struct rt_can_msg msg = {0};
  460. rt_err_t res = RT_EOK;;
  461. rt_thread_t thread;
  462. char can_name[RT_NAME_MAX];
  463. if (argc == 2)
  464. {
  465. rt_strncpy(can_name, argv[1], RT_NAME_MAX);
  466. }
  467. else
  468. {
  469. rt_strncpy(can_name, "CAN0", RT_NAME_MAX);
  470. }
  471. /* Find CAN device */
  472. can_dev = rt_device_find(can_name);
  473. if (!can_dev)
  474. {
  475. rt_kprintf("Find %s failed.\n", can_name);
  476. return RT_ERROR;
  477. }
  478. /* Initialize CAN receive signal quantity */
  479. res = rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
  480. RT_ASSERT(res == RT_EOK);
  481. /* Open the CAN device in the way of interrupt reception and transmission */
  482. res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
  483. rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, CAN1MBaud);
  484. RT_ASSERT(res == RT_EOK);
  485. #ifdef RT_CAN_USING_HDR
  486. struct rt_can_filter_item items[4] =
  487. {
  488. RT_CAN_FILTER_ITEM_INIT(0x3, 0, 0, 0, 0, RT_NULL, RT_NULL),
  489. RT_CAN_FILTER_ITEM_INIT(0x3, 0, 0, 0, 0, RT_NULL, RT_NULL),
  490. RT_CAN_FILTER_ITEM_INIT(0x3, 0, 0, 0, 0, RT_NULL, RT_NULL),
  491. RT_CAN_FILTER_ITEM_INIT(0x3, 0, 0, 0, 0, RT_NULL, RT_NULL)
  492. };
  493. struct rt_can_filter_config cfg = {4, 1, items}; /* There are 4 filter tables in total */
  494. /* Set the hardware filter table. After setting, only frames with id=0x03 can be received*/
  495. res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
  496. RT_ASSERT(res == RT_EOK);
  497. #endif
  498. /* Create data receiving thread */
  499. thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 4096, 25, 10);
  500. if (thread != RT_NULL)
  501. {
  502. res = rt_thread_startup(thread);
  503. RT_ASSERT(res == RT_EOK);
  504. }
  505. else
  506. {
  507. rt_kprintf("Create can_rx thread failed.\n");
  508. }
  509. msg.id = 0x78; /* ID = 0x78 */
  510. msg.ide = RT_CAN_STDID; /* Standard format */
  511. msg.rtr = RT_CAN_DTR; /* Data frame */
  512. msg.len = 8; /* Data length is 8 */
  513. /* Send CAN data */
  514. for (int i = 0; i < 1; i++)
  515. {
  516. /* 8-byte data to be sent */
  517. msg.data[0] = 0x00 + i;
  518. msg.data[1] = 0x11 + i;
  519. msg.data[2] = 0x22 + i;
  520. msg.data[3] = 0x33 + i;
  521. msg.data[4] = 0x44 + i;
  522. msg.data[5] = 0x55 + i;
  523. msg.data[6] = 0x66 + i;
  524. msg.data[7] = 0x77 + i;
  525. rt_device_write(can_dev, 0, &msg, sizeof(msg));
  526. }
  527. return res;
  528. }
  529. /* Enter can_sample command for testing */
  530. MSH_CMD_EXPORT(can_sample, can device sample);
  531. #endif