drv_can.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-03-24 YangXi the first version.
  9. */
  10. #include <rtdevice.h>
  11. #ifdef RT_USING_CAN
  12. #include "fsl_common.h"
  13. #include "fsl_flexcan.h"
  14. #define TX_MB_IDX (7)
  15. #define RX_MB_COUNT (1)
  16. static flexcan_frame_t frame[RX_MB_COUNT]; /* one frame buffer per RX MB */
  17. static rt_uint32_t filter_mask = 0;
  18. enum
  19. {
  20. #ifdef BSP_USING_CAN0
  21. CAN0_INDEX,
  22. #endif
  23. };
  24. struct imxrt_can
  25. {
  26. char *name;
  27. CAN_Type *base;
  28. IRQn_Type irqn;
  29. uint32_t instance;
  30. clock_div_name_t clock_div_name;
  31. clock_attach_id_t clock_attach_id;
  32. flexcan_handle_t handle;
  33. struct rt_can_device can_dev;
  34. };
  35. struct imxrt_can flexcans[] =
  36. {
  37. #ifdef BSP_USING_CAN0
  38. {
  39. .name = "can0",
  40. .base = CAN0,
  41. .instance = 0,
  42. .irqn = CAN0_IRQn,
  43. .clock_div_name = kCLOCK_DivFlexcan0Clk,
  44. .clock_attach_id = kFRO_HF_to_FLEXCAN0,
  45. },
  46. #endif
  47. };
  48. static void flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t status, uint64_t result, void *userData)
  49. {
  50. struct imxrt_can *can;
  51. flexcan_mb_transfer_t rxXfer;
  52. can = (struct imxrt_can *)userData;
  53. switch (status)
  54. {
  55. case kStatus_FLEXCAN_RxIdle:
  56. rt_hw_can_isr(&can->can_dev, RT_CAN_EVENT_RX_IND | result << 8);
  57. rxXfer.frame = &frame[result - 1];
  58. rxXfer.mbIdx = result;
  59. FLEXCAN_TransferReceiveNonBlocking(can->base, &can->handle, &rxXfer);
  60. break;
  61. // case kStatus_FLEXCAN_TxIdle:
  62. // rt_hw_can_isr(&can->can_dev, RT_CAN_EVENT_TX_DONE | (63 - result) << 8);
  63. // break;
  64. // case kStatus_FLEXCAN_WakeUp:
  65. // case kStatus_FLEXCAN_ErrorStatus:
  66. // if ((result >= 47) && (result <= 63))
  67. // {
  68. // rt_hw_can_isr(&can->can_dev, RT_CAN_EVENT_TX_FAIL | (63 - result) << 8);
  69. // }
  70. // break;
  71. // case kStatus_FLEXCAN_TxSwitchToRx:
  72. // break;
  73. default:
  74. break;
  75. }
  76. }
  77. static rt_err_t can_cfg(struct rt_can_device *can_dev, struct can_configure *cfg)
  78. {
  79. struct imxrt_can *can = (struct imxrt_can *)can_dev->parent.user_data;
  80. flexcan_config_t config;
  81. rt_uint32_t res = RT_EOK;
  82. flexcan_rx_mb_config_t mbConfig;
  83. flexcan_mb_transfer_t rxXfer;
  84. rt_uint8_t i, mailbox;
  85. FLEXCAN_GetDefaultConfig(&config);
  86. config.baudRate = cfg->baud_rate;
  87. config.enableIndividMask = true; /* one filter per MB */
  88. switch (cfg->mode)
  89. {
  90. case RT_CAN_MODE_NORMAL:
  91. /* default mode */
  92. break;
  93. case RT_CAN_MODE_LISTEN:
  94. break;
  95. case RT_CAN_MODE_LOOPBACK:
  96. config.enableLoopBack = true;
  97. break;
  98. case RT_CAN_MODE_LOOPBACKANLISTEN:
  99. break;
  100. }
  101. flexcan_timing_config_t timing_config;
  102. rt_memset(&timing_config, 0, sizeof(flexcan_timing_config_t));
  103. if(FLEXCAN_CalculateImprovedTimingValues(can->base, config.baudRate, CLOCK_GetFlexcanClkFreq(can->instance), &timing_config))
  104. {
  105. /* Update the improved timing configuration*/
  106. rt_memcpy(&(config.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
  107. }
  108. else
  109. {
  110. rt_kprintf("No found Improved Timing Configuration. Just used default configuration\n");
  111. }
  112. FLEXCAN_Init(can->base, &config, CLOCK_GetFlexcanClkFreq(can->instance));
  113. FLEXCAN_TransferCreateHandle(can->base, &can->handle, flexcan_callback, can);
  114. /* init RX_MB_COUNT RX MB to default status */
  115. mbConfig.format = kFLEXCAN_FrameFormatStandard; /* standard ID */
  116. mbConfig.type = kFLEXCAN_FrameTypeData; /* data frame */
  117. mbConfig.id = FLEXCAN_ID_STD(0); /* default ID is 0 */
  118. for (i = 0; i < RX_MB_COUNT; i++)
  119. {
  120. /* the used MB index from 1 to RX_MB_COUNT */
  121. mailbox = i + 1;
  122. /* all ID bit in the filter is "don't care" */
  123. FLEXCAN_SetRxIndividualMask(can->base, mailbox, FLEXCAN_RX_MB_STD_MASK(0, 0, 0));
  124. FLEXCAN_SetRxMbConfig(can->base, mailbox, &mbConfig, true);
  125. /* one frame buffer per MB */
  126. rxXfer.frame = &frame[i];
  127. rxXfer.mbIdx = mailbox;
  128. FLEXCAN_TransferReceiveNonBlocking(can->base, &can->handle, &rxXfer);
  129. }
  130. return res;
  131. }
  132. static rt_err_t can_control(struct rt_can_device *can_dev, int cmd, void *arg)
  133. {
  134. struct imxrt_can *can;
  135. rt_uint32_t argval, mask;
  136. rt_uint32_t res = RT_EOK;
  137. flexcan_rx_mb_config_t mbConfig;
  138. struct rt_can_filter_config *cfg;
  139. struct rt_can_filter_item *item;
  140. rt_uint8_t i, count, index;
  141. RT_ASSERT(can_dev != RT_NULL);
  142. can = (struct imxrt_can *)can_dev->parent.user_data;
  143. RT_ASSERT(can != RT_NULL);
  144. switch (cmd)
  145. {
  146. case RT_DEVICE_CTRL_SET_INT:
  147. argval = (rt_uint32_t) arg;
  148. if (argval == RT_DEVICE_FLAG_INT_RX)
  149. {
  150. mask = kFLEXCAN_RxWarningInterruptEnable;
  151. }
  152. else if (argval == RT_DEVICE_FLAG_INT_TX)
  153. {
  154. mask = kFLEXCAN_TxWarningInterruptEnable;
  155. }
  156. else if (argval == RT_DEVICE_CAN_INT_ERR)
  157. {
  158. mask = kFLEXCAN_ErrorInterruptEnable;
  159. }
  160. FLEXCAN_EnableInterrupts(can->base, mask);
  161. NVIC_SetPriority(can->irqn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
  162. EnableIRQ(can->irqn);
  163. break;
  164. case RT_DEVICE_CTRL_CLR_INT:
  165. /* each CAN device have one IRQ number. */
  166. DisableIRQ(can->irqn);
  167. break;
  168. case RT_CAN_CMD_SET_FILTER:
  169. cfg = (struct rt_can_filter_config *)arg;
  170. item = cfg->items;
  171. count = cfg->count;
  172. if (filter_mask == 0xffffffff)
  173. {
  174. rt_kprintf("%s filter is full!\n", can->name);
  175. res = -RT_ERROR;
  176. break;
  177. }
  178. else if (filter_mask == 0)
  179. {
  180. /* deinit all init RX MB */
  181. for (i = 0; i < RX_MB_COUNT; i++)
  182. {
  183. FLEXCAN_SetRxMbConfig(can->base, i + 1, RT_NULL, false);
  184. }
  185. }
  186. while (count)
  187. {
  188. if (item->ide)
  189. {
  190. mbConfig.format = kFLEXCAN_FrameFormatExtend;
  191. mbConfig.id = FLEXCAN_ID_EXT(item->id);
  192. mask = FLEXCAN_RX_MB_EXT_MASK(item->mask, 0, 0);
  193. }
  194. else
  195. {
  196. mbConfig.format = kFLEXCAN_FrameFormatStandard;
  197. mbConfig.id = FLEXCAN_ID_STD(item->id);
  198. mask = FLEXCAN_RX_MB_STD_MASK(item->mask, 0, 0);
  199. }
  200. if (item->rtr)
  201. {
  202. mbConfig.type = kFLEXCAN_FrameTypeRemote;
  203. }
  204. else
  205. {
  206. mbConfig.type = kFLEXCAN_FrameTypeData;
  207. }
  208. /* user does not specify hdr index,set hdr_bank from RX MB 1 */
  209. if (item->hdr_bank == -1)
  210. {
  211. for (i = 0; i < 32; i++)
  212. {
  213. if (!(filter_mask & (1 << i)))
  214. {
  215. index = i;
  216. break;
  217. }
  218. }
  219. }
  220. else /* use user specified hdr_bank */
  221. {
  222. if (filter_mask & (1 << item->hdr_bank))
  223. {
  224. res = -RT_ERROR;
  225. rt_kprintf("%s hdr%d filter already set!\n", can->name, item->hdr_bank);
  226. break;
  227. }
  228. else
  229. {
  230. index = item->hdr_bank;
  231. }
  232. }
  233. /* RX MB index from 1 to 32,hdr index 0~31 map RX MB index 1~32. */
  234. FLEXCAN_SetRxIndividualMask(can->base, index + 1, mask);
  235. FLEXCAN_SetRxMbConfig(can->base, index + 1, &mbConfig, true);
  236. filter_mask |= 1 << index;
  237. item++;
  238. count--;
  239. }
  240. break;
  241. case RT_CAN_CMD_SET_BAUD:
  242. res = -RT_ERROR;
  243. break;
  244. case RT_CAN_CMD_SET_MODE:
  245. res = -RT_ERROR;
  246. break;
  247. case RT_CAN_CMD_SET_PRIV:
  248. res = -RT_ERROR;
  249. break;
  250. case RT_CAN_CMD_GET_STATUS:
  251. FLEXCAN_GetBusErrCount(can->base, (rt_uint8_t *)(&can->can_dev.status.snderrcnt), (rt_uint8_t *)(&can->can_dev.status.rcverrcnt));
  252. rt_memcpy(arg, &can->can_dev.status, sizeof(can->can_dev.status));
  253. break;
  254. default:
  255. res = -RT_ERROR;
  256. break;
  257. }
  258. return res;
  259. }
  260. static rt_ssize_t can_send(struct rt_can_device *can_dev, const void *buf, rt_uint32_t boxno)
  261. {
  262. struct imxrt_can *can;
  263. struct rt_can_msg *msg;
  264. status_t ret;
  265. flexcan_frame_t frame;
  266. can = (struct imxrt_can *)can_dev->parent.user_data;
  267. msg = (struct rt_can_msg *) buf;
  268. FLEXCAN_SetTxMbConfig(can->base, TX_MB_IDX, true);
  269. if (RT_CAN_STDID == msg->ide)
  270. {
  271. frame.id = FLEXCAN_ID_STD(msg->id);
  272. frame.format = kFLEXCAN_FrameFormatStandard;
  273. }
  274. else if (RT_CAN_EXTID == msg->ide)
  275. {
  276. frame.id = FLEXCAN_ID_EXT(msg->id);
  277. frame.format = kFLEXCAN_FrameFormatExtend;
  278. }
  279. if (RT_CAN_DTR == msg->rtr)
  280. {
  281. frame.type = kFLEXCAN_FrameTypeData;
  282. }
  283. else if (RT_CAN_RTR == msg->rtr)
  284. {
  285. frame.type = kFLEXCAN_FrameTypeRemote;
  286. }
  287. frame.length = msg->len;
  288. frame.dataByte0 = msg->data[0];
  289. frame.dataByte1 = msg->data[1];
  290. frame.dataByte2 = msg->data[2];
  291. frame.dataByte3 = msg->data[3];
  292. frame.dataByte4 = msg->data[4];
  293. frame.dataByte5 = msg->data[5];
  294. frame.dataByte6 = msg->data[6];
  295. frame.dataByte7 = msg->data[7];
  296. ret = FLEXCAN_TransferSendBlocking(can->base, TX_MB_IDX, &frame);
  297. switch (ret)
  298. {
  299. case kStatus_Success:
  300. ret = RT_EOK;
  301. break;
  302. case kStatus_Fail:
  303. ret = -RT_ERROR;
  304. break;
  305. case kStatus_FLEXCAN_TxBusy:
  306. ret = -RT_EBUSY;
  307. break;
  308. }
  309. return (rt_ssize_t)ret;
  310. }
  311. static rt_ssize_t can_recv(struct rt_can_device *can_dev, void *buf, rt_uint32_t boxno)
  312. {
  313. struct imxrt_can *can;
  314. struct rt_can_msg *pmsg;
  315. rt_uint8_t index;
  316. can = (struct imxrt_can *)can_dev->parent.user_data;
  317. pmsg = (struct rt_can_msg *) buf;
  318. index = boxno - 1;
  319. if (frame[index].format == kFLEXCAN_FrameFormatStandard)
  320. {
  321. pmsg->ide = RT_CAN_STDID;
  322. pmsg->id = frame[index].id >> CAN_ID_STD_SHIFT;
  323. }
  324. else
  325. {
  326. pmsg->ide = RT_CAN_EXTID;
  327. pmsg->id = frame[index].id >> CAN_ID_EXT_SHIFT;
  328. }
  329. if (frame[index].type == kFLEXCAN_FrameTypeData)
  330. {
  331. pmsg->rtr = RT_CAN_DTR;
  332. }
  333. else if (frame[index].type == kFLEXCAN_FrameTypeRemote)
  334. {
  335. pmsg->rtr = RT_CAN_RTR;
  336. }
  337. pmsg->hdr_index = index; /* one hdr filter per MB */
  338. pmsg->len = frame[index].length;
  339. pmsg->data[0] = frame[index].dataByte0;
  340. pmsg->data[1] = frame[index].dataByte1;
  341. pmsg->data[2] = frame[index].dataByte2;
  342. pmsg->data[3] = frame[index].dataByte3;
  343. pmsg->data[4] = frame[index].dataByte4;
  344. pmsg->data[5] = frame[index].dataByte5;
  345. pmsg->data[6] = frame[index].dataByte6;
  346. pmsg->data[7] = frame[index].dataByte7;
  347. return 0;
  348. }
  349. static struct rt_can_ops imxrt_can_ops =
  350. {
  351. .configure = can_cfg,
  352. .control = can_control,
  353. .sendmsg = can_send,
  354. .recvmsg = can_recv,
  355. };
  356. int rt_hw_can_init(void)
  357. {
  358. int i;
  359. rt_err_t ret = RT_EOK;
  360. struct can_configure config = CANDEFAULTCONFIG;
  361. config.privmode = 0;
  362. config.ticks = 50;
  363. config.sndboxnumber = 1;
  364. config.msgboxsz = RX_MB_COUNT;
  365. #ifdef RT_CAN_USING_HDR
  366. config.maxhdr = RX_MB_COUNT; /* filter count,one filter per MB */
  367. #endif
  368. for (i = 0; i < sizeof(flexcans) / sizeof(flexcans[0]); i++)
  369. {
  370. flexcans[i].can_dev.config = config;
  371. CLOCK_SetClkDiv(flexcans[i].clock_div_name, 1u);
  372. CLOCK_AttachClk(flexcans[i].clock_attach_id);
  373. ret = rt_hw_can_register(&flexcans[i].can_dev, flexcans[i].name, &imxrt_can_ops, &flexcans[i]);
  374. }
  375. return ret;
  376. }
  377. INIT_BOARD_EXPORT(rt_hw_can_init);
  378. #endif /*RT_USING_CAN */