drv_can.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-05-11 Carl the first version
  9. */
  10. #include "drv_can.h"
  11. #include "interrupt.h"
  12. #include <string.h>
  13. #ifdef BSP_USE_CAN
  14. #define LOG_TAG "drv_can"
  15. #include <drv_log.h>
  16. #define _CAN0_NAME "can0"
  17. #define _CAN1_NAME "can1"
  18. #define RTHW_CAN_WAIT(_can) rt_sem_take(&_can->recv_semaphore, RT_WAITING_FOREVER);
  19. #define RTHW_CAN_SEND(_can) rt_sem_release(&_can->recv_semaphore);
  20. #ifdef BSP_USING_CAN0
  21. struct ft2004_can drv_can0 =
  22. {
  23. .name = _CAN0_NAME,
  24. .can_handle.Config.InstanceId = 0};
  25. #endif
  26. #ifdef BSP_USING_CAN1
  27. struct ft2004_can drv_can1 =
  28. {
  29. .name = _CAN1_NAME,
  30. .can_handle.Config.InstanceId = 1};
  31. #endif
  32. static void _can_recv_irq(void *args)
  33. {
  34. struct ft2004_can *drv_can = (struct ft2004_can *)args;
  35. RTHW_CAN_SEND(drv_can);
  36. }
  37. static void rt_hw_inner_can_isr(int irqno, void *param)
  38. {
  39. FCan_IntrHandler(param);
  40. }
  41. static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg)
  42. {
  43. struct FCan_Bittiming bit_timing = {0};
  44. struct ft2004_can *drv_can;
  45. RT_ASSERT(can);
  46. RT_ASSERT(cfg);
  47. drv_can = (struct ft2004_can *)can->parent.user_data;
  48. RT_ASSERT(drv_can);
  49. FCan_CfgInitialize(&drv_can->can_handle, FCan_LookupConfig(drv_can->can_handle.Config.InstanceId));
  50. FCan_SetHandler(&drv_can->can_handle, FCAN_HANDLER_RECV, _can_recv_irq, drv_can);
  51. bit_timing.bitrate = cfg->baud_rate;
  52. if (FCan_CalcBittiming(&bit_timing) != FCAN_SUCCESS)
  53. {
  54. LOG_E("Setting baud rate %x is not valid \r\n", bit_timing.bitrate);
  55. return -RT_ERROR;
  56. }
  57. FCan_SetTiming(&drv_can->can_handle, &bit_timing);
  58. rt_hw_interrupt_set_priority(drv_can->can_handle.Config.IrqNum, 16);
  59. rt_hw_interrupt_install(drv_can->can_handle.Config.IrqNum, rt_hw_inner_can_isr, &drv_can->can_handle, drv_can->name);
  60. rt_hw_interrupt_umask(drv_can->can_handle.Config.IrqNum);
  61. FCan_Enable(&drv_can->can_handle);
  62. return RT_EOK;
  63. }
  64. static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
  65. {
  66. return RT_EOK;
  67. }
  68. static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
  69. {
  70. struct ft2004_can *drv_can;
  71. struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
  72. struct FCan_Frame can_frame = {0};
  73. RT_ASSERT(can);
  74. drv_can = (struct ft2004_can *)can->parent.user_data;
  75. RT_ASSERT(drv_can);
  76. /* Check the parameters */
  77. RT_ASSERT(pmsg->len <= 8U);
  78. if (RT_CAN_STDID == pmsg->ide)
  79. {
  80. can_frame.CanId = pmsg->id;
  81. }
  82. else
  83. {
  84. can_frame.CanId = pmsg->id;
  85. can_frame.CanId |= CAN_EFF_FLAG;
  86. }
  87. if (RT_CAN_DTR == pmsg->rtr)
  88. {
  89. }
  90. else
  91. {
  92. can_frame.CanId |= CAN_RTR_FLAG;
  93. }
  94. can_frame.CanDlc = pmsg->len & 0x0FU;
  95. memcpy(can_frame.data, pmsg->data, 8);
  96. return (FCan_SendByIrq(&drv_can->can_handle, &can_frame, 1, RT_NULL) == 1) ? RT_EOK : -RT_ERROR;
  97. }
  98. static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
  99. {
  100. struct ft2004_can *drv_can;
  101. struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
  102. RT_ASSERT(can);
  103. struct FCan_Frame recv_frame = {0};
  104. drv_can = (struct ft2004_can *)can->parent.user_data;
  105. RT_ASSERT(drv_can);
  106. RTHW_CAN_WAIT(drv_can);
  107. if (FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1) == 0)
  108. {
  109. LOG_E("rx msg is error");
  110. return -RT_ERROR;
  111. }
  112. if (CAN_EFF_FLAG & recv_frame.CanId)
  113. {
  114. pmsg->ide = RT_CAN_EXTID;
  115. pmsg->id = (recv_frame.CanId & ~(RT_CAN_EXTID));
  116. }
  117. else
  118. {
  119. pmsg->ide = RT_CAN_STDID;
  120. pmsg->id = recv_frame.CanId;
  121. }
  122. if (CAN_RTR_FLAG & recv_frame.CanId)
  123. {
  124. pmsg->id &= ~CAN_RTR_FLAG;
  125. pmsg->rtr = RT_CAN_RTR;
  126. }
  127. else
  128. {
  129. pmsg->rtr = RT_CAN_DTR;
  130. }
  131. /* get len */
  132. pmsg->len = recv_frame.CanDlc;
  133. return RT_EOK;
  134. }
  135. static const struct rt_can_ops _can_ops =
  136. {
  137. _can_config,
  138. _can_control,
  139. _can_sendmsg,
  140. _can_recvmsg,
  141. };
  142. int rt_hw_can_init(void)
  143. {
  144. #ifdef BSP_USING_CAN0
  145. drv_can0.can_handle.Config.InstanceId = 0;
  146. rt_sem_init(&drv_can0.recv_semaphore, "can0_recv", 0, RT_IPC_FLAG_FIFO);
  147. drv_can0.device.config.ticks = 20000;
  148. drv_can0.device.config.baud_rate = 1000000;
  149. rt_hw_can_register(&drv_can0.device,
  150. drv_can0.name,
  151. &_can_ops,
  152. &drv_can0);
  153. #endif
  154. #ifdef BSP_USING_CAN1
  155. drv_can1.can_handle.Config.InstanceId = 1;
  156. drv_can1.device.config.ticks = 20000;
  157. drv_can1.device.config.baud_rate = 1000000;
  158. rt_sem_init(&drv_can1.recv_semaphore, "can1_recv", 0, RT_IPC_FLAG_FIFO);
  159. rt_hw_can_register(&drv_can1.device,
  160. drv_can1.name,
  161. &_can_ops,
  162. &drv_can1);
  163. #endif
  164. return 0;
  165. }
  166. INIT_BOARD_EXPORT(rt_hw_can_init);
  167. #ifdef BSP_USING_CAN0_DEBUG
  168. struct can_test_struct
  169. {
  170. const char *name;
  171. struct rt_can_filter_config *filter;
  172. rt_device_t candev;
  173. struct rt_semaphore _sem;
  174. };
  175. static struct can_test_struct can0_test_obj = {
  176. .name = _CAN0_NAME};
  177. void can_recv_irq(void *param)
  178. {
  179. struct can_test_struct *_can_obj = (struct can_test_struct *)param;
  180. rt_kprintf("can_recv_iqr \r\n");
  181. rt_sem_release(&_can_obj->_sem);
  182. }
  183. static void rt_can_test_loopback_thread_entry(void *param)
  184. {
  185. struct can_test_struct *_can_obj = (struct can_test_struct *)param;
  186. struct FCan_Frame recv_frame;
  187. struct ft2004_can *drv_can;
  188. rt_uint32_t i;
  189. _can_obj->candev = rt_device_find(_can_obj->name);
  190. RT_ASSERT(_can_obj->candev);
  191. drv_can = (struct ft2004_can *)_can_obj->candev->user_data;
  192. rt_sem_init(&_can_obj->_sem, "canrx_wait", 0, RT_IPC_FLAG_FIFO);
  193. rt_device_open(_can_obj->candev, RT_DEVICE_OFLAG_RDWR);
  194. while (1)
  195. {
  196. rt_kprintf(" start to wait loopback \r\n");
  197. RTHW_CAN_WAIT(drv_can);
  198. while (0 != FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1))
  199. {
  200. rt_kprintf("CanId %x \r\n", recv_frame.CanId);
  201. rt_kprintf("CanDlc %x \r\n", recv_frame.CanDlc);
  202. for (i = 0; i < recv_frame.CanDlc; i++)
  203. {
  204. rt_kprintf("data [%d] %x \r\n", i, recv_frame.data[i]);
  205. }
  206. FCan_SendByIrq(&drv_can->can_handle, &recv_frame, 1, RT_NULL);
  207. }
  208. }
  209. }
  210. int rt_can0_test(void)
  211. {
  212. rt_thread_t tid;
  213. tid = rt_thread_create("can0_loopback",
  214. rt_can_test_loopback_thread_entry, &can0_test_obj,
  215. 1024, 16, 20);
  216. if (tid != RT_NULL)
  217. rt_thread_startup(tid);
  218. return 0;
  219. }
  220. INIT_APP_EXPORT(rt_can0_test);
  221. #endif
  222. #endif