drv_can.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. * Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-02-16 lik first version
  9. */
  10. #include "drv_can.h"
  11. #ifdef RT_USING_CAN
  12. #ifdef BSP_USING_CAN
  13. //#define DRV_DEBUG
  14. #define LOG_TAG "drv.can"
  15. #include <drv_log.h>
  16. #if !defined(BSP_USING_CAN0) && !defined(BSP_USING_CAN1)
  17. #error "Please define at least one BSP_USING_CANx"
  18. /* this driver can be disabled at menuconfig ? RT-Thread Components ? Device Drivers */
  19. #endif
  20. #ifdef BSP_USING_CAN0
  21. #ifndef CAN0_CFG
  22. #define CAN0_CFG \
  23. { \
  24. .name = "can0", \
  25. .CANx = CAN0, \
  26. }
  27. #endif /* CAN0_CFG */
  28. #endif /* BSP_USING_CAN0 */
  29. #ifdef BSP_USING_CAN1
  30. #ifndef CAN1_CFG
  31. #define CAN1_CFG \
  32. { \
  33. .name = "can1", \
  34. .CANx = CAN1, \
  35. }
  36. #endif /* CAN1_CFG */
  37. #endif /* BSP_USING_CAN1 */
  38. #define PRESCL_Pos 0
  39. #define BS1_Pos 16
  40. #define BS2_Pos 20
  41. #define SJW_Pos 24
  42. #define PRESCL_Msk (0x3FF << PRESCL_Pos)
  43. #define BS1_Msk ((0x0F) << BS1_Pos)
  44. #define BS2_Msk ((0x07) << BS2_Pos)
  45. #define SJW_Msk (0x3 << SJW_Pos)
  46. struct swm_baud_rate_tab
  47. {
  48. rt_uint32_t baud_rate;
  49. rt_uint32_t config_data;
  50. };
  51. #define BAUD_DATA(TYPE, NO) ((can_baud_rate_tab[NO].config_data & TYPE##_Msk) >> TYPE##_Pos)
  52. struct swm_can_cfg
  53. {
  54. const char *name;
  55. CAN_TypeDef *CANx;
  56. CAN_InitStructure CAN_initstruct;
  57. };
  58. struct swm_can_device
  59. {
  60. struct swm_can_cfg *can_cfg;
  61. struct rt_can_device can_device;
  62. };
  63. /* SystemCoreClock 152MHz(max) 150MHz不能生成CAN1MBaud */
  64. static const struct swm_baud_rate_tab can_baud_rate_tab[] =
  65. {
  66. {CAN1MBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (1 << PRESCL_Pos))},
  67. {CAN500kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (3 << PRESCL_Pos))},
  68. {CAN250kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (7 << PRESCL_Pos))},
  69. {CAN125kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (15 << PRESCL_Pos))},
  70. {CAN100kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (19 << PRESCL_Pos))},
  71. {CAN50kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (39 << PRESCL_Pos))},
  72. {CAN20kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (99 << PRESCL_Pos))},
  73. {CAN10kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (199 << PRESCL_Pos))}};
  74. enum
  75. {
  76. #ifdef BSP_USING_CAN0
  77. CAN0_INDEX,
  78. #endif
  79. #ifdef BSP_USING_CAN1
  80. CAN1_INDEX,
  81. #endif
  82. };
  83. static struct swm_can_cfg swm_can_cfg[] =
  84. {
  85. #ifdef BSP_USING_CAN0
  86. CAN0_CFG,
  87. #endif
  88. #ifdef BSP_USING_CAN1
  89. CAN1_CFG,
  90. #endif
  91. };
  92. static struct swm_can_device can_obj[sizeof(swm_can_cfg) / sizeof(swm_can_cfg[0])];
  93. static rt_uint32_t get_can_baud_index(rt_uint32_t baud)
  94. {
  95. rt_uint32_t len, index;
  96. len = sizeof(can_baud_rate_tab) / sizeof(can_baud_rate_tab[0]);
  97. for (index = 0; index < len; index++)
  98. {
  99. if (can_baud_rate_tab[index].baud_rate == baud)
  100. return index;
  101. }
  102. return 0; /* default baud is CAN1MBaud */
  103. }
  104. static rt_err_t swm_can_config(struct rt_can_device *can_device, struct can_configure *cfg)
  105. {
  106. struct swm_can_device *can_dev;
  107. rt_uint32_t baud_index;
  108. rt_uint32_t can_mode;
  109. RT_ASSERT(can_device);
  110. RT_ASSERT(cfg);
  111. can_dev = (struct swm_can_device *)can_device->parent.user_data;
  112. RT_ASSERT(can_dev);
  113. switch (cfg->mode)
  114. {
  115. case RT_CAN_MODE_NORMAL:
  116. can_mode = CAN_MODE_NORMAL;
  117. break;
  118. case RT_CAN_MODE_LISTEN:
  119. can_mode = CAN_MODE_LISTEN;
  120. break;
  121. case RT_CAN_MODE_LOOPBACK:
  122. can_mode = CAN_MODE_SELFTEST;
  123. break;
  124. case RT_CAN_MODE_LOOPBACKANLISTEN:
  125. can_mode = CAN_MODE_SELFTEST;
  126. break;
  127. }
  128. baud_index = get_can_baud_index(cfg->baud_rate);
  129. CAN_Close(can_dev->can_cfg->CANx); //一些关键寄存器只能在CAN关闭时设置
  130. can_dev->can_cfg->CANx->CR &= ~(CAN_CR_LOM_Msk | CAN_CR_STM_Msk);
  131. can_dev->can_cfg->CANx->CR |= (can_mode << CAN_CR_LOM_Pos);
  132. can_dev->can_cfg->CANx->BT1 = (0 << CAN_BT1_SAM_Pos) |
  133. (BAUD_DATA(BS1, baud_index) << CAN_BT1_TSEG1_Pos) |
  134. (BAUD_DATA(BS2, baud_index) << CAN_BT1_TSEG2_Pos);
  135. can_dev->can_cfg->CANx->BT0 = (BAUD_DATA(SJW, baud_index) << CAN_BT0_SJW_Pos) |
  136. ((BAUD_DATA(PRESCL, baud_index) & 0x3F) << CAN_BT0_BRP_Pos);
  137. can_dev->can_cfg->CANx->BT2 = ((BAUD_DATA(PRESCL, baud_index) >> 6) << CAN_BT2_BRP_Pos);
  138. can_dev->can_cfg->CANx->RXERR = 0; //只能在复位模式下清除
  139. can_dev->can_cfg->CANx->TXERR = 0;
  140. /* can start */
  141. CAN_Open(can_dev->can_cfg->CANx);
  142. return RT_EOK;
  143. }
  144. static rt_err_t swm_can_control(struct rt_can_device *can_device, int cmd, void *arg)
  145. {
  146. rt_uint32_t argval;
  147. struct swm_can_device *can_dev;
  148. struct rt_can_filter_config *filter_cfg;
  149. RT_ASSERT(can_device != RT_NULL);
  150. can_dev = (struct swm_can_device *)can_device->parent.user_data;
  151. RT_ASSERT(can_dev != RT_NULL);
  152. switch (cmd)
  153. {
  154. case RT_DEVICE_CTRL_CLR_INT:
  155. argval = (rt_uint32_t)arg;
  156. if (argval == RT_DEVICE_FLAG_INT_RX)
  157. {
  158. can_dev->can_cfg->CANx->IE &= ~(CAN_IE_RXDA_Msk | CAN_IE_RXOV_Msk);
  159. }
  160. else if (argval == RT_DEVICE_FLAG_INT_TX)
  161. {
  162. can_dev->can_cfg->CANx->IE &= ~CAN_IE_TXBR_Msk;
  163. }
  164. else if (argval == RT_DEVICE_CAN_INT_ERR)
  165. {
  166. can_dev->can_cfg->CANx->IE &= ~(CAN_IE_ARBLOST_Msk | CAN_IE_BUSERR_Msk | CAN_IE_ERRWARN_Msk | CAN_IE_ERRPASS_Msk);
  167. }
  168. break;
  169. case RT_DEVICE_CTRL_SET_INT:
  170. argval = (rt_uint32_t)arg;
  171. if (argval == RT_DEVICE_FLAG_INT_RX)
  172. {
  173. can_dev->can_cfg->CANx->IE |= (CAN_IE_RXDA_Msk | CAN_IE_RXOV_Msk);
  174. }
  175. else if (argval == RT_DEVICE_FLAG_INT_TX)
  176. {
  177. can_dev->can_cfg->CANx->IE |= CAN_IE_TXBR_Msk;
  178. }
  179. else if (argval == RT_DEVICE_CAN_INT_ERR)
  180. {
  181. can_dev->can_cfg->CANx->IE |= (CAN_IE_ARBLOST_Msk | CAN_IE_BUSERR_Msk | CAN_IE_ERRWARN_Msk | CAN_IE_ERRPASS_Msk);
  182. }
  183. break;
  184. case RT_CAN_CMD_SET_FILTER:
  185. {
  186. rt_uint32_t filter_idx = 0;
  187. if (RT_NULL == arg)
  188. {
  189. /* default filter config */
  190. }
  191. else
  192. {
  193. filter_cfg = (struct rt_can_filter_config *)arg;
  194. /* get default filter */
  195. for (int i = 0; i < filter_cfg->count; i++)
  196. {
  197. if (filter_cfg->items[i].hdr_bank == -1)
  198. {
  199. filter_idx = i;
  200. }
  201. else
  202. {
  203. filter_idx = filter_cfg->items[i].hdr_bank;
  204. }
  205. if (filter_cfg->items[i].ide == RT_CAN_STDID)
  206. {
  207. can_dev->can_cfg->CANx->AFM &= ~(1 << filter_idx);
  208. can_dev->can_cfg->CANx->ACR[filter_idx] = __REV(filter_cfg->items[i].id << 5);
  209. can_dev->can_cfg->CANx->AMR[filter_idx] = __REV(~(filter_cfg->items[i].mask << 5));
  210. can_dev->can_cfg->CANx->AFE |= (1 << filter_idx);
  211. }
  212. else if (filter_cfg->items[i].ide == RT_CAN_EXTID)
  213. {
  214. can_dev->can_cfg->CANx->AFM |= (1 << filter_idx);
  215. can_dev->can_cfg->CANx->ACR[filter_idx] = __REV(filter_cfg->items[i].id << 3);
  216. can_dev->can_cfg->CANx->AMR[filter_idx] = __REV(~(filter_cfg->items[i].mask << 3));
  217. can_dev->can_cfg->CANx->AFE |= (1 << filter_idx);
  218. }
  219. }
  220. }
  221. break;
  222. }
  223. case RT_CAN_CMD_SET_MODE:
  224. argval = (rt_uint32_t)arg;
  225. if (argval != RT_CAN_MODE_NORMAL &&
  226. argval != RT_CAN_MODE_LISTEN &&
  227. argval != RT_CAN_MODE_LOOPBACK &&
  228. argval != RT_CAN_MODE_LOOPBACKANLISTEN)
  229. {
  230. return -RT_ERROR;
  231. }
  232. if (argval != can_dev->can_device.config.mode)
  233. {
  234. can_dev->can_device.config.mode = argval;
  235. return swm_can_config(&can_dev->can_device, &can_dev->can_device.config);
  236. }
  237. break;
  238. case RT_CAN_CMD_SET_BAUD:
  239. argval = (rt_uint32_t)arg;
  240. if (argval != CAN1MBaud &&
  241. argval != CAN800kBaud &&
  242. argval != CAN500kBaud &&
  243. argval != CAN250kBaud &&
  244. argval != CAN125kBaud &&
  245. argval != CAN100kBaud &&
  246. argval != CAN50kBaud &&
  247. argval != CAN20kBaud &&
  248. argval != CAN10kBaud)
  249. {
  250. return -RT_ERROR;
  251. }
  252. if (argval != can_dev->can_device.config.baud_rate)
  253. {
  254. can_dev->can_device.config.baud_rate = argval;
  255. return swm_can_config(&can_dev->can_device, &can_dev->can_device.config);
  256. }
  257. break;
  258. case RT_CAN_CMD_SET_PRIV:
  259. argval = (rt_uint32_t)arg;
  260. if (argval != RT_CAN_MODE_PRIV &&
  261. argval != RT_CAN_MODE_NOPRIV)
  262. {
  263. return -RT_ERROR;
  264. }
  265. if (argval != can_dev->can_device.config.privmode)
  266. {
  267. can_dev->can_device.config.privmode = argval;
  268. return swm_can_config(&can_dev->can_device, &can_dev->can_device.config);
  269. }
  270. break;
  271. case RT_CAN_CMD_GET_STATUS:
  272. {
  273. can_dev->can_device.status.rcverrcnt = can_dev->can_cfg->CANx->RXERR;
  274. can_dev->can_device.status.snderrcnt = can_dev->can_cfg->CANx->TXERR;
  275. can_dev->can_device.status.lasterrtype = (can_dev->can_cfg->CANx->ECC >> 6) & 0x03;
  276. can_dev->can_device.status.errcode = can_dev->can_cfg->CANx->ECC & 0x1F;
  277. rt_memcpy(arg, &can_dev->can_device.status, sizeof(can_dev->can_device.status));
  278. }
  279. break;
  280. }
  281. return RT_EOK;
  282. }
  283. static int swm_can_sendmsg(struct rt_can_device *can_device, const void *buf, rt_uint32_t box_num)
  284. {
  285. uint32_t i;
  286. struct swm_can_device *can_dev;
  287. RT_ASSERT(can_device != RT_NULL);
  288. can_dev = (struct swm_can_device *)can_device->parent.user_data;
  289. struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
  290. if (RT_CAN_STDID == pmsg->ide)
  291. {
  292. can_dev->can_cfg->CANx->FRAME.DATA[0] = pmsg->id >> 3;
  293. can_dev->can_cfg->CANx->FRAME.DATA[1] = pmsg->id << 5;
  294. if (RT_CAN_DTR == pmsg->rtr)
  295. {
  296. can_dev->can_cfg->CANx->FRAME.INFO = (0 << CAN_INFO_FF_Pos) |
  297. (0 << CAN_INFO_RTR_Pos) |
  298. (pmsg->len << CAN_INFO_DLC_Pos);
  299. for(i = 0; i < pmsg->len; i++)
  300. {
  301. can_dev->can_cfg->CANx->FRAME.DATA[i+2] = pmsg->data[i];
  302. }
  303. if(can_dev->can_cfg->CANx->CR & CAN_CR_STM_Msk)
  304. {
  305. can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_SRR_Pos);
  306. }
  307. else
  308. {
  309. can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_TXREQ_Pos);
  310. }
  311. }
  312. else
  313. {
  314. can_dev->can_cfg->CANx->FRAME.INFO = (0 << CAN_INFO_FF_Pos) |
  315. (1 << CAN_INFO_RTR_Pos) |
  316. (0 << CAN_INFO_DLC_Pos);
  317. can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_TXREQ_Pos);
  318. }
  319. }
  320. else
  321. {
  322. can_dev->can_cfg->CANx->FRAME.DATA[0] = pmsg->id >> 21;
  323. can_dev->can_cfg->CANx->FRAME.DATA[1] = pmsg->id >> 13;
  324. can_dev->can_cfg->CANx->FRAME.DATA[2] = pmsg->id >> 5;
  325. can_dev->can_cfg->CANx->FRAME.DATA[3] = pmsg->id << 3;
  326. if (RT_CAN_DTR == pmsg->rtr)
  327. {
  328. can_dev->can_cfg->CANx->FRAME.INFO = (1 << CAN_INFO_FF_Pos) |
  329. (0 << CAN_INFO_RTR_Pos) |
  330. (pmsg->len << CAN_INFO_DLC_Pos);
  331. for(i = 0; i < pmsg->len; i++)
  332. {
  333. can_dev->can_cfg->CANx->FRAME.DATA[i+4] = pmsg->data[i];
  334. }
  335. if(can_dev->can_cfg->CANx->CR & CAN_CR_STM_Msk)
  336. {
  337. can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_SRR_Pos);
  338. }
  339. else
  340. {
  341. can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_TXREQ_Pos);
  342. }
  343. }
  344. else
  345. {
  346. can_dev->can_cfg->CANx->FRAME.INFO = (1 << CAN_INFO_FF_Pos) |
  347. (1 << CAN_INFO_RTR_Pos) |
  348. (0 << CAN_INFO_DLC_Pos);
  349. can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_TXREQ_Pos);
  350. }
  351. }
  352. return RT_EOK;
  353. }
  354. static int swm_can_recvmsg(struct rt_can_device *can_device, void *buf, rt_uint32_t fifo)
  355. {
  356. uint32_t i;
  357. struct swm_can_device *can_dev;
  358. RT_ASSERT(can_device != RT_NULL);
  359. can_dev = (struct swm_can_device *)can_device->parent.user_data;
  360. struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
  361. CAN_RXMessage CAN_RXMsg;
  362. /* get data */
  363. CAN_Receive(can_dev->can_cfg->CANx, &CAN_RXMsg);
  364. /* get id */
  365. if (CAN_RXMsg.format == CAN_FRAME_STD)
  366. {
  367. pmsg->ide = RT_CAN_STDID;
  368. }
  369. else
  370. {
  371. pmsg->ide = RT_CAN_EXTID;
  372. }
  373. pmsg->id = CAN_RXMsg.id;
  374. /* get type */
  375. if (CAN_RXMsg.remote == 0)
  376. {
  377. pmsg->rtr = RT_CAN_DTR;
  378. }
  379. else
  380. {
  381. pmsg->rtr = RT_CAN_RTR;
  382. }
  383. /* get len */
  384. pmsg->len = CAN_RXMsg.size;
  385. for(i = 0; i < pmsg->len; i++)
  386. {
  387. pmsg->data[i] = CAN_RXMsg.data[i];
  388. }
  389. return RT_EOK;
  390. }
  391. static const struct rt_can_ops swm_can_ops =
  392. {
  393. .configure = swm_can_config,
  394. .control = swm_can_control,
  395. .sendmsg = swm_can_sendmsg,
  396. .recvmsg = swm_can_recvmsg,
  397. };
  398. static void swm_can_isr(struct rt_can_device *can_device)
  399. {
  400. struct swm_can_device *can_dev;
  401. RT_ASSERT(can_device != RT_NULL);
  402. can_dev = (struct swm_can_device *)can_device->parent.user_data;
  403. uint32_t int_sr = CAN_INTStat(can_dev->can_cfg->CANx);
  404. if(int_sr & CAN_IF_RXDA_Msk)
  405. {
  406. rt_hw_can_isr(can_device, RT_CAN_EVENT_RX_IND);
  407. }
  408. else if (int_sr & CAN_IF_RXOV_Msk)
  409. {
  410. rt_hw_can_isr(can_device, RT_CAN_EVENT_RXOF_IND);
  411. }
  412. else if (int_sr & CAN_IF_TXBR_Msk)
  413. {
  414. rt_hw_can_isr(can_device, RT_CAN_EVENT_TX_DONE);
  415. }
  416. else if (int_sr & CAN_IE_ERRWARN_Msk)
  417. {
  418. }
  419. else if (int_sr & CAN_IE_ERRPASS_Msk)
  420. {
  421. }
  422. else if (int_sr & CAN_IE_ARBLOST_Msk)
  423. {
  424. }
  425. else if (int_sr & CAN_IE_BUSERR_Msk)
  426. {
  427. }
  428. }
  429. #ifdef BSP_USING_CAN0
  430. /**
  431. * @brief This function handles CAN0 interrupts.
  432. */
  433. void CAN0_Handler(void)
  434. {
  435. rt_interrupt_enter();
  436. swm_can_isr(&(can_obj[CAN0_INDEX].can_device));
  437. rt_interrupt_leave();
  438. }
  439. #endif /* BSP_USING_CAN0 */
  440. #ifdef BSP_USING_CAN1
  441. /**
  442. * @brief This function handles CAN1 interrupts.
  443. */
  444. void CAN1_Handler(void)
  445. {
  446. rt_interrupt_enter();
  447. swm_can_isr(&(can_obj[CAN0_INDEX].can_device));
  448. rt_interrupt_leave();
  449. }
  450. #endif /* BSP_USING_CAN1 */
  451. int swm_can_init(void)
  452. {
  453. int i = 0;
  454. int result = RT_EOK;
  455. struct can_configure config = CANDEFAULTCONFIG;
  456. config.privmode = RT_CAN_MODE_NOPRIV;
  457. config.ticks = 50;
  458. #ifdef RT_CAN_USING_HDR
  459. config.maxhdr = 16;
  460. #endif
  461. #ifdef BSP_USING_CAN0
  462. PORT_Init(PORTB, PIN5, PORTB_PIN5_CAN0_RX, 1);
  463. PORT_Init(PORTB, PIN4, PORTB_PIN4_CAN0_TX, 0);
  464. SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_CAN0_Pos);
  465. NVIC_EnableIRQ(CAN0_IRQn);
  466. #endif
  467. #ifdef BSP_USING_CAN1
  468. PORT_Init(PORTB, PIN3, PORTB_PIN3_CAN1_RX, 1);
  469. PORT_Init(PORTB, PIN2, PORTB_PIN2_CAN1_TX, 0);
  470. SYS->CLKEN1 |= (0x01 << SYS_CLKEN1_CAN1_Pos);
  471. NVIC_EnableIRQ(CAN1_IRQn);
  472. #endif
  473. for (i = 0; i < sizeof(swm_can_cfg) / sizeof(swm_can_cfg[0]); i++)
  474. {
  475. can_obj[i].can_device.config = config;
  476. can_obj[i].can_cfg = &swm_can_cfg[i];
  477. result = rt_hw_can_register(&can_obj[i].can_device,
  478. can_obj[i].can_cfg->name,
  479. &swm_can_ops,
  480. &can_obj[i]);
  481. if (result != RT_EOK)
  482. {
  483. LOG_E("%s register fail.", can_obj[i].can_cfg->name);
  484. }
  485. else
  486. {
  487. LOG_D("%s register success.", can_obj[i].can_cfg->name);
  488. }
  489. }
  490. return result;
  491. return 0;
  492. }
  493. INIT_BOARD_EXPORT(swm_can_init);
  494. #endif /* BSP_USING_CAN */
  495. #endif /* RT_USING_CAN */