drv_canfd.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  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. * 2022-4-27 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_CANFD)
  14. #include <rtdevice.h>
  15. #include <rthw.h>
  16. #include "drv_sys.h"
  17. #include "drv_common.h"
  18. #include "nu_bitutil.h"
  19. #define LOG_TAG "drv.canfd"
  20. #undef DBG_ENABLE
  21. #define DBG_SECTION_NAME LOG_TAG
  22. #define DBG_LEVEL LOG_LVL_ERROR
  23. #define DBG_COLOR
  24. #include <rtdbg.h>
  25. /* Private Define ---------------------------------------------------------------*/
  26. #define IS_CAN_STDID(STDID) ((STDID) <= 0x7FFU)
  27. #define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU)
  28. #define IS_CAN_DLC(DLC) ((DLC) <= 8U)
  29. /* Default config for serial_configure structure */
  30. #define NU_CANFD_CONFIG_DEFAULT \
  31. { \
  32. CAN1MBaud, /* 1M bits/s */ \
  33. RT_CANMSG_BOX_SZ, /* message box max size */ \
  34. RT_CANSND_BOX_NUM, /* message box number */ \
  35. RT_CAN_MODE_NORMAL, /* Normal mode */ \
  36. 0, /* privmode */ \
  37. 0, /* reserved */ \
  38. 100, /* Timeout Tick */ \
  39. }
  40. enum
  41. {
  42. CANFD_START = -1,
  43. #if defined(BSP_USING_CANFD0)
  44. CANFD0_IDX,
  45. #endif
  46. #if defined(BSP_USING_CANFD1)
  47. CANFD1_IDX,
  48. #endif
  49. #if defined(BSP_USING_CANFD2)
  50. CANFD2_IDX,
  51. #endif
  52. #if defined(BSP_USING_CANFD3)
  53. CANFD3_IDX,
  54. #endif
  55. CANFD_CNT
  56. };
  57. /* Private Typedef --------------------------------------------------------------*/
  58. struct nu_canfd
  59. {
  60. struct rt_can_device dev;
  61. char *name;
  62. CANFD_T *base;
  63. uint32_t rstidx;
  64. IRQn_Type irqn0;
  65. IRQn_Type irqn1;
  66. uint32_t int_flag;
  67. CANFD_FD_T sCANFD_Config;
  68. };
  69. typedef struct nu_canfd *nu_canfd_t;
  70. /* Private functions ------------------------------------------------------------*/
  71. static rt_err_t nu_canfd_configure(struct rt_can_device *can, struct can_configure *cfg);
  72. static rt_err_t nu_canfd_control(struct rt_can_device *can, int cmd, void *arg);
  73. static int nu_canfd_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno);
  74. static int nu_canfd_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno);
  75. static struct nu_canfd nu_canfd_arr[] =
  76. {
  77. #if defined(BSP_USING_CANFD0)
  78. {
  79. .name = "canfd0",
  80. .base = CANFD0,
  81. .rstidx = CANFD0_RST,
  82. .irqn0 = CANFD00_IRQn,
  83. .irqn1 = CANFD01_IRQn,
  84. },
  85. #endif
  86. #if defined(BSP_USING_CANFD1)
  87. {
  88. .name = "canfd1",
  89. .base = CANFD1,
  90. .rstidx = CANFD1_RST,
  91. .irqn0 = CANFD10_IRQn,
  92. .irqn1 = CANFD11_IRQn,
  93. },
  94. #endif
  95. #if defined(BSP_USING_CANFD2)
  96. {
  97. .name = "canfd2",
  98. .base = CANFD2,
  99. .rstidx = CANFD2_RST,
  100. .irqn0 = CANFD20_IRQn,
  101. .irqn1 = CANFD21_IRQn,
  102. },
  103. #endif
  104. #if defined(BSP_USING_CANFD3)
  105. {
  106. .name = "canfd3",
  107. .base = CANFD3,
  108. .rstidx = CANFD3_RST,
  109. .irqn0 = CANFD30_IRQn,
  110. .irqn1 = CANFD31_IRQn,
  111. },
  112. #endif
  113. }; /* struct nu_can */
  114. /* Public functions ------------------------------------------------------------*/
  115. /* Private variables ------------------------------------------------------------*/
  116. static const struct rt_can_ops nu_canfd_ops =
  117. {
  118. .configure = nu_canfd_configure,
  119. .control = nu_canfd_control,
  120. .sendmsg = nu_canfd_sendmsg,
  121. .recvmsg = nu_canfd_recvmsg,
  122. };
  123. static const struct can_configure nu_canfd_default_config = NU_CANFD_CONFIG_DEFAULT;
  124. /* Interrupt Handle Function ----------------------------------------------------*/
  125. /* Private Variables ------------------------------------------------------------*/
  126. const char *szIR[] =
  127. {
  128. "CANFD_IR_RF0N - Rx FIFO 0 New Message",
  129. "CANFD_IR_RF0W - Rx FIFO 0 Watermark Reached",
  130. "CANFD_IR_RF0F - Rx FIFO 0 Full",
  131. "CANFD_IR_RF0L - Rx FIFO 0 Message Lost",
  132. "CANFD_IR_RF1N - Rx FIFO 1 New Message",
  133. "CANFD_IR_RF1W - Rx FIFO 1 Watermark Reached",
  134. "CANFD_IR_RF1F - Rx FIFO 1 Full",
  135. "CANFD_IR_RF1L - Rx FIFO 1 Message Lost",
  136. "CANFD_IR_HPM - High Priority Message",
  137. "CANFD_IR_TC - Transmission Completed",
  138. "CANFD_IR_TCF - Transmission Cancellation Finished",
  139. "CANFD_IR_TFE - Tx FIFO Empty",
  140. "CANFD_IR_TEFN - Tx Event FIFO New Entry",
  141. "CANFD_IR_TEFW - Tx Event FIFO Watermark Reached",
  142. "CANFD_IR_TEFF - Tx Event FIFO Full",
  143. "CANFD_IR_TEFL - Tx Event FIFO Event Lost",
  144. "CANFD_IR_TSW - Timestamp Wraparound",
  145. "CANFD_IR_MRAF - Message RAM Access Failure",
  146. "CANFD_IR_TOO - Timeout Occurred",
  147. "CANFD_IR_DRX - Message stored to Dedicated Rx Buffer",
  148. "BIT20",
  149. "BIT21",
  150. "CANFD_IR_ELO - Error Logging Overflow",
  151. "CANFD_IR_EP - Error Passive",
  152. "CANFD_IR_EW - Warning Status",
  153. "CANFD_IR_BO - Bus_Off Status",
  154. "CANFD_IR_WDI - Watchdog",
  155. "CANFD_IR_PEA - Protocol Error in Arbitration Phase",
  156. "CANFD_IR_PED - Protocol Error in Data Phase",
  157. "CANFD_IR_ARA - Access to Reserved Address",
  158. "BIT30",
  159. "BIT31"
  160. };
  161. static void dump_interrupt_event(uint32_t u32Status)
  162. {
  163. uint32_t idx;
  164. while ((idx = nu_ctz(u32Status)) < 32) // Count Trailing Zeros ==> Find First One
  165. {
  166. LOG_D("[%s]", szIR[idx]);
  167. u32Status &= ~(1 << idx);
  168. }
  169. }
  170. static void nu_canfd_isr(int vector, void *param)
  171. {
  172. /* Get base address of canfd register */
  173. nu_canfd_t psNuCANFD = (nu_canfd_t)param;
  174. /* Get base address of CAN register */
  175. CANFD_T *base = psNuCANFD->base;
  176. /* Get interrupt status */
  177. uint32_t u32Status = base->IR;
  178. CANFD_ClearStatusFlag(base, u32Status);
  179. /* Dump IR event */
  180. dump_interrupt_event(u32Status);
  181. /* Check Status Interrupt Flag (Error status Int and Status change Int) */
  182. /**************************/
  183. /* Status Change interrupt*/
  184. /**************************/
  185. if (u32Status & CANFD_IR_TC_Msk)
  186. {
  187. if (psNuCANFD->int_flag & RT_DEVICE_FLAG_INT_TX)
  188. {
  189. rt_hw_can_isr(&psNuCANFD->dev, RT_CAN_EVENT_TX_DONE);
  190. }
  191. }
  192. if (u32Status & (CANFD_IR_RF0N_Msk | CANFD_IR_RF1N_Msk))
  193. {
  194. if (psNuCANFD->int_flag & RT_DEVICE_FLAG_INT_RX)
  195. {
  196. rt_hw_can_isr(&psNuCANFD->dev, RT_CAN_EVENT_RX_IND);
  197. }
  198. }
  199. if (u32Status & (CANFD_IR_RF0L_Msk | CANFD_IR_RF1L_Msk))
  200. {
  201. rt_hw_can_isr(&psNuCANFD->dev, RT_CAN_EVENT_RXOF_IND);
  202. }
  203. if (u32Status & (CANFD_IR_TEFF_Msk | CANFD_IR_TOO_Msk))
  204. {
  205. rt_hw_can_isr(&psNuCANFD->dev, RT_CAN_EVENT_TX_FAIL);
  206. }
  207. /**************************/
  208. /* Error Status interrupt */
  209. /**************************/
  210. if (u32Status & CANFD_IR_EW_Msk)
  211. {
  212. LOG_E("[%s]EWARN", psNuCANFD->name) ;
  213. }
  214. if (u32Status & CANFD_IR_BO_Msk)
  215. {
  216. LOG_E("[%s]BUSOFF", psNuCANFD->name) ;
  217. /* To release busoff pin */
  218. }
  219. if (u32Status & CANFD_IR_PED_Msk)
  220. {
  221. LOG_E("[%s] LEC: %03x\n", psNuCANFD->name, base->PSR & CANFD_PSR_LEC_Msk) ;
  222. }
  223. }
  224. static void nu_canfd_ie(nu_canfd_t psNuCANFD)
  225. {
  226. uint32_t u32CanFDIE = CANFD_IE_BOE_Msk;
  227. if (psNuCANFD->int_flag & (RT_DEVICE_FLAG_INT_RX))
  228. {
  229. /* Rx FIFO 0 New Message Interrupt */
  230. u32CanFDIE |= (CANFD_IE_RF0NE_Msk | CANFD_IE_RF1NE_Msk);
  231. }
  232. if (psNuCANFD->int_flag & (RT_DEVICE_FLAG_INT_TX))
  233. {
  234. /* Transmission Completed Interrupt */
  235. /* Timeout Occurred Interrupt */
  236. u32CanFDIE |= (CANFD_IE_TCE_Msk | CANFD_IE_TEFNE_Msk);
  237. }
  238. if (psNuCANFD->int_flag & RT_DEVICE_CAN_INT_ERR)
  239. {
  240. /* Bus_Off Status Interrupt */
  241. /* Warning Status Interrupt */
  242. /* Error Passive Interrupt */
  243. /* Error Logging Overflow Interrupt */
  244. /* Protocol Error in Data Phase interrupt Indicator */
  245. u32CanFDIE |= (CANFD_IE_EPE_Msk | CANFD_IE_EWE_Msk | CANFD_IE_ELOE_Msk | CANFD_IE_TOOE_Msk | CANFD_IR_PED_Msk);
  246. }
  247. //u32CanFDIE = 0xffffffff;
  248. CANFD_EnableInt(psNuCANFD->base, u32CanFDIE, 0,
  249. (psNuCANFD->int_flag & (RT_DEVICE_FLAG_INT_TX)) ? CANFD_TXBTIE_TIEn_Msk : 0,
  250. (psNuCANFD->int_flag & (RT_DEVICE_FLAG_INT_TX)) ? CANFD_TXBCIE_CFIEn_Msk : 0);
  251. }
  252. static rt_err_t nu_canfd_configure(struct rt_can_device *can, struct can_configure *cfg)
  253. {
  254. nu_canfd_t psNuCANFD = (nu_canfd_t)can;
  255. CANFD_FD_T *psCANFDConf;
  256. RT_ASSERT(can);
  257. RT_ASSERT(cfg);
  258. psCANFDConf = &psNuCANFD->sCANFD_Config;
  259. /* Get base address of CAN register */
  260. CANFD_T *base = psNuCANFD->base;
  261. CANFD_GetDefaultConfig(psCANFDConf, CANFD_OP_CAN_MODE);
  262. LOG_I("Message Ram Size: %d @%08x ~ %08x", psCANFDConf->u32MRamSize, CANFD_SRAM_BASE_ADDR(base), psCANFDConf->u32MRamSize + CANFD_SRAM_BASE_ADDR(base));
  263. LOG_I("SIDFC: %d @%08x Size:%d", psCANFDConf->sElemSize.u32SIDFC, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32SIDFC_FLSSA, psCANFDConf->sElemSize.u32SIDFC * sizeof(CANFD_STD_FILTER_T));
  264. LOG_I("XIDFC: %d @%08x Size:%d", psCANFDConf->sElemSize.u32XIDFC, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32XIDFC_FLESA, psCANFDConf->sElemSize.u32XIDFC * sizeof(CANFD_EXT_FILTER_T));
  265. LOG_I("RxFifo0: %d @%08x Size:%d", psCANFDConf->sElemSize.u32RxFifo0, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32RXF0C_F0SA, psCANFDConf->sElemSize.u32RxFifo0 * sizeof(CANFD_BUF_T));
  266. LOG_I("RxFifo1: %d @%08x Size:%d", psCANFDConf->sElemSize.u32RxFifo1, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32RXF1C_F1SA, psCANFDConf->sElemSize.u32RxFifo1 * sizeof(CANFD_BUF_T));
  267. LOG_I("RxBuf: %d @%08x Size:%d", psCANFDConf->sElemSize.u32RxBuf, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32RXBC_RBSA, psCANFDConf->sElemSize.u32RxBuf * sizeof(CANFD_BUF_T));
  268. LOG_I("TxEventFifo: %d @%08x Size:%d", psCANFDConf->sElemSize.u32TxEventFifo, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32TXEFC_EFSA, psCANFDConf->sElemSize.u32TxEventFifo * sizeof(CANFD_EXT_FILTER_T));
  269. LOG_I("TxBuf: %d @%08x Size:%d", psCANFDConf->sElemSize.u32TxBuf, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32TXBC_TBSA, psCANFDConf->sElemSize.u32TxBuf * sizeof(CANFD_BUF_T));
  270. psCANFDConf->sBtConfig.sNormBitRate.u32BitRate = cfg->baud_rate;
  271. psCANFDConf->sBtConfig.sDataBitRate.u32BitRate = 0;
  272. LOG_I("CAN Baud rate: %d bps", cfg->baud_rate);
  273. switch (cfg->mode)
  274. {
  275. case RT_CAN_MODE_NORMAL: // Normal
  276. psCANFDConf->sBtConfig.evTestMode = eCANFD_NORMAL;
  277. break;
  278. case RT_CAN_MODE_LISTEN: // Bus monitor Mode, can't start a transmission
  279. psCANFDConf->sBtConfig.evTestMode = eCANFD_BUS_MONITOR;
  280. break;
  281. case RT_CAN_MODE_LOOPBACK: // Test - Internal loopback
  282. psCANFDConf->sBtConfig.evTestMode = eCANFD_LOOPBACK_INTERNAL;
  283. break;
  284. case RT_CAN_MODE_LOOPBACKANLISTEN:
  285. default:
  286. rt_kprintf("Unsupported Operating mode\n");
  287. goto exit_nu_canfd_configure;
  288. }
  289. /*Set the CAN Bit Rate and Operating mode*/
  290. CANFD_Open(base, psCANFDConf);
  291. /* Set FIFO policy */
  292. #if defined(RT_CAN_USING_HDR)
  293. /* Whitelist filtering */
  294. CANFD_SetGFC(base, eCANFD_REJ_NON_MATCH_FRM, eCANFD_REJ_NON_MATCH_FRM, 0, 0);
  295. #else
  296. /* Blacklist filtering. */
  297. CANFD_SetGFC(base, eCANFD_ACC_NON_MATCH_FRM_RX_FIFO0, eCANFD_ACC_NON_MATCH_FRM_RX_FIFO0, 0, 0);
  298. #endif
  299. /* Enable interrupt */
  300. nu_canfd_ie(psNuCANFD);
  301. //LOG_HEX("canfd", 16, (void *)base, sizeof(CANFD_T));
  302. /* Lock protected registers & Run */
  303. CANFD_RunToNormal(base, TRUE);
  304. return RT_EOK;
  305. exit_nu_canfd_configure:
  306. CANFD_Close(base);
  307. return -(RT_ERROR);
  308. }
  309. static rt_err_t nu_canfd_control(struct rt_can_device *can, int cmd, void *arg)
  310. {
  311. rt_uint32_t argval = (rt_uint32_t)arg;
  312. nu_canfd_t psNuCANFD = (nu_canfd_t)can;
  313. RT_ASSERT(can);
  314. switch (cmd)
  315. {
  316. case RT_DEVICE_CTRL_SET_INT:
  317. psNuCANFD->int_flag |= argval;
  318. return nu_canfd_configure(can, &can->config);
  319. case RT_DEVICE_CTRL_CLR_INT:
  320. psNuCANFD->int_flag &= ~argval;
  321. return nu_canfd_configure(can, &can->config);
  322. #if defined(RT_CAN_USING_HDR)
  323. case RT_CAN_CMD_SET_FILTER:
  324. {
  325. struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg;
  326. RT_ASSERT(filter_cfg);
  327. for (int i = 0; i < filter_cfg->count; i++)
  328. {
  329. uint32_t u32FEC = (filter_cfg->items[i].mode == RT_CAN_MODE_PRIV) ? eCANFD_FLTR_ELEM_SET_PRI_STO_FIFO0 : eCANFD_FLTR_ELEM_STO_FIFO0;
  330. /* Set the filter rule */
  331. if (filter_cfg->items[i].ide == RT_CAN_STDID)
  332. {
  333. /* for 11-bit */
  334. CANFD_STD_FILTER_T sStdFilter;
  335. if (i >= CANFD_MAX_11_BIT_FTR_ELEMS) // Check filter entry limitation
  336. return -(RT_ERROR);
  337. sStdFilter.SFID2 = filter_cfg->items[i].mask; /*!<Standard Filter ID 2. */ //mask
  338. sStdFilter.SFID1 = filter_cfg->items[i].id; /*!<Standard Filter ID 1. */ //filter
  339. sStdFilter.SFEC = u32FEC; /*!<Standard Filter Element Configuration */ //001b: Store in Rx FIFO 0 if filter matches
  340. sStdFilter.SFT = eCANFD_SID_FLTR_TYPE_CLASSIC; /*!<Standard Filter Type */ //10b: Classic filter: SFID1 = filter, SFID2 = mask
  341. CANFD_SetSIDFltr(psNuCANFD->base, i, sStdFilter.VALUE);
  342. }
  343. else
  344. {
  345. /* for 29-bit */
  346. CANFD_EXT_FILTER_T sXidFilter;
  347. if (i >= CANFD_MAX_29_BIT_FTR_ELEMS) // Check filter entry limitation
  348. return -(RT_ERROR);
  349. sXidFilter.EFID1 = filter_cfg->items[i].mask; /*!<Extended Filter ID 2. */ //mask
  350. sXidFilter.EFID2 = filter_cfg->items[i].id; /*!<Extended Filter ID 1. */ //filter
  351. sXidFilter.EFEC = u32FEC; /*!<Extended Filter Element Configuration */ //001b: Store in Rx FIFO 0 if filter matches
  352. sXidFilter.EFT = eCANFD_XID_FLTR_TYPE_CLASSIC; /*!<Extended Filter Type */ //10b: Classic filter: SFID1 = filter, SFID2 = mask
  353. CANFD_SetXIDFltr(psNuCANFD->base, i, sXidFilter.LOWVALUE, sXidFilter.HIGHVALUE);
  354. }
  355. } //for (int i = 0; i < filter_cfg->count; i++)
  356. }
  357. break;
  358. #endif
  359. case RT_CAN_CMD_SET_MODE:
  360. if ((argval == RT_CAN_MODE_NORMAL) ||
  361. (argval == RT_CAN_MODE_LISTEN) ||
  362. (argval == RT_CAN_MODE_LOOPBACK) ||
  363. (argval == RT_CAN_MODE_LOOPBACKANLISTEN))
  364. {
  365. if (argval != can->config.mode)
  366. {
  367. can->config.mode = argval;
  368. return nu_canfd_configure(can, &can->config);
  369. }
  370. }
  371. else
  372. {
  373. return -(RT_ERROR);
  374. }
  375. break;
  376. case RT_CAN_CMD_SET_BAUD:
  377. {
  378. if ((argval == CAN1MBaud) ||
  379. (argval == CAN800kBaud) ||
  380. (argval == CAN500kBaud) ||
  381. (argval == CAN250kBaud) ||
  382. (argval == CAN125kBaud) ||
  383. (argval == CAN100kBaud) ||
  384. (argval == CAN50kBaud) ||
  385. (argval == CAN20kBaud) ||
  386. (argval == CAN10kBaud))
  387. {
  388. if (argval != can->config.baud_rate)
  389. {
  390. can->config.baud_rate = argval;
  391. return nu_canfd_configure(can, &can->config);
  392. }
  393. }
  394. else
  395. {
  396. return -(RT_ERROR);
  397. }
  398. }
  399. break;
  400. case RT_CAN_CMD_SET_PRIV:
  401. if (argval != RT_CAN_MODE_PRIV &&
  402. argval != RT_CAN_MODE_NOPRIV)
  403. {
  404. return -(RT_ERROR);
  405. }
  406. if (argval != can->config.privmode)
  407. {
  408. can->config.privmode = argval;
  409. return nu_canfd_configure(can, &can->config);
  410. }
  411. break;
  412. case RT_CAN_CMD_GET_STATUS:
  413. {
  414. rt_uint32_t u32ErrCounter = psNuCANFD->base->ECR;
  415. rt_uint32_t u32ProtocolStatus = psNuCANFD->base->PSR;
  416. RT_ASSERT(arg);
  417. /*Receive Error Counter, return value is with Receive Error Passive.*/
  418. can->status.rcverrcnt = ((u32ErrCounter & CANFD_ECR_REC_Msk) >> CANFD_ECR_REC_Pos);
  419. /*Transmit Error Counter*/
  420. can->status.snderrcnt = ((u32ErrCounter & CANFD_ECR_TEC_Msk) >> CANFD_ECR_TEC_Pos);
  421. /*Last Error Type*/
  422. can->status.lasterrtype = ((u32ProtocolStatus & CANFD_PSR_LEC_Msk) >> CANFD_PSR_LEC_Pos);
  423. /*Status error code*/
  424. can->status.errcode = (u32ProtocolStatus & CANFD_PSR_EW_Msk) ? 1 :
  425. (u32ProtocolStatus & CANFD_PSR_EP_Msk) ? 2 :
  426. (u32ProtocolStatus & CANFD_PSR_BO_Msk) ? 3 :
  427. 0;
  428. rt_memcpy(arg, &can->status, sizeof(struct rt_can_status));
  429. }
  430. break;
  431. default:
  432. return -(RT_EINVAL);
  433. }
  434. return RT_EOK;
  435. }
  436. static int nu_canfd_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno)
  437. {
  438. CANFD_FD_MSG_T sTxMsg;
  439. struct rt_can_msg *pmsg;
  440. nu_canfd_t psNuCANFD = (nu_canfd_t)can;
  441. RT_ASSERT(can);
  442. RT_ASSERT(buf);
  443. pmsg = (struct rt_can_msg *) buf;
  444. if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id))
  445. {
  446. /* Standard ID (11 bits)*/
  447. sTxMsg.u32Id = pmsg->id;
  448. sTxMsg.eIdType = eCANFD_SID;
  449. }
  450. else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id))
  451. {
  452. /* Extended ID (29 bits)*/
  453. sTxMsg.u32Id = pmsg->id;
  454. sTxMsg.eIdType = eCANFD_XID;
  455. }
  456. else
  457. {
  458. goto exit_nu_canfd_sendmsg;
  459. }
  460. sTxMsg.bBitRateSwitch = 0;
  461. if (pmsg->rtr == RT_CAN_DTR)
  462. {
  463. /* Data frame */
  464. sTxMsg.eFrmType = eCANFD_DATA_FRM;
  465. }
  466. else if (pmsg->rtr == RT_CAN_RTR)
  467. {
  468. /* Remote frame */
  469. sTxMsg.eFrmType = eCANFD_REMOTE_FRM;
  470. }
  471. else
  472. {
  473. goto exit_nu_canfd_sendmsg;
  474. }
  475. /* Check the parameters */
  476. if (IS_CAN_DLC(pmsg->len))
  477. {
  478. sTxMsg.u32DLC = pmsg->len;
  479. }
  480. else
  481. {
  482. goto exit_nu_canfd_sendmsg;
  483. }
  484. if (pmsg->len > 0)
  485. {
  486. rt_memcpy(&sTxMsg.au8Data[0], pmsg->data, pmsg->len);
  487. }
  488. if (!CANFD_TransmitTxMsg(psNuCANFD->base, 0, &sTxMsg))
  489. {
  490. goto exit_nu_canfd_sendmsg;
  491. }
  492. return RT_EOK;
  493. exit_nu_canfd_sendmsg:
  494. return -(RT_ERROR);
  495. }
  496. static int nu_canfd_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno)
  497. {
  498. CANFD_FD_MSG_T sRxMsg;
  499. struct rt_can_msg *pmsg;
  500. nu_canfd_t psNuCANFD = (nu_canfd_t)can;
  501. RT_ASSERT(can);
  502. RT_ASSERT(buf);
  503. pmsg = (struct rt_can_msg *) buf;
  504. /* get data */
  505. if (CANFD_ReadRxFifoMsg(psNuCANFD->base, 0, &sRxMsg) == FALSE)
  506. {
  507. rt_kprintf("No available RX Msg.\n");
  508. return -(RT_ERROR);
  509. }
  510. #ifdef RT_CAN_USING_HDR
  511. /* Hardware filter messages are valid */
  512. pmsg->hdr_index = boxno;
  513. can->hdr[pmsg->hdr_index].connected = 1;
  514. #endif
  515. pmsg->ide = (sRxMsg.eIdType == eCANFD_SID) ? RT_CAN_STDID : RT_CAN_EXTID;
  516. pmsg->rtr = (sRxMsg.eFrmType == eCANFD_DATA_FRM) ? RT_CAN_DTR : RT_CAN_RTR;
  517. pmsg->id = sRxMsg.u32Id;
  518. pmsg->len = sRxMsg.u32DLC;
  519. if (pmsg->len > 0)
  520. rt_memcpy(&pmsg->data[0], &sRxMsg.au8Data[0], pmsg->len);
  521. return RT_EOK;
  522. }
  523. /**
  524. * Hardware CAN Initialization
  525. */
  526. static int rt_hw_canfd_init(void)
  527. {
  528. int i;
  529. rt_err_t ret = RT_EOK;
  530. for (i = (CANFD_START + 1); i < CANFD_CNT; i++)
  531. {
  532. nu_canfd_arr[i].dev.config = nu_canfd_default_config;
  533. #ifdef RT_CAN_USING_HDR
  534. nu_canfd_arr[i].dev.config.maxhdr = RT_CANMSG_BOX_SZ;
  535. #endif
  536. /* Register can device */
  537. ret = rt_hw_can_register(&nu_canfd_arr[i].dev, nu_canfd_arr[i].name, &nu_canfd_ops, NULL);
  538. RT_ASSERT(ret == RT_EOK);
  539. /* Register ISR. */
  540. rt_hw_interrupt_install(nu_canfd_arr[i].irqn0, nu_canfd_isr, &nu_canfd_arr[i], nu_canfd_arr[i].name);
  541. rt_hw_interrupt_install(nu_canfd_arr[i].irqn1, nu_canfd_isr, &nu_canfd_arr[i], nu_canfd_arr[i].name);
  542. /* Unmask interrupt. */
  543. rt_hw_interrupt_umask(nu_canfd_arr[i].irqn0);
  544. rt_hw_interrupt_umask(nu_canfd_arr[i].irqn1);
  545. }
  546. return (int)ret;
  547. }
  548. INIT_DEVICE_EXPORT(rt_hw_canfd_init);
  549. #endif //#if defined(BSP_USING_CANFD)