drv_can.c 14 KB

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