drv_can.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-2-07 ChingI First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_CAN)
  14. #include <rtdevice.h>
  15. #include <rthw.h>
  16. #include <NuMicro.h>
  17. /* Private Define ---------------------------------------------------------------*/
  18. #define RX_MSG_ID_INDEX 16
  19. #define IS_CAN_STDID(STDID) ((STDID) <= 0x7FFU)
  20. #define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU)
  21. #define IS_CAN_DLC(DLC) ((DLC) <= 8U)
  22. /* Default config for serial_configure structure */
  23. #define NU_CAN_CONFIG_DEFAULT \
  24. { \
  25. CAN1MBaud, /* 1M bits/s */ \
  26. RT_CANMSG_BOX_SZ, /* message box max size */ \
  27. RT_CANSND_BOX_NUM, /* message box number */ \
  28. RT_CAN_MODE_NORMAL, /* Normal mode */ \
  29. 0, /* privmode */ \
  30. 0, /* reserved */ \
  31. 100, /* Timeout Tick */ \
  32. }
  33. enum
  34. {
  35. CAN_START = -1,
  36. #if defined(BSP_USING_CAN0)
  37. CAN0_IDX,
  38. #endif
  39. #if defined(BSP_USING_CAN1)
  40. CAN1_IDX,
  41. #endif
  42. #if defined(BSP_USING_CAN2)
  43. CAN2_IDX,
  44. #endif
  45. CAN_CNT
  46. };
  47. /* Private Typedef --------------------------------------------------------------*/
  48. struct nu_can
  49. {
  50. struct rt_can_device dev;
  51. char *name;
  52. CAN_T *can_base;
  53. uint32_t can_rst;
  54. IRQn_Type can_irq_n;
  55. };
  56. typedef struct nu_can *nu_can_t;
  57. /* Private functions ------------------------------------------------------------*/
  58. static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg);
  59. static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg);
  60. static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno);
  61. static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno);
  62. static void nu_can_isr(nu_can_t can);
  63. static struct nu_can nu_can_arr[] =
  64. {
  65. #if defined(BSP_USING_CAN0)
  66. {
  67. .name = "can0",
  68. .can_base = CAN0,
  69. .can_rst = CAN0_RST,
  70. .can_irq_n = CAN0_IRQn,
  71. },
  72. #endif
  73. #if defined(BSP_USING_CAN1)
  74. {
  75. .name = "can1",
  76. .can_base = CAN1,
  77. .can_rst = CAN1_RST,
  78. .can_irq_n = CAN1_IRQn,
  79. },
  80. #endif
  81. #if defined(BSP_USING_CAN2)
  82. {
  83. .name = "can2",
  84. .can_base = CAN2,
  85. .can_rst = CAN2_RST,
  86. .can_irq_n = CAN2_IRQn,
  87. },
  88. #endif
  89. {0}
  90. }; /* struct nu_can */
  91. /* Public functions ------------------------------------------------------------*/
  92. /* Private variables ------------------------------------------------------------*/
  93. static const struct rt_can_ops nu_can_ops =
  94. {
  95. .configure = nu_can_configure,
  96. .control = nu_can_control,
  97. .sendmsg = nu_can_sendmsg,
  98. .recvmsg = nu_can_recvmsg,
  99. };
  100. static const struct can_configure nu_can_default_config = NU_CAN_CONFIG_DEFAULT;
  101. /* Interrupt Handle Function ----------------------------------------------------*/
  102. #if defined(BSP_USING_CAN0)
  103. /* CAN0 interrupt entry */
  104. void CAN0_IRQHandler(void)
  105. {
  106. /* enter interrupt */
  107. rt_interrupt_enter();
  108. nu_can_isr(&nu_can_arr[CAN0_IDX]);
  109. /* leave interrupt */
  110. rt_interrupt_leave();
  111. }
  112. #endif
  113. #if defined(BSP_USING_CAN1)
  114. /* CAN1 interrupt entry */
  115. void CAN1_IRQHandler(void)
  116. {
  117. /* enter interrupt */
  118. rt_interrupt_enter();
  119. nu_can_isr(&nu_can_arr[CAN1_IDX]);
  120. /* leave interrupt */
  121. rt_interrupt_leave();
  122. }
  123. #endif
  124. #if defined(BSP_USING_CAN2)
  125. /* CAN2 interrupt entry */
  126. void CAN2_IRQHandler(void)
  127. {
  128. /* enter interrupt */
  129. rt_interrupt_enter();
  130. nu_can_isr(&nu_can_arr[CAN2_IDX]);
  131. /* leave interrupt */
  132. rt_interrupt_leave();
  133. }
  134. #endif
  135. /* Private Variables ------------------------------------------------------------*/
  136. static void nu_can_isr(nu_can_t can)
  137. {
  138. uint32_t u32IIDRstatus;
  139. /* Get base address of CAN register */
  140. CAN_T *can_base = ((nu_can_t)can)->can_base;
  141. /* Get interrupt event */
  142. u32IIDRstatus = can_base->IIDR;
  143. if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */
  144. {
  145. /**************************/
  146. /* Status Change interrupt*/
  147. /**************************/
  148. if (can_base->STATUS & CAN_STATUS_RXOK_Msk)
  149. {
  150. #ifndef RT_CAN_USING_HDR
  151. /* Using as Lisen,Loopback,Loopback+Lisen mode*/
  152. rt_hw_can_isr(&can->dev, RT_CAN_EVENT_RX_IND);
  153. #endif
  154. can_base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/
  155. rt_kprintf("RX OK INT\n") ;
  156. }
  157. if (can_base->STATUS & CAN_STATUS_TXOK_Msk)
  158. {
  159. #ifndef RT_CAN_USING_HDR
  160. /* Using as Lisen,Loopback,Loopback+Lisen mode*/
  161. rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE);
  162. #endif
  163. can_base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/
  164. rt_kprintf("TX OK INT\n") ;
  165. }
  166. /**************************/
  167. /* Error Status interrupt */
  168. /**************************/
  169. if (can_base->STATUS & CAN_STATUS_EWARN_Msk)
  170. {
  171. rt_kprintf("EWARN INT\n") ;
  172. }
  173. if (can_base->STATUS & CAN_STATUS_BOFF_Msk)
  174. {
  175. rt_kprintf("BOFF INT\n") ;
  176. /* Do Init to release busoff pin */
  177. can_base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk);
  178. can_base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk));
  179. while (can_base->CON & CAN_CON_INIT_Msk);
  180. }
  181. }
  182. #ifdef RT_CAN_USING_HDR
  183. /*Number of Message Object which caused the interrupt*/
  184. else if (u32IIDRstatus != 0 && u32IIDRstatus <= 32)
  185. {
  186. rt_kprintf("=> Interrupt Pointer = %d\n", can_base->IIDR - 1);
  187. /*Message RAM 0~15 for CAN Tx using*/
  188. if (u32IIDRstatus < 16)
  189. rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE);
  190. else /*Message RAM 16~31 for CAN Rx using*/
  191. {
  192. rt_hw_can_isr(&can->dev, (RT_CAN_EVENT_RX_IND | (((can_base->IIDR) - 1) << 8)));
  193. }
  194. CAN_CLR_INT_PENDING_BIT(can_base, ((can_base->IIDR) - 1)); /* Clear Interrupt Pending */
  195. }
  196. #endif
  197. }
  198. static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg)
  199. {
  200. RT_ASSERT(can != RT_NULL);
  201. RT_ASSERT(cfg != RT_NULL);
  202. /* Get base address of CAN register */
  203. CAN_T *can_base = ((nu_can_t)can)->can_base;
  204. RT_ASSERT(can_base != RT_NULL);
  205. /* Reset this module */
  206. SYS_ResetModule(((nu_can_t)can)->can_rst);
  207. switch (cfg->mode)
  208. {
  209. /* CAN default Normal mode */
  210. case RT_CAN_MODE_NORMAL:
  211. can->config.mode = CAN_NORMAL_MODE;
  212. break;
  213. case RT_CAN_MODE_LISEN:
  214. can->config.mode = RT_CAN_MODE_LISEN;
  215. break;
  216. case RT_CAN_MODE_LOOPBACK:
  217. can->config.mode = RT_CAN_MODE_LOOPBACK;
  218. break;
  219. case RT_CAN_MODE_LOOPBACKANLISEN:
  220. can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN;
  221. break;
  222. default:
  223. rt_kprintf("Unsupported Operating mode");
  224. goto exit_nu_can_configure;
  225. }
  226. /*Set the CAN Bit Rate and Operating mode*/
  227. if (CAN_Open(can_base, can->config.baud_rate, can->config.mode) < 1)
  228. return -(RT_ERROR);
  229. switch (cfg->mode)
  230. {
  231. /* CAN default Normal mode */
  232. case RT_CAN_MODE_NORMAL:
  233. #ifdef RT_CAN_USING_HDR
  234. CAN_LeaveTestMode(can_base);
  235. #else
  236. CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk);
  237. #endif
  238. break;
  239. case RT_CAN_MODE_LISEN:
  240. CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk);
  241. break;
  242. case RT_CAN_MODE_LOOPBACK:
  243. CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk);
  244. break;
  245. case RT_CAN_MODE_LOOPBACKANLISEN:
  246. CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk);
  247. break;
  248. default:
  249. rt_kprintf("Unsupported Operating mode");
  250. goto exit_nu_can_configure;
  251. }
  252. return RT_EOK;
  253. exit_nu_can_configure:
  254. CAN_Close(can_base);
  255. return -(RT_ERROR);
  256. }
  257. static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg)
  258. {
  259. rt_uint32_t argval;
  260. #ifdef RT_CAN_USING_HDR
  261. struct rt_can_filter_config *filter_cfg;
  262. #endif
  263. /* Get base address of CAN register */
  264. CAN_T *can_base = ((nu_can_t)can)->can_base;
  265. RT_ASSERT(can_base != RT_NULL);
  266. /* Check baudrate */
  267. RT_ASSERT(can->config.baud_rate != 0);
  268. switch (cmd)
  269. {
  270. case RT_DEVICE_CTRL_CLR_INT:
  271. argval = (rt_uint32_t) arg;
  272. if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX))
  273. {
  274. /* Disable NVIC interrupt. */
  275. NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n);
  276. /* Disable Status Change Interrupt */
  277. CAN_DisableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk);
  278. }
  279. else if (argval == RT_DEVICE_CAN_INT_ERR)
  280. {
  281. /* Disable NVIC interrupt. */
  282. NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n);
  283. /* Disable Error Interrupt */
  284. CAN_DisableInt(can_base, CAN_CON_EIE_Msk);
  285. }
  286. break;
  287. case RT_DEVICE_CTRL_SET_INT:
  288. argval = (rt_uint32_t) arg;
  289. if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX))
  290. {
  291. /* Enable Status Change Interrupt */
  292. CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk);
  293. /* Enable NVIC interrupt. */
  294. NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n);
  295. }
  296. else if (argval == RT_DEVICE_CAN_INT_ERR)
  297. {
  298. /* Enable Error Status and Status Change Interrupt */
  299. CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
  300. /* Enable NVIC interrupt. */
  301. NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n);
  302. }
  303. break;
  304. case RT_CAN_CMD_SET_FILTER:
  305. #ifdef RT_CAN_USING_HDR
  306. filter_cfg = (struct rt_can_filter_config *)arg;
  307. for (int i = 0; i < filter_cfg->count; i++)
  308. {
  309. /*set the filter message object*/
  310. if (filter_cfg->items[i].mode == 1)
  311. {
  312. if (CAN_SetRxMsgObjAndMsk(can_base, MSG(i + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE)
  313. {
  314. return -(RT_ERROR);
  315. }
  316. }
  317. else
  318. {
  319. /*set the filter message object*/
  320. if (CAN_SetRxMsgAndMsk(can_base, MSG(i + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE)
  321. {
  322. return -(RT_ERROR);
  323. }
  324. }
  325. }
  326. #endif
  327. break;
  328. case RT_CAN_CMD_SET_MODE:
  329. argval = (rt_uint32_t) arg;
  330. if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN &&
  331. argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN)
  332. {
  333. return -(RT_ERROR);
  334. }
  335. if (argval != can->config.mode)
  336. {
  337. can->config.mode = argval;
  338. return nu_can_configure(can, &can->config);
  339. }
  340. break;
  341. case RT_CAN_CMD_SET_BAUD:
  342. argval = (rt_uint32_t) arg;
  343. if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud &&
  344. argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud)
  345. {
  346. return -(RT_ERROR);
  347. }
  348. if (argval != can->config.baud_rate)
  349. {
  350. can->config.baud_rate = argval;
  351. return nu_can_configure(can, &can->config);
  352. }
  353. break;
  354. case RT_CAN_CMD_SET_PRIV:
  355. argval = (rt_uint32_t) arg;
  356. if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV)
  357. {
  358. return -(RT_ERROR);
  359. }
  360. if (argval != can->config.privmode)
  361. {
  362. can->config.privmode = argval;
  363. return nu_can_configure(can, &can->config);
  364. }
  365. break;
  366. case RT_CAN_CMD_GET_STATUS:
  367. {
  368. rt_uint32_t errtype;
  369. errtype = can_base->ERR;
  370. /*Receive Error Counter*/
  371. can->status.rcverrcnt = (errtype >> 8);
  372. /*Transmit Error Counter*/
  373. can->status.snderrcnt = ((errtype >> 24) & 0xFF);
  374. can->status.lasterrtype = CAN_GET_INT_STATUS(can_base) & 0x8000;
  375. /*status error code*/
  376. can->status.errcode = CAN_GET_INT_STATUS(can_base) & 0x07;
  377. rt_memcpy(arg, &can->status, sizeof(can->status));
  378. }
  379. break;
  380. default:
  381. return -(RT_EINVAL);
  382. }
  383. return RT_EOK;
  384. }
  385. static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno)
  386. {
  387. STR_CANMSG_T tMsg;
  388. struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
  389. /* Get base address of CAN register */
  390. CAN_T *can_base = ((nu_can_t)can)->can_base;
  391. RT_ASSERT(can_base != RT_NULL);
  392. RT_ASSERT(buf != RT_NULL);
  393. /* Check the parameters */
  394. RT_ASSERT(IS_CAN_DLC(pmsg->len));
  395. /* Standard ID (11 bits)*/
  396. if (pmsg->ide == RT_CAN_STDID)
  397. {
  398. tMsg.IdType = CAN_STD_ID;
  399. RT_ASSERT(IS_CAN_STDID(pmsg->id))
  400. tMsg.Id = pmsg->id ;
  401. }
  402. else
  403. {
  404. /* Extended ID (29 bits)*/
  405. tMsg.IdType = CAN_EXT_ID;
  406. RT_ASSERT(IS_CAN_EXTID(pmsg->id));
  407. tMsg.Id = pmsg->id ;
  408. }
  409. if (pmsg->rtr == RT_CAN_DTR)
  410. {
  411. /* Data frame */
  412. tMsg.FrameType = CAN_DATA_FRAME;
  413. }
  414. else
  415. {
  416. /* Remote frame */
  417. tMsg.FrameType = CAN_REMOTE_FRAME;
  418. }
  419. tMsg.DLC = pmsg->len;
  420. rt_memcpy(tMsg.Data, pmsg->data, pmsg->len);
  421. if (CAN_Transmit(can_base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM
  422. {
  423. return -(RT_ERROR);
  424. }
  425. return RT_EOK;
  426. }
  427. static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno)
  428. {
  429. STR_CANMSG_T tMsg;
  430. struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
  431. /* Get base address of CAN register */
  432. CAN_T *can_base = ((nu_can_t)can)->can_base;
  433. RT_ASSERT(can_base != RT_NULL);
  434. RT_ASSERT(buf != RT_NULL);
  435. /* get data */
  436. CAN_Receive(can_base, boxno, &tMsg);
  437. #ifdef RT_CAN_USING_HDR
  438. /* Hardware filter messages are valid */
  439. can->hdr->connected = 1;
  440. #endif
  441. /* Standard ID (11 bits)*/
  442. if (tMsg.IdType == CAN_STD_ID)
  443. {
  444. pmsg->ide = RT_CAN_STDID;
  445. pmsg->id = tMsg.Id;
  446. }
  447. else /* Extended ID (29 bits)*/
  448. {
  449. pmsg->ide = RT_CAN_EXTID;
  450. pmsg->id = tMsg.Id;
  451. }
  452. if (tMsg.FrameType == CAN_DATA_FRAME)
  453. {
  454. /* Data frame */
  455. pmsg->rtr = RT_CAN_DTR;
  456. }
  457. else
  458. {
  459. /* Remote frame */
  460. pmsg->rtr = RT_CAN_RTR;
  461. }
  462. pmsg->len = tMsg.DLC ;
  463. rt_memcpy(pmsg->data, tMsg.Data, pmsg->len);
  464. return RT_EOK;
  465. }
  466. /**
  467. * Hardware CAN Initialization
  468. */
  469. static int rt_hw_can_init(void)
  470. {
  471. int i;
  472. rt_err_t ret = RT_EOK;
  473. for (i = (CAN_START + 1); i < CAN_CNT; i++)
  474. {
  475. nu_can_arr[i].dev.ops = &nu_can_ops;
  476. nu_can_arr[i].dev.config = nu_can_default_config;
  477. #ifdef RT_CAN_USING_HDR
  478. nu_can_arr[i].dev.config.maxhdr = RT_CANMSG_BOX_SZ;
  479. #endif
  480. ret = rt_hw_can_register(&nu_can_arr[i].dev, nu_can_arr[i].name, &nu_can_ops, NULL);
  481. RT_ASSERT(ret == RT_EOK);
  482. }
  483. return (int)ret;
  484. }
  485. INIT_DEVICE_EXPORT(rt_hw_can_init);
  486. #endif //#if defined(BSP_USING_CAN)