drv_canfd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-10-29 mazhiyuan first version
  9. */
  10. #include "drv_canfd.h"
  11. static struct ra_can_config can_config[] =
  12. {
  13. #ifdef BSP_USING_CANFD0
  14. CANFD0_CONFIG,
  15. #endif
  16. #ifdef BSP_USING_CANFD1
  17. CANFD1_CONFIG
  18. #endif
  19. };
  20. enum
  21. {
  22. #ifdef BSP_USING_CANFD0
  23. CANFD0_INDEX,
  24. #endif
  25. #ifdef BSP_USING_CANFD1
  26. CANFD1_INDEX,
  27. #endif
  28. };
  29. static struct ra_can can_obj[sizeof(can_config) / sizeof(can_config[0])] = {0};
  30. const canfd_afl_entry_t p_canfd0_afl[CANFD_CFG_AFL_CH0_RULE_NUM] =
  31. {
  32. {
  33. .id =
  34. {
  35. .id = 0x00,
  36. .frame_type = CAN_FRAME_TYPE_DATA,
  37. .id_mode = CAN_ID_MODE_STANDARD
  38. },
  39. .destination =
  40. {
  41. .minimum_dlc = CANFD_MINIMUM_DLC_0,
  42. .rx_buffer = CANFD_RX_MB_NONE,
  43. .fifo_select_flags = CANFD_RX_FIFO_0
  44. }
  45. },
  46. };
  47. const canfd_afl_entry_t p_canfd1_afl[CANFD_CFG_AFL_CH1_RULE_NUM] =
  48. {
  49. {
  50. .id =
  51. {
  52. .id = 0x01,
  53. .frame_type = CAN_FRAME_TYPE_DATA,
  54. .id_mode = CAN_ID_MODE_STANDARD
  55. },
  56. .destination =
  57. {
  58. .minimum_dlc = CANFD_MINIMUM_DLC_1,
  59. .rx_buffer = CANFD_RX_MB_NONE,
  60. .fifo_select_flags = CANFD_RX_FIFO_1
  61. }
  62. },
  63. };
  64. static const struct ra_baud_rate_tab can_baud_rate_tab[] =
  65. {
  66. {CAN1MBaud, 3, 6, 3, 1 + 4},
  67. {CAN800kBaud, 4, 15, 5, 1 + 2},
  68. {CAN500kBaud, 4, 14, 5, 1 + 4},
  69. {CAN250kBaud, 4, 14, 5, 1 + 9},
  70. {CAN125kBaud, 4, 14, 5, 1 + 19},
  71. {CAN100kBaud, 4, 14, 5, 1 + 24},
  72. {CAN50kBaud, 4, 14, 5, 1 + 49},
  73. {CAN20kBaud, 4, 14, 5, 1 + 124},
  74. {CAN10kBaud, 4, 14, 5, 1 + 249}
  75. };
  76. static rt_uint32_t get_can_baud_index(rt_uint32_t baud)
  77. {
  78. rt_uint32_t len, index;
  79. len = sizeof(can_baud_rate_tab) / sizeof(can_baud_rate_tab[0]);
  80. for (index = 0; index < len; index++)
  81. {
  82. if (can_baud_rate_tab[index].baud_rate == baud)
  83. return index;
  84. }
  85. return 0; /* default baud is CAN1MBaud */
  86. }
  87. static void ra_can_get_config(void)
  88. {
  89. struct can_configure config = CANDEFAULTCONFIG;
  90. #ifdef BSP_USING_CANFD0
  91. can_obj[CANFD0_INDEX].can_dev.config = config;
  92. can_obj[CANFD0_INDEX].can_dev.config.msgboxsz = 64;
  93. can_obj[CANFD0_INDEX].can_dev.config.sndboxnumber = 1;
  94. can_obj[CANFD0_INDEX].can_dev.config.ticks = 50;
  95. #endif
  96. #ifdef BSP_USING_CANFD1
  97. can_obj[CANFD1_INDEX].can_dev.config = config;
  98. can_obj[CANFD1_INDEX].can_dev.config.msgboxsz = 64;
  99. can_obj[CANFD1_INDEX].can_dev.config.sndboxnumber = 1;
  100. can_obj[CANFD1_INDEX].can_dev.config.ticks = 50;
  101. #endif
  102. }
  103. rt_err_t ra_can_configure(struct rt_can_device *can_dev, struct can_configure *cfg)
  104. {
  105. struct ra_can *can;
  106. RT_ASSERT(can_dev != RT_NULL);
  107. RT_ASSERT(cfg != RT_NULL);
  108. fsp_err_t err = FSP_SUCCESS;
  109. can = rt_container_of(can_dev, struct ra_can, can_dev);
  110. RT_ASSERT(can != RT_NULL);
  111. err = R_CANFD_Open(can->config->p_api_ctrl, can->config->p_cfg);
  112. if (FSP_SUCCESS != err)
  113. {
  114. return -RT_ERROR;
  115. }
  116. return RT_EOK;
  117. }
  118. rt_err_t ra_can_control(struct rt_can_device *can_dev, int cmd, void *arg)
  119. {
  120. struct ra_can *can;
  121. can_info_t can_info;
  122. rt_uint32_t argval;
  123. RT_ASSERT(can_dev != RT_NULL);
  124. can = rt_container_of(can_dev, struct ra_can, can_dev);
  125. switch (cmd)
  126. {
  127. case RT_DEVICE_CTRL_CLR_INT:
  128. R_BSP_IrqClearPending((IRQn_Type)(uintptr_t)arg);
  129. break;
  130. case RT_CAN_CMD_SET_BAUD:
  131. argval = (rt_uint32_t) arg;
  132. if (argval != CAN1MBaud &&
  133. argval != CAN800kBaud &&
  134. argval != CAN500kBaud &&
  135. argval != CAN250kBaud &&
  136. argval != CAN125kBaud &&
  137. argval != CAN100kBaud &&
  138. argval != CAN50kBaud &&
  139. argval != CAN20kBaud &&
  140. argval != CAN10kBaud)
  141. {
  142. return -RT_ERROR;
  143. }
  144. if (argval != can->can_dev.config.baud_rate)
  145. {
  146. can->can_dev.config.baud_rate = argval;
  147. uint32_t index = get_can_baud_index(argval);
  148. can->config->p_cfg->p_bit_timing->baud_rate_prescaler = can_baud_rate_tab[index].prescaler;
  149. can->config->p_cfg->p_bit_timing->synchronization_jump_width = can_baud_rate_tab[index].sjw;
  150. can->config->p_cfg->p_bit_timing->time_segment_1 = can_baud_rate_tab[index].ts1;
  151. can->config->p_cfg->p_bit_timing->time_segment_2 = can_baud_rate_tab[index].ts2;
  152. return ra_can_configure(&can->can_dev, &can->can_dev.config);
  153. }
  154. break;
  155. case RT_CAN_CMD_SET_MODE:
  156. argval = (rt_uint32_t) arg;
  157. if (argval != RT_CAN_MODE_NORMAL &&
  158. argval != RT_CAN_MODE_LISTEN &&
  159. argval != RT_CAN_MODE_LOOPBACK)
  160. {
  161. return -RT_ERROR;
  162. }
  163. if (argval != can->can_dev.config.mode)
  164. {
  165. can_test_mode_t mode_to_set;
  166. can->can_dev.config.mode = argval;
  167. switch (argval)
  168. {
  169. case RT_CAN_MODE_NORMAL:
  170. mode_to_set = CAN_TEST_MODE_DISABLED;
  171. case RT_CAN_MODE_LISTEN:
  172. mode_to_set = CAN_TEST_MODE_LISTEN;
  173. case RT_CAN_MODE_LOOPBACK:
  174. mode_to_set = CAN_TEST_MODE_LOOPBACK_INTERNAL;
  175. }
  176. R_CANFD_ModeTransition(can->config->p_api_ctrl, ((canfd_instance_ctrl_t *)(can->config->p_api_ctrl))->operation_mode, mode_to_set);
  177. }
  178. break;
  179. case RT_CAN_CMD_GET_STATUS:
  180. R_CANFD_InfoGet(can->config->p_api_ctrl, &can_info);
  181. can->can_dev.status.rcverrcnt = can_info.error_count_receive;
  182. can->can_dev.status.snderrcnt = can_info.error_count_transmit;
  183. can->can_dev.status.errcode = can_info.error_code;
  184. rt_memcpy(arg, &can->can_dev.status, sizeof(can->can_dev.status));
  185. break;
  186. default:
  187. return -RT_ERROR;
  188. }
  189. return RT_EOK;
  190. }
  191. rt_ssize_t ra_can_sendmsg(struct rt_can_device *can_dev, const void *buf, rt_uint32_t boxno)
  192. {
  193. struct ra_can *can;
  194. can_frame_t g_can_tx_frame;
  195. struct rt_can_msg *msg_rt = (struct rt_can_msg *)buf;
  196. RT_ASSERT(can_dev != RT_NULL);
  197. RT_ASSERT(buf != RT_NULL);
  198. g_can_tx_frame.id = msg_rt->id;
  199. g_can_tx_frame.id_mode = (can_id_mode_t)msg_rt->ide;
  200. g_can_tx_frame.type = (can_frame_type_t)msg_rt->rtr;
  201. g_can_tx_frame.data_length_code = msg_rt->len;
  202. #if defined(BSP_USING_CANFD) && defined(BSP_USING_CAN_RZ)
  203. g_can_tx_frame.options = 0;
  204. #elif defined(BSP_USING_CANFD)
  205. g_can_tx_frame.options = CANFD_FRAME_OPTION_FD | CANFD_FRAME_OPTION_BRS;
  206. #else
  207. g_can_tx_frame.options = 0;
  208. #endif
  209. memcpy(g_can_tx_frame.data, msg_rt->data, 8);
  210. can = rt_container_of(can_dev, struct ra_can, can_dev);
  211. RT_ASSERT(boxno < can->config->num_of_mailboxs);
  212. if (R_CANFD_Write(can->config->p_api_ctrl, boxno, &g_can_tx_frame) != FSP_SUCCESS)
  213. {
  214. rt_exit_critical();
  215. return -RT_ERROR;
  216. }
  217. return RT_EOK;
  218. }
  219. rt_ssize_t ra_can_recvmsg(struct rt_can_device *can_dev, void *buf, rt_uint32_t boxno)
  220. {
  221. struct rt_can_msg *msg_rt = (struct rt_can_msg *)buf;
  222. can_frame_t *msg_ra;
  223. struct ra_can *can;
  224. RT_ASSERT(can_dev != RT_NULL);
  225. RT_ASSERT(buf != RT_NULL);
  226. can = rt_container_of(can_dev, struct ra_can, can_dev);
  227. RT_ASSERT(boxno < can->config->num_of_mailboxs);
  228. if (can->callback_args->mailbox != boxno)
  229. return 0;
  230. msg_ra = &can->callback_args->frame;
  231. msg_rt->id = msg_ra->id;
  232. msg_rt->ide = msg_ra->id_mode;
  233. msg_rt->rtr = msg_ra->type;
  234. msg_rt->rsv = RT_NULL;
  235. msg_rt->len = msg_ra->data_length_code;
  236. msg_rt->priv = boxno;
  237. msg_rt->hdr_index = RT_NULL;
  238. memcpy(msg_rt->data, msg_ra->data, msg_ra->data_length_code);
  239. return sizeof(struct rt_can_msg);
  240. }
  241. const struct rt_can_ops ra_can_ops =
  242. {
  243. .configure = ra_can_configure,
  244. .control = ra_can_control,
  245. .sendmsg = ra_can_sendmsg,
  246. .recvmsg = ra_can_recvmsg
  247. };
  248. #ifdef BSP_USING_CANFD0
  249. void canfd0_callback(can_callback_args_t *p_args)
  250. {
  251. rt_interrupt_enter();
  252. switch (p_args->event)
  253. {
  254. case CAN_EVENT_TX_COMPLETE:
  255. rt_hw_can_isr(&can_obj[CANFD0_INDEX].can_dev, RT_CAN_EVENT_TX_DONE | p_args->mailbox << 8);
  256. break;
  257. case CAN_EVENT_RX_COMPLETE:
  258. can_obj[CANFD0_INDEX].callback_args = p_args;
  259. if (p_args->event == CAN_EVENT_RX_COMPLETE)
  260. rt_hw_can_isr(&can_obj[CANFD0_INDEX].can_dev, RT_CAN_EVENT_RX_IND | p_args->mailbox << 8);
  261. break;
  262. case CAN_EVENT_TX_ABORTED:
  263. rt_hw_can_isr(&can_obj[CANFD0_INDEX].can_dev, RT_CAN_EVENT_TX_FAIL | p_args->mailbox << 8);
  264. break;
  265. case CAN_EVENT_MAILBOX_MESSAGE_LOST: //overwrite/overrun error event
  266. case CAN_EVENT_BUS_RECOVERY: //Bus recovery error event
  267. case CAN_EVENT_ERR_BUS_OFF: //error Bus Off event
  268. case CAN_EVENT_ERR_PASSIVE: //error passive event
  269. case CAN_EVENT_ERR_WARNING: //error warning event
  270. case CAN_EVENT_ERR_BUS_LOCK: //error bus lock
  271. case CAN_EVENT_ERR_CHANNEL: //error channel
  272. case CAN_EVENT_ERR_GLOBAL: //error global
  273. case CAN_EVENT_TX_FIFO_EMPTY: //error transmit FIFO is empty
  274. {
  275. break;
  276. }
  277. }
  278. rt_interrupt_leave();
  279. }
  280. #endif
  281. #ifdef BSP_USING_CANFD1
  282. void canfd1_callback(can_callback_args_t *p_args)
  283. {
  284. rt_interrupt_enter();
  285. switch (p_args->event)
  286. {
  287. case CAN_EVENT_TX_COMPLETE:
  288. rt_hw_can_isr(&can_obj[CANFD1_INDEX].can_dev, RT_CAN_EVENT_TX_DONE | p_args->mailbox << 8);
  289. break;
  290. case CAN_EVENT_RX_COMPLETE:
  291. can_obj[CANFD1_INDEX].callback_args = p_args;
  292. if (p_args->event == CAN_EVENT_RX_COMPLETE)
  293. rt_hw_can_isr(&can_obj[CANFD1_INDEX].can_dev, RT_CAN_EVENT_RX_IND | p_args->mailbox << 8);
  294. break;
  295. case CAN_EVENT_TX_ABORTED:
  296. rt_hw_can_isr(&can_obj[CANFD1_INDEX].can_dev, RT_CAN_EVENT_TX_FAIL | p_args->mailbox << 8);
  297. break;
  298. case CAN_EVENT_MAILBOX_MESSAGE_LOST: //overwrite/overrun error event
  299. case CAN_EVENT_BUS_RECOVERY: //Bus recovery error event
  300. case CAN_EVENT_ERR_BUS_OFF: //error Bus Off event
  301. case CAN_EVENT_ERR_PASSIVE: //error passive event
  302. case CAN_EVENT_ERR_WARNING: //error warning event
  303. case CAN_EVENT_ERR_BUS_LOCK: //error bus lock
  304. case CAN_EVENT_ERR_CHANNEL: //error channel
  305. case CAN_EVENT_ERR_GLOBAL: //error global
  306. {
  307. break;
  308. }
  309. }
  310. rt_interrupt_leave();
  311. }
  312. #endif
  313. int rt_hw_can_init(void)
  314. {
  315. rt_err_t result = 0;
  316. rt_size_t obj_num = sizeof(can_obj) / sizeof(struct ra_can);
  317. ra_can_get_config();
  318. for (int i = 0; i < obj_num; i++)
  319. {
  320. /* init CAN object */
  321. can_obj[i].config = &can_config[i];
  322. can_obj[i].can_dev.ops = &ra_can_ops;
  323. /* register CAN device */
  324. result = rt_hw_can_register(&can_obj[i].can_dev, can_obj[i].config->name, can_obj[i].can_dev.ops, RT_NULL);
  325. RT_ASSERT(result == RT_EOK);
  326. }
  327. return result;
  328. }
  329. INIT_BOARD_EXPORT(rt_hw_can_init);