drv_can.c 15 KB

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