drv_can.c 15 KB

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