drv_can.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-01-06 sundm75 first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <board.h>
  13. #include <rthw.h>
  14. #include <drv_can.h>
  15. #include "ls1c.h"
  16. #include "../libraries/ls1c_public.h"
  17. #include "../libraries/ls1c_regs.h"
  18. #include "../libraries/ls1c_clock.h"
  19. #include "../libraries/ls1c_can.h"
  20. #include "../libraries/ls1c_pin.h"
  21. #ifdef RT_USING_CAN
  22. CanRxMsg RxMessage;
  23. struct ls1c_bxcan
  24. {
  25. CAN_TypeDef *reg;
  26. void * irq;
  27. };
  28. static rt_err_t bxmodifyfilter(struct ls1c_bxcan *pbxcan, struct rt_can_filter_item *pitem, rt_uint32_t actived)
  29. {
  30. rt_int32_t fcase;
  31. rt_err_t res;
  32. rt_int32_t hdr, fbase, foff;
  33. CAN_TypeDef* CANx;
  34. CANx = pbxcan->reg;
  35. /*pitem->mode 1-掩码模式; 0- 滤波器模式 SJA1000中使用以下方式*/
  36. /*SJA1000中AFM 1-单滤波器模式; 0- 双滤波器模式 */
  37. fcase = pitem->mode;/*1-单滤波器模式; 0- 双滤波器模式*/
  38. {
  39. if (!actived)
  40. {
  41. return RT_EOK;
  42. }
  43. else if (pitem->hdr == -1)
  44. {
  45. res = -1;
  46. if (res != RT_EOK)
  47. {
  48. return res;
  49. }
  50. }
  51. else if (pitem->hdr >= 0)
  52. {
  53. rt_enter_critical();
  54. res = RT_EOK;
  55. if (res != RT_EOK)
  56. {
  57. return res;
  58. }
  59. hdr = pitem->hdr;
  60. rt_exit_critical();
  61. }
  62. }
  63. CAN_FilterInitTypeDef CAN_FilterInitStruct;
  64. unsigned char ide, rtr, id , idmask, mode;
  65. ide = (unsigned char) pitem->ide;
  66. rtr = (unsigned char) pitem->rtr;
  67. id = pitem->id;
  68. idmask = pitem->mask;
  69. mode = (unsigned char) pitem->mode;
  70. CAN_FilterInitStruct.IDE = ide;
  71. CAN_FilterInitStruct.RTR = rtr;
  72. CAN_FilterInitStruct.ID = id;
  73. CAN_FilterInitStruct.IDMASK = idmask;
  74. CAN_FilterInitStruct.MODE = mode;
  75. CAN_FilterInit(CANx, &CAN_FilterInitStruct);
  76. return RT_EOK;
  77. }
  78. static rt_err_t setfilter(struct ls1c_bxcan *pbxcan, struct rt_can_filter_config *pconfig)
  79. {
  80. struct rt_can_filter_item *pitem = pconfig->items;
  81. rt_uint32_t count = pconfig->count;
  82. rt_err_t res;
  83. while (count)
  84. {
  85. res = bxmodifyfilter(pbxcan, pitem, pconfig->actived);
  86. if (res != RT_EOK)
  87. {
  88. return res;
  89. }
  90. pitem++;
  91. count--;
  92. }
  93. return RT_EOK;
  94. }
  95. static void bxcan0_filter_init(struct rt_can_device *can)
  96. {
  97. struct ls1c_bxcan *pbxcan;
  98. pbxcan = (struct ls1c_bxcan *) can->parent.user_data;
  99. }
  100. static void bxcan1_filter_init(struct rt_can_device *can)
  101. {
  102. struct ls1c_bxcan *pbxcan;
  103. pbxcan = (struct ls1c_bxcan *) can->parent.user_data;
  104. }
  105. static void bxcan_init(CAN_TypeDef *pcan, rt_uint32_t baud, rt_uint32_t mode)
  106. {
  107. CAN_InitTypeDef CAN_InitStructure;
  108. Ls1c_CanBPS_t bps ;
  109. switch(baud)
  110. {
  111. case CAN1MBaud:
  112. bps = LS1C_CAN1MBaud;
  113. break;
  114. case CAN800kBaud:
  115. bps = LS1C_CAN800kBaud;
  116. break;
  117. case CAN500kBaud:
  118. bps = LS1C_CAN500kBaud;
  119. break;
  120. case CAN250kBaud:
  121. bps = LS1C_CAN250kBaud;
  122. break;
  123. case CAN125kBaud:
  124. bps = LS1C_CAN125kBaud;
  125. break;
  126. case CAN50kBaud:
  127. bps = LS1C_CAN40kBaud;
  128. break;
  129. default:
  130. bps = LS1C_CAN250kBaud;
  131. break;
  132. }
  133. switch (mode)
  134. {
  135. case RT_CAN_MODE_NORMAL:
  136. CAN_InitStructure.CAN_Mode = 0x00;
  137. break;
  138. case RT_CAN_MODE_LISEN:
  139. CAN_InitStructure.CAN_Mode = CAN_Mode_LOM;
  140. break;
  141. case RT_CAN_MODE_LOOPBACK:
  142. CAN_InitStructure.CAN_Mode = CAN_Mode_STM;
  143. break;
  144. case RT_CAN_MODE_LOOPBACKANLISEN:
  145. CAN_InitStructure.CAN_Mode = CAN_Mode_STM|CAN_Mode_LOM;
  146. break;
  147. }
  148. CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
  149. switch (bps)
  150. {
  151. case LS1C_CAN1MBaud:
  152. CAN_InitStructure.CAN_Prescaler = 9;
  153. CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
  154. CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  155. break;
  156. case LS1C_CAN800kBaud:
  157. CAN_InitStructure.CAN_Prescaler = 8;
  158. CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq;
  159. CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  160. break;
  161. case LS1C_CAN500kBaud:
  162. CAN_InitStructure.CAN_Prescaler = 9;
  163. CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq;
  164. CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  165. break;
  166. case LS1C_CAN250kBaud:
  167. CAN_InitStructure.CAN_Prescaler = 36;
  168. CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
  169. CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  170. break;
  171. case LS1C_CAN125kBaud:
  172. CAN_InitStructure.CAN_Prescaler = 36;
  173. CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq;
  174. CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  175. break;
  176. case LS1C_CAN100kBaud:
  177. CAN_InitStructure.CAN_Prescaler = 63;
  178. CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq;
  179. CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  180. break;
  181. case LS1C_CAN50kBaud:
  182. CAN_InitStructure.CAN_Prescaler = 63;
  183. CAN_InitStructure.CAN_BS1 = CAN_BS1_16tq;
  184. CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;
  185. break;
  186. default: //250K
  187. CAN_InitStructure.CAN_Prescaler = 36;
  188. CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
  189. CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  190. break;
  191. }
  192. CAN_Init(pcan, &CAN_InitStructure);
  193. }
  194. #ifdef USING_BXCAN0
  195. static void bxcan0_hw_init(void)
  196. {
  197. pin_set_purpose(54, PIN_PURPOSE_OTHER);
  198. pin_set_purpose(55, PIN_PURPOSE_OTHER);
  199. pin_set_remap(54, PIN_REMAP_THIRD);
  200. pin_set_remap(55, PIN_REMAP_THIRD);
  201. }
  202. #endif
  203. #ifdef USING_BXCAN1
  204. static void bxcan1_hw_init(void)
  205. {
  206. pin_set_purpose(56, PIN_PURPOSE_OTHER);
  207. pin_set_purpose(57, PIN_PURPOSE_OTHER);
  208. pin_set_remap(56, PIN_REMAP_THIRD);
  209. pin_set_remap(57, PIN_REMAP_THIRD);
  210. }
  211. #endif
  212. static rt_err_t configure(struct rt_can_device *can, struct can_configure *cfg)
  213. {
  214. CAN_TypeDef *pbxcan;
  215. pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg;
  216. if (pbxcan == CAN0)
  217. {
  218. #ifdef USING_BXCAN0
  219. bxcan0_hw_init();
  220. bxcan_init(pbxcan, cfg->baud_rate, cfg->mode);
  221. #endif
  222. }
  223. else if (pbxcan == CAN1)
  224. {
  225. #ifdef USING_BXCAN1
  226. bxcan1_hw_init();
  227. bxcan_init(pbxcan, cfg->baud_rate, cfg->mode);
  228. #endif
  229. }
  230. return RT_EOK;
  231. }
  232. static rt_err_t control(struct rt_can_device *can, int cmd, void *arg)
  233. {
  234. struct ls1c_bxcan *pbxcan;
  235. rt_uint32_t argval;
  236. pbxcan = (struct ls1c_bxcan *) can->parent.user_data;
  237. switch (cmd)
  238. {
  239. case RT_CAN_CMD_SET_FILTER:
  240. return setfilter(pbxcan, (struct rt_can_filter_config *) arg);
  241. break;
  242. case RT_CAN_CMD_SET_MODE:
  243. argval = (rt_uint32_t) arg;
  244. if (argval != RT_CAN_MODE_NORMAL ||
  245. argval != RT_CAN_MODE_LISEN ||
  246. argval != RT_CAN_MODE_LOOPBACK ||
  247. argval != RT_CAN_MODE_LOOPBACKANLISEN)
  248. {
  249. return RT_ERROR;
  250. }
  251. if (argval != can->config.mode)
  252. {
  253. can->config.mode = argval;
  254. return CAN_SetMode(pbxcan->reg, argval);
  255. }
  256. break;
  257. case RT_CAN_CMD_SET_BAUD:
  258. argval = (rt_uint32_t) arg;
  259. if (argval != CAN1MBaud &&
  260. argval != CAN800kBaud &&
  261. argval != CAN500kBaud &&
  262. argval != CAN250kBaud &&
  263. argval != CAN125kBaud &&
  264. argval != CAN100kBaud &&
  265. argval != CAN50kBaud )
  266. {
  267. return RT_ERROR;
  268. }
  269. if (argval != can->config.baud_rate)
  270. {
  271. can->config.baud_rate = argval;
  272. Ls1c_CanBPS_t bps;
  273. switch(argval)
  274. {
  275. case CAN1MBaud:
  276. bps = LS1C_CAN1MBaud;
  277. break;
  278. case CAN800kBaud:
  279. bps = LS1C_CAN800kBaud;
  280. break;
  281. case CAN500kBaud:
  282. bps = LS1C_CAN500kBaud;
  283. break;
  284. case CAN250kBaud:
  285. bps = LS1C_CAN250kBaud;
  286. break;
  287. case CAN125kBaud:
  288. bps = LS1C_CAN125kBaud;
  289. break;
  290. case CAN50kBaud:
  291. bps = LS1C_CAN40kBaud;
  292. break;
  293. default:
  294. bps = LS1C_CAN250kBaud;
  295. break;
  296. }
  297. return CAN_SetBps( pbxcan->reg, bps);
  298. }
  299. break;
  300. case RT_CAN_CMD_GET_STATUS:
  301. {
  302. rt_uint32_t errtype;
  303. errtype = pbxcan->reg->RXERR;
  304. can->status.rcverrcnt = errtype ;
  305. errtype = pbxcan->reg->TXERR;
  306. can->status.snderrcnt = errtype ;
  307. errtype = pbxcan->reg->ECC;
  308. can->status.errcode = errtype ;
  309. if (arg != &can->status)
  310. {
  311. rt_memcpy(arg, &can->status, sizeof(can->status));
  312. }
  313. }
  314. break;
  315. }
  316. return RT_EOK;
  317. }
  318. static int sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno)
  319. {
  320. CAN_TypeDef *pbxcan;
  321. CanTxMsg TxMessage;
  322. struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
  323. int i;
  324. pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg;
  325. TxMessage.StdId = pmsg->id;
  326. TxMessage.ExtId = pmsg->id;
  327. TxMessage.RTR = pmsg->rtr;
  328. TxMessage.IDE = pmsg->ide;
  329. TxMessage.DLC = pmsg->len;
  330. for( i=0; i<TxMessage.DLC ;i++)
  331. {
  332. TxMessage.Data[i] = pmsg->data[i];
  333. }
  334. CAN_Transmit(pbxcan, &TxMessage);
  335. return RT_EOK;
  336. }
  337. static int recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno)
  338. {
  339. CAN_TypeDef *pbxcan;
  340. struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
  341. int i;
  342. pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg;
  343. pmsg->ide = (rt_uint32_t) RxMessage.IDE;
  344. if(RxMessage.IDE == 1)
  345. pmsg->id = RxMessage.ExtId;
  346. else
  347. pmsg->id = RxMessage.StdId;
  348. pmsg->len = RxMessage.DLC;
  349. pmsg->rtr = RxMessage.RTR;
  350. pmsg->hdr = 0;
  351. for(i= 0;i< RxMessage.DLC; i++)
  352. {
  353. pmsg->data[i] = RxMessage.Data[i];
  354. }
  355. return RT_EOK;
  356. }
  357. static const struct rt_can_ops canops =
  358. {
  359. configure,
  360. control,
  361. sendmsg,
  362. recvmsg,
  363. };
  364. #ifdef USING_BXCAN0
  365. struct rt_can_device bxcan0;
  366. void ls1c_can0_irqhandler(int irq, void *param)
  367. {
  368. CAN_TypeDef* CANx;
  369. unsigned char status;
  370. CANx = CAN0;
  371. /*读寄存器清除中断*/
  372. status = CANx->IR;
  373. /*接收中断*/
  374. if (( status & CAN_IR_RI) == CAN_IR_RI)
  375. {
  376. /*清除RI 中断*/
  377. CAN_Receive(CANx, &RxMessage);
  378. CANx->CMR |= CAN_CMR_RRB;
  379. CANx->CMR |= CAN_CMR_CDO;
  380. rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_RX_IND);
  381. rt_kprintf("\r\nCan0 int RX happened!\r\n");
  382. }
  383. /*发送中断*/
  384. else if (( status & CAN_IR_TI) == CAN_IR_TI)
  385. {
  386. rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_TX_DONE | 0 << 8);
  387. rt_kprintf("\r\nCan0 int TX happened!\r\n");
  388. }
  389. /*数据溢出中断*/
  390. else if (( status & CAN_IR_DOI) == CAN_IR_DOI)
  391. {
  392. rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_RXOF_IND);
  393. rt_kprintf("\r\nCan0 int RX OF happened!\r\n");
  394. }
  395. }
  396. static struct ls1c_bxcan bxcan0data =
  397. {
  398. .reg = CAN0,
  399. .irq = ls1c_can0_irqhandler,
  400. };
  401. #endif /*USING_BXCAN0*/
  402. #ifdef USING_BXCAN1
  403. struct rt_can_device bxcan1;
  404. void ls1c_can1_irqhandler(int irq, void *param)
  405. {
  406. CAN_TypeDef* CANx;
  407. unsigned char status;
  408. CANx = CAN1;
  409. /*读寄存器清除中断*/
  410. status = CANx->IR;
  411. /*接收中断*/
  412. if (( status & CAN_IR_RI) == CAN_IR_RI)
  413. {
  414. /*清除RI 中断*/
  415. CAN_Receive(CANx, &RxMessage);
  416. CANx->CMR |= CAN_CMR_RRB;
  417. CANx->CMR |= CAN_CMR_CDO;
  418. rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_RX_IND);
  419. rt_kprintf("\r\nCan1 int RX happened!\r\n");
  420. }
  421. /*发送中断*/
  422. else if (( status & CAN_IR_TI) == CAN_IR_TI)
  423. {
  424. rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_TX_DONE | 0 << 8);
  425. rt_kprintf("\r\nCan1 int TX happened!\r\n");
  426. }
  427. /*数据溢出中断*/
  428. else if (( status & CAN_IR_DOI) == CAN_IR_DOI)
  429. {
  430. rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_RXOF_IND);
  431. rt_kprintf("\r\nCan1 int RX OF happened!\r\n");
  432. }
  433. }
  434. static struct ls1c_bxcan bxcan1data =
  435. {
  436. .reg = CAN1,
  437. .irq = ls1c_can1_irqhandler,
  438. };
  439. #endif /*USING_BXCAN1*/
  440. int ls1c_bxcan_init(void)
  441. {
  442. #ifdef USING_BXCAN0
  443. bxcan0.config.baud_rate = CAN250kBaud;
  444. bxcan0.config.msgboxsz = 1;
  445. bxcan0.config.sndboxnumber = 1;
  446. bxcan0.config.mode = RT_CAN_MODE_NORMAL;
  447. bxcan0.config.privmode = 0;
  448. bxcan0.config.ticks = 50;
  449. #ifdef RT_CAN_USING_HDR
  450. bxcan0.config.maxhdr = 2;
  451. #endif
  452. rt_hw_can_register(&bxcan0, "bxcan0", &canops, &bxcan0data);
  453. rt_kprintf("\r\ncan0 register! \r\n");
  454. rt_hw_interrupt_install(LS1C_CAN0_IRQ,( rt_isr_handler_t)bxcan0data.irq , RT_NULL, "can0");
  455. rt_hw_interrupt_umask(LS1C_CAN0_IRQ);
  456. #endif
  457. #ifdef USING_BXCAN1
  458. bxcan1.config.baud_rate = CAN250kBaud;
  459. bxcan1.config.msgboxsz = 1;
  460. bxcan1.config.sndboxnumber = 1;
  461. bxcan1.config.mode = RT_CAN_MODE_NORMAL;
  462. bxcan1.config.privmode = 0;
  463. bxcan1.config.ticks = 50;
  464. #ifdef RT_CAN_USING_HDR
  465. bxcan1.config.maxhdr = 2;
  466. #endif
  467. rt_hw_can_register(&bxcan1, "bxcan1", &canops, &bxcan1data);
  468. rt_kprintf("\r\ncan1 register! \r\n");
  469. rt_hw_interrupt_install(LS1C_CAN1_IRQ,( rt_isr_handler_t)bxcan1data.irq , RT_NULL, "can1");
  470. rt_hw_interrupt_umask(LS1C_CAN1_IRQ);
  471. #endif
  472. return RT_EOK;
  473. }
  474. INIT_BOARD_EXPORT(ls1c_bxcan_init);
  475. #endif /*RT_USING_CAN*/