dev_can.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2015-05-14 aubrcool@qq.com first version
  9. * 2015-07-06 Bernard code cleanup and remove RT_CAN_USING_LED;
  10. */
  11. #include <rthw.h>
  12. #include <rtthread.h>
  13. #include <rtdevice.h>
  14. #define CAN_LOCK(can) rt_mutex_take(&(can->lock), RT_WAITING_FOREVER)
  15. #define CAN_UNLOCK(can) rt_mutex_release(&(can->lock))
  16. static rt_err_t rt_can_init(struct rt_device *dev)
  17. {
  18. rt_err_t result = RT_EOK;
  19. struct rt_can_device *can;
  20. RT_ASSERT(dev != RT_NULL);
  21. can = (struct rt_can_device *)dev;
  22. /* initialize rx/tx */
  23. can->can_rx = RT_NULL;
  24. can->can_tx = RT_NULL;
  25. #ifdef RT_CAN_USING_HDR
  26. can->hdr = RT_NULL;
  27. #endif
  28. /* apply configuration */
  29. if (can->ops->configure)
  30. result = can->ops->configure(can, &can->config);
  31. else
  32. result = -RT_ENOSYS;
  33. return result;
  34. }
  35. /*
  36. * can interrupt routines
  37. */
  38. rt_inline rt_ssize_t _can_int_rx(struct rt_can_device *can, struct rt_can_msg *data, rt_ssize_t msgs)
  39. {
  40. rt_ssize_t size;
  41. struct rt_can_rx_fifo *rx_fifo;
  42. RT_ASSERT(can != RT_NULL);
  43. size = msgs;
  44. rx_fifo = (struct rt_can_rx_fifo *) can->can_rx;
  45. RT_ASSERT(rx_fifo != RT_NULL);
  46. /* read from software FIFO */
  47. while (msgs / sizeof(struct rt_can_msg) > 0)
  48. {
  49. rt_base_t level;
  50. #ifdef RT_CAN_USING_HDR
  51. rt_int8_t hdr;
  52. #endif /*RT_CAN_USING_HDR*/
  53. struct rt_can_msg_list *listmsg = RT_NULL;
  54. /* disable interrupt */
  55. level = rt_hw_interrupt_disable();
  56. #ifdef RT_CAN_USING_HDR
  57. hdr = data->hdr_index;
  58. if (hdr >= 0 && can->hdr && hdr < can->config.maxhdr && !rt_list_isempty(&can->hdr[hdr].list))
  59. {
  60. listmsg = rt_list_entry(can->hdr[hdr].list.next, struct rt_can_msg_list, hdrlist);
  61. rt_list_remove(&listmsg->list);
  62. rt_list_remove(&listmsg->hdrlist);
  63. if (can->hdr[hdr].msgs)
  64. {
  65. can->hdr[hdr].msgs--;
  66. }
  67. listmsg->owner = RT_NULL;
  68. }
  69. else if (hdr == -1)
  70. #endif /*RT_CAN_USING_HDR*/
  71. {
  72. if (!rt_list_isempty(&rx_fifo->uselist))
  73. {
  74. listmsg = rt_list_entry(rx_fifo->uselist.next, struct rt_can_msg_list, list);
  75. rt_list_remove(&listmsg->list);
  76. #ifdef RT_CAN_USING_HDR
  77. rt_list_remove(&listmsg->hdrlist);
  78. if (listmsg->owner != RT_NULL && listmsg->owner->msgs)
  79. {
  80. listmsg->owner->msgs--;
  81. }
  82. listmsg->owner = RT_NULL;
  83. #endif /*RT_CAN_USING_HDR*/
  84. }
  85. else
  86. {
  87. /* no data, enable interrupt and break out */
  88. rt_hw_interrupt_enable(level);
  89. break;
  90. }
  91. }
  92. /* enable interrupt */
  93. rt_hw_interrupt_enable(level);
  94. if (listmsg != RT_NULL)
  95. {
  96. rt_memcpy(data, &listmsg->data, sizeof(struct rt_can_msg));
  97. level = rt_hw_interrupt_disable();
  98. rt_list_insert_before(&rx_fifo->freelist, &listmsg->list);
  99. rx_fifo->freenumbers++;
  100. RT_ASSERT(rx_fifo->freenumbers <= can->config.msgboxsz);
  101. rt_hw_interrupt_enable(level);
  102. listmsg = RT_NULL;
  103. }
  104. else
  105. {
  106. break;
  107. }
  108. data ++;
  109. msgs -= sizeof(struct rt_can_msg);
  110. }
  111. return (size - msgs);
  112. }
  113. rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *data, int msgs)
  114. {
  115. int size;
  116. struct rt_can_tx_fifo *tx_fifo;
  117. RT_ASSERT(can != RT_NULL);
  118. size = msgs;
  119. tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
  120. RT_ASSERT(tx_fifo != RT_NULL);
  121. while (msgs)
  122. {
  123. rt_base_t level;
  124. rt_uint32_t no;
  125. rt_uint32_t result;
  126. struct rt_can_sndbxinx_list *tx_tosnd = RT_NULL;
  127. rt_sem_take(&(tx_fifo->sem), RT_WAITING_FOREVER);
  128. level = rt_hw_interrupt_disable();
  129. tx_tosnd = rt_list_entry(tx_fifo->freelist.next, struct rt_can_sndbxinx_list, list);
  130. RT_ASSERT(tx_tosnd != RT_NULL);
  131. rt_list_remove(&tx_tosnd->list);
  132. rt_hw_interrupt_enable(level);
  133. no = ((rt_ubase_t)tx_tosnd - (rt_ubase_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list);
  134. tx_tosnd->result = RT_CAN_SND_RESULT_WAIT;
  135. rt_completion_init(&tx_tosnd->completion);
  136. if (can->ops->sendmsg(can, data, no) != RT_EOK)
  137. {
  138. /* send failed. */
  139. level = rt_hw_interrupt_disable();
  140. rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list);
  141. rt_hw_interrupt_enable(level);
  142. rt_sem_release(&(tx_fifo->sem));
  143. goto err_ret;
  144. }
  145. can->status.sndchange |= 1<<no;
  146. if (rt_completion_wait(&(tx_tosnd->completion), RT_CANSND_MSG_TIMEOUT) != RT_EOK)
  147. {
  148. level = rt_hw_interrupt_disable();
  149. rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list);
  150. can->status.sndchange &= ~ (1<<no);
  151. rt_hw_interrupt_enable(level);
  152. rt_sem_release(&(tx_fifo->sem));
  153. goto err_ret;
  154. }
  155. level = rt_hw_interrupt_disable();
  156. result = tx_tosnd->result;
  157. if (!rt_list_isempty(&tx_tosnd->list))
  158. {
  159. rt_list_remove(&tx_tosnd->list);
  160. }
  161. rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list);
  162. rt_hw_interrupt_enable(level);
  163. rt_sem_release(&(tx_fifo->sem));
  164. if (result == RT_CAN_SND_RESULT_OK)
  165. {
  166. level = rt_hw_interrupt_disable();
  167. can->status.sndpkg++;
  168. rt_hw_interrupt_enable(level);
  169. data ++;
  170. msgs -= sizeof(struct rt_can_msg);
  171. if (!msgs) break;
  172. }
  173. else
  174. {
  175. err_ret:
  176. level = rt_hw_interrupt_disable();
  177. can->status.dropedsndpkg++;
  178. rt_hw_interrupt_enable(level);
  179. break;
  180. }
  181. }
  182. return (size - msgs);
  183. }
  184. rt_inline int _can_int_tx_priv(struct rt_can_device *can, const struct rt_can_msg *data, int msgs)
  185. {
  186. int size;
  187. rt_base_t level;
  188. rt_uint32_t no, result;
  189. struct rt_can_tx_fifo *tx_fifo;
  190. RT_ASSERT(can != RT_NULL);
  191. size = msgs;
  192. tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
  193. RT_ASSERT(tx_fifo != RT_NULL);
  194. while (msgs)
  195. {
  196. no = data->priv;
  197. if (no >= can->config.sndboxnumber)
  198. {
  199. break;
  200. }
  201. level = rt_hw_interrupt_disable();
  202. if ((tx_fifo->buffer[no].result != RT_CAN_SND_RESULT_OK))
  203. {
  204. rt_hw_interrupt_enable(level);
  205. rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_WAITING_FOREVER);
  206. continue;
  207. }
  208. tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_WAIT;
  209. rt_hw_interrupt_enable(level);
  210. if (can->ops->sendmsg(can, data, no) != RT_EOK)
  211. {
  212. continue;
  213. }
  214. can->status.sndchange |= 1<<no;
  215. if (rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_CANSND_MSG_TIMEOUT) != RT_EOK)
  216. {
  217. can->status.sndchange &= ~ (1<<no);
  218. continue;
  219. }
  220. result = tx_fifo->buffer[no].result;
  221. if (result == RT_CAN_SND_RESULT_OK)
  222. {
  223. level = rt_hw_interrupt_disable();
  224. can->status.sndpkg++;
  225. rt_hw_interrupt_enable(level);
  226. data ++;
  227. msgs -= sizeof(struct rt_can_msg);
  228. if (!msgs) break;
  229. }
  230. else
  231. {
  232. level = rt_hw_interrupt_disable();
  233. can->status.dropedsndpkg++;
  234. rt_hw_interrupt_enable(level);
  235. break;
  236. }
  237. }
  238. return (size - msgs);
  239. }
  240. static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag)
  241. {
  242. struct rt_can_device *can;
  243. char tmpname[16];
  244. RT_ASSERT(dev != RT_NULL);
  245. can = (struct rt_can_device *)dev;
  246. CAN_LOCK(can);
  247. /* get open flags */
  248. dev->open_flag = oflag & 0xff;
  249. if (can->can_rx == RT_NULL)
  250. {
  251. if (oflag & RT_DEVICE_FLAG_INT_RX)
  252. {
  253. int i = 0;
  254. struct rt_can_rx_fifo *rx_fifo;
  255. rx_fifo = (struct rt_can_rx_fifo *) rt_malloc(sizeof(struct rt_can_rx_fifo) +
  256. can->config.msgboxsz * sizeof(struct rt_can_msg_list));
  257. RT_ASSERT(rx_fifo != RT_NULL);
  258. rx_fifo->buffer = (struct rt_can_msg_list *)(rx_fifo + 1);
  259. rt_memset(rx_fifo->buffer, 0, can->config.msgboxsz * sizeof(struct rt_can_msg_list));
  260. rt_list_init(&rx_fifo->freelist);
  261. rt_list_init(&rx_fifo->uselist);
  262. rx_fifo->freenumbers = can->config.msgboxsz;
  263. for (i = 0; i < can->config.msgboxsz; i++)
  264. {
  265. rt_list_insert_before(&rx_fifo->freelist, &rx_fifo->buffer[i].list);
  266. #ifdef RT_CAN_USING_HDR
  267. rt_list_init(&rx_fifo->buffer[i].hdrlist);
  268. rx_fifo->buffer[i].owner = RT_NULL;
  269. #endif
  270. }
  271. can->can_rx = rx_fifo;
  272. dev->open_flag |= RT_DEVICE_FLAG_INT_RX;
  273. /* open can rx interrupt */
  274. can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
  275. }
  276. }
  277. if (can->can_tx == RT_NULL)
  278. {
  279. if (oflag & RT_DEVICE_FLAG_INT_TX)
  280. {
  281. int i = 0;
  282. struct rt_can_tx_fifo *tx_fifo;
  283. tx_fifo = (struct rt_can_tx_fifo *) rt_malloc(sizeof(struct rt_can_tx_fifo) +
  284. can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list));
  285. RT_ASSERT(tx_fifo != RT_NULL);
  286. tx_fifo->buffer = (struct rt_can_sndbxinx_list *)(tx_fifo + 1);
  287. rt_memset(tx_fifo->buffer, 0,
  288. can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list));
  289. rt_list_init(&tx_fifo->freelist);
  290. for (i = 0; i < can->config.sndboxnumber; i++)
  291. {
  292. rt_list_insert_before(&tx_fifo->freelist, &tx_fifo->buffer[i].list);
  293. rt_completion_init(&(tx_fifo->buffer[i].completion));
  294. tx_fifo->buffer[i].result = RT_CAN_SND_RESULT_OK;
  295. }
  296. rt_sprintf(tmpname, "%stl", dev->parent.name);
  297. rt_sem_init(&(tx_fifo->sem), tmpname, can->config.sndboxnumber, RT_IPC_FLAG_FIFO);
  298. can->can_tx = tx_fifo;
  299. dev->open_flag |= RT_DEVICE_FLAG_INT_TX;
  300. /* open can tx interrupt */
  301. can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX);
  302. }
  303. }
  304. can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_CAN_INT_ERR);
  305. #ifdef RT_CAN_USING_HDR
  306. if (can->hdr == RT_NULL)
  307. {
  308. int i = 0;
  309. struct rt_can_hdr *phdr;
  310. phdr = (struct rt_can_hdr *) rt_malloc(can->config.maxhdr * sizeof(struct rt_can_hdr));
  311. RT_ASSERT(phdr != RT_NULL);
  312. rt_memset(phdr, 0, can->config.maxhdr * sizeof(struct rt_can_hdr));
  313. for (i = 0; i < can->config.maxhdr; i++)
  314. {
  315. rt_list_init(&phdr[i].list);
  316. }
  317. can->hdr = phdr;
  318. }
  319. #endif
  320. if (!can->timerinitflag)
  321. {
  322. can->timerinitflag = 1;
  323. rt_timer_start(&can->timer);
  324. }
  325. CAN_UNLOCK(can);
  326. return RT_EOK;
  327. }
  328. static rt_err_t rt_can_close(struct rt_device *dev)
  329. {
  330. struct rt_can_device *can;
  331. RT_ASSERT(dev != RT_NULL);
  332. can = (struct rt_can_device *)dev;
  333. CAN_LOCK(can);
  334. /* this device has more reference count */
  335. if (dev->ref_count > 1)
  336. {
  337. CAN_UNLOCK(can);
  338. return RT_EOK;
  339. }
  340. if (can->timerinitflag)
  341. {
  342. can->timerinitflag = 0;
  343. rt_timer_stop(&can->timer);
  344. }
  345. can->status_indicate.ind = RT_NULL;
  346. can->status_indicate.args = RT_NULL;
  347. #ifdef RT_CAN_USING_HDR
  348. if (can->hdr != RT_NULL)
  349. {
  350. rt_free(can->hdr);
  351. can->hdr = RT_NULL;
  352. }
  353. #endif
  354. if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
  355. {
  356. struct rt_can_rx_fifo *rx_fifo;
  357. /* clear can rx interrupt */
  358. can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
  359. rx_fifo = (struct rt_can_rx_fifo *)can->can_rx;
  360. RT_ASSERT(rx_fifo != RT_NULL);
  361. rt_free(rx_fifo);
  362. dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX;
  363. can->can_rx = RT_NULL;
  364. }
  365. if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
  366. {
  367. struct rt_can_tx_fifo *tx_fifo;
  368. /* clear can tx interrupt */
  369. can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_TX);
  370. tx_fifo = (struct rt_can_tx_fifo *)can->can_tx;
  371. RT_ASSERT(tx_fifo != RT_NULL);
  372. rt_sem_detach(&(tx_fifo->sem));
  373. rt_free(tx_fifo);
  374. dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX;
  375. can->can_tx = RT_NULL;
  376. }
  377. can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_CAN_INT_ERR);
  378. can->ops->control(can, RT_CAN_CMD_START, RT_FALSE);
  379. CAN_UNLOCK(can);
  380. return RT_EOK;
  381. }
  382. static rt_ssize_t rt_can_read(struct rt_device *dev,
  383. rt_off_t pos,
  384. void *buffer,
  385. rt_size_t size)
  386. {
  387. struct rt_can_device *can;
  388. RT_ASSERT(dev != RT_NULL);
  389. if (size == 0) return 0;
  390. can = (struct rt_can_device *)dev;
  391. if ((dev->open_flag & RT_DEVICE_FLAG_INT_RX) && (dev->ref_count > 0))
  392. {
  393. return _can_int_rx(can, buffer, size);
  394. }
  395. return 0;
  396. }
  397. static rt_ssize_t rt_can_write(struct rt_device *dev,
  398. rt_off_t pos,
  399. const void *buffer,
  400. rt_size_t size)
  401. {
  402. struct rt_can_device *can;
  403. RT_ASSERT(dev != RT_NULL);
  404. if (size == 0) return 0;
  405. can = (struct rt_can_device *)dev;
  406. if ((dev->open_flag & RT_DEVICE_FLAG_INT_TX) && (dev->ref_count > 0))
  407. {
  408. if (can->config.privmode)
  409. {
  410. return _can_int_tx_priv(can, buffer, size);
  411. }
  412. else
  413. {
  414. return _can_int_tx(can, buffer, size);
  415. }
  416. }
  417. return 0;
  418. }
  419. static rt_err_t rt_can_control(struct rt_device *dev,
  420. int cmd,
  421. void *args)
  422. {
  423. struct rt_can_device *can;
  424. rt_err_t res;
  425. res = RT_EOK;
  426. RT_ASSERT(dev != RT_NULL);
  427. can = (struct rt_can_device *)dev;
  428. switch (cmd)
  429. {
  430. case RT_DEVICE_CTRL_SUSPEND:
  431. /* suspend device */
  432. dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
  433. break;
  434. case RT_DEVICE_CTRL_RESUME:
  435. /* resume device */
  436. dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
  437. break;
  438. case RT_DEVICE_CTRL_CONFIG:
  439. /* configure device */
  440. res = can->ops->configure(can, (struct can_configure *)args);
  441. break;
  442. case RT_CAN_CMD_SET_PRIV:
  443. /* configure device */
  444. if ((rt_uint32_t)(rt_ubase_t)args != can->config.privmode)
  445. {
  446. int i;
  447. rt_base_t level;
  448. struct rt_can_tx_fifo *tx_fifo;
  449. res = can->ops->control(can, cmd, args);
  450. if (res != RT_EOK) return res;
  451. tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
  452. if (can->config.privmode)
  453. {
  454. for (i = 0; i < can->config.sndboxnumber; i++)
  455. {
  456. level = rt_hw_interrupt_disable();
  457. if(rt_list_isempty(&tx_fifo->buffer[i].list))
  458. {
  459. rt_sem_release(&(tx_fifo->sem));
  460. }
  461. else
  462. {
  463. rt_list_remove(&tx_fifo->buffer[i].list);
  464. }
  465. rt_hw_interrupt_enable(level);
  466. }
  467. }
  468. else
  469. {
  470. for (i = 0; i < can->config.sndboxnumber; i++)
  471. {
  472. level = rt_hw_interrupt_disable();
  473. if (tx_fifo->buffer[i].result == RT_CAN_SND_RESULT_OK)
  474. {
  475. rt_list_insert_before(&tx_fifo->freelist, &tx_fifo->buffer[i].list);
  476. }
  477. rt_hw_interrupt_enable(level);
  478. }
  479. }
  480. }
  481. break;
  482. case RT_CAN_CMD_SET_STATUS_IND:
  483. can->status_indicate.ind = ((rt_can_status_ind_type_t)args)->ind;
  484. can->status_indicate.args = ((rt_can_status_ind_type_t)args)->args;
  485. break;
  486. #ifdef RT_CAN_USING_HDR
  487. case RT_CAN_CMD_SET_FILTER:
  488. res = can->ops->control(can, cmd, args);
  489. if (res != RT_EOK || can->hdr == RT_NULL)
  490. {
  491. return res;
  492. }
  493. struct rt_can_filter_config *pfilter;
  494. struct rt_can_filter_item *pitem;
  495. rt_uint32_t count;
  496. rt_base_t level;
  497. pfilter = (struct rt_can_filter_config *)args;
  498. RT_ASSERT(pfilter);
  499. count = pfilter->count;
  500. pitem = pfilter->items;
  501. if (pfilter->actived)
  502. {
  503. while (count)
  504. {
  505. if (pitem->hdr_bank >= can->config.maxhdr || pitem->hdr_bank < 0)
  506. {
  507. count--;
  508. pitem++;
  509. continue;
  510. }
  511. level = rt_hw_interrupt_disable();
  512. if (!can->hdr[pitem->hdr_bank].connected)
  513. {
  514. rt_hw_interrupt_enable(level);
  515. rt_memcpy(&can->hdr[pitem->hdr_bank].filter, pitem,
  516. sizeof(struct rt_can_filter_item));
  517. level = rt_hw_interrupt_disable();
  518. can->hdr[pitem->hdr_bank].connected = 1;
  519. can->hdr[pitem->hdr_bank].msgs = 0;
  520. rt_list_init(&can->hdr[pitem->hdr_bank].list);
  521. }
  522. rt_hw_interrupt_enable(level);
  523. count--;
  524. pitem++;
  525. }
  526. }
  527. else
  528. {
  529. while (count)
  530. {
  531. if (pitem->hdr_bank >= can->config.maxhdr || pitem->hdr_bank < 0)
  532. {
  533. count--;
  534. pitem++;
  535. continue;
  536. }
  537. level = rt_hw_interrupt_disable();
  538. if (can->hdr[pitem->hdr_bank].connected)
  539. {
  540. can->hdr[pitem->hdr_bank].connected = 0;
  541. can->hdr[pitem->hdr_bank].msgs = 0;
  542. if (!rt_list_isempty(&can->hdr[pitem->hdr_bank].list))
  543. {
  544. rt_list_remove(can->hdr[pitem->hdr_bank].list.next);
  545. }
  546. rt_hw_interrupt_enable(level);
  547. rt_memset(&can->hdr[pitem->hdr_bank].filter, 0,
  548. sizeof(struct rt_can_filter_item));
  549. }
  550. else
  551. {
  552. rt_hw_interrupt_enable(level);
  553. }
  554. count--;
  555. pitem++;
  556. }
  557. }
  558. break;
  559. #endif /*RT_CAN_USING_HDR*/
  560. #ifdef RT_CAN_USING_BUS_HOOK
  561. case RT_CAN_CMD_SET_BUS_HOOK:
  562. can->bus_hook = (rt_can_bus_hook) args;
  563. break;
  564. #endif /*RT_CAN_USING_BUS_HOOK*/
  565. default :
  566. /* control device */
  567. if (can->ops->control != RT_NULL)
  568. {
  569. res = can->ops->control(can, cmd, args);
  570. }
  571. else
  572. {
  573. res = -RT_ENOSYS;
  574. }
  575. break;
  576. }
  577. return res;
  578. }
  579. /*
  580. * can timer
  581. */
  582. static void cantimeout(void *arg)
  583. {
  584. rt_can_t can;
  585. can = (rt_can_t)arg;
  586. RT_ASSERT(can);
  587. rt_device_control((rt_device_t)can, RT_CAN_CMD_GET_STATUS, (void *)&can->status);
  588. if (can->status_indicate.ind != RT_NULL)
  589. {
  590. can->status_indicate.ind(can, can->status_indicate.args);
  591. }
  592. #ifdef RT_CAN_USING_BUS_HOOK
  593. if(can->bus_hook)
  594. {
  595. can->bus_hook(can);
  596. }
  597. #endif /*RT_CAN_USING_BUS_HOOK*/
  598. if (can->timerinitflag == 1)
  599. {
  600. can->timerinitflag = 0xFF;
  601. }
  602. }
  603. #ifdef RT_USING_DEVICE_OPS
  604. const static struct rt_device_ops can_device_ops =
  605. {
  606. rt_can_init,
  607. rt_can_open,
  608. rt_can_close,
  609. rt_can_read,
  610. rt_can_write,
  611. rt_can_control
  612. };
  613. #endif
  614. /*
  615. * can register
  616. */
  617. rt_err_t rt_hw_can_register(struct rt_can_device *can,
  618. const char *name,
  619. const struct rt_can_ops *ops,
  620. void *data)
  621. {
  622. struct rt_device *device;
  623. RT_ASSERT(can != RT_NULL);
  624. device = &(can->parent);
  625. device->type = RT_Device_Class_CAN;
  626. device->rx_indicate = RT_NULL;
  627. device->tx_complete = RT_NULL;
  628. #ifdef RT_CAN_USING_HDR
  629. can->hdr = RT_NULL;
  630. #endif
  631. can->can_rx = RT_NULL;
  632. can->can_tx = RT_NULL;
  633. rt_mutex_init(&(can->lock), "can", RT_IPC_FLAG_PRIO);
  634. #ifdef RT_CAN_USING_BUS_HOOK
  635. can->bus_hook = RT_NULL;
  636. #endif /*RT_CAN_USING_BUS_HOOK*/
  637. #ifdef RT_USING_DEVICE_OPS
  638. device->ops = &can_device_ops;
  639. #else
  640. device->init = rt_can_init;
  641. device->open = rt_can_open;
  642. device->close = rt_can_close;
  643. device->read = rt_can_read;
  644. device->write = rt_can_write;
  645. device->control = rt_can_control;
  646. #endif
  647. can->ops = ops;
  648. can->status_indicate.ind = RT_NULL;
  649. can->status_indicate.args = RT_NULL;
  650. rt_memset(&can->status, 0, sizeof(can->status));
  651. device->user_data = data;
  652. can->timerinitflag = 0;
  653. rt_timer_init(&can->timer,
  654. name,
  655. cantimeout,
  656. (void *)can,
  657. can->config.ticks,
  658. RT_TIMER_FLAG_PERIODIC);
  659. /* register a character device */
  660. return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
  661. }
  662. /* ISR for can interrupt */
  663. void rt_hw_can_isr(struct rt_can_device *can, int event)
  664. {
  665. switch (event & 0xff)
  666. {
  667. case RT_CAN_EVENT_RXOF_IND:
  668. {
  669. rt_base_t level;
  670. level = rt_hw_interrupt_disable();
  671. can->status.dropedrcvpkg++;
  672. rt_hw_interrupt_enable(level);
  673. }
  674. case RT_CAN_EVENT_RX_IND:
  675. {
  676. struct rt_can_msg tmpmsg;
  677. struct rt_can_rx_fifo *rx_fifo;
  678. struct rt_can_msg_list *listmsg = RT_NULL;
  679. #ifdef RT_CAN_USING_HDR
  680. rt_int8_t hdr;
  681. #endif
  682. int ch = -1;
  683. rt_base_t level;
  684. rt_uint32_t no;
  685. rx_fifo = (struct rt_can_rx_fifo *)can->can_rx;
  686. RT_ASSERT(rx_fifo != RT_NULL);
  687. /* interrupt mode receive */
  688. RT_ASSERT(can->parent.open_flag & RT_DEVICE_FLAG_INT_RX);
  689. no = event >> 8;
  690. ch = can->ops->recvmsg(can, &tmpmsg, no);
  691. if (ch == -1) break;
  692. /* disable interrupt */
  693. level = rt_hw_interrupt_disable();
  694. can->status.rcvpkg++;
  695. can->status.rcvchange = 1;
  696. if (!rt_list_isempty(&rx_fifo->freelist))
  697. {
  698. listmsg = rt_list_entry(rx_fifo->freelist.next, struct rt_can_msg_list, list);
  699. rt_list_remove(&listmsg->list);
  700. #ifdef RT_CAN_USING_HDR
  701. rt_list_remove(&listmsg->hdrlist);
  702. if (listmsg->owner != RT_NULL && listmsg->owner->msgs)
  703. {
  704. listmsg->owner->msgs--;
  705. }
  706. listmsg->owner = RT_NULL;
  707. #endif /*RT_CAN_USING_HDR*/
  708. RT_ASSERT(rx_fifo->freenumbers > 0);
  709. rx_fifo->freenumbers--;
  710. }
  711. else if (!rt_list_isempty(&rx_fifo->uselist))
  712. {
  713. listmsg = rt_list_entry(rx_fifo->uselist.next, struct rt_can_msg_list, list);
  714. can->status.dropedrcvpkg++;
  715. rt_list_remove(&listmsg->list);
  716. #ifdef RT_CAN_USING_HDR
  717. rt_list_remove(&listmsg->hdrlist);
  718. if (listmsg->owner != RT_NULL && listmsg->owner->msgs)
  719. {
  720. listmsg->owner->msgs--;
  721. }
  722. listmsg->owner = RT_NULL;
  723. #endif
  724. }
  725. /* enable interrupt */
  726. rt_hw_interrupt_enable(level);
  727. if (listmsg != RT_NULL)
  728. {
  729. rt_memcpy(&listmsg->data, &tmpmsg, sizeof(struct rt_can_msg));
  730. level = rt_hw_interrupt_disable();
  731. rt_list_insert_before(&rx_fifo->uselist, &listmsg->list);
  732. #ifdef RT_CAN_USING_HDR
  733. hdr = tmpmsg.hdr_index;
  734. if (can->hdr != RT_NULL)
  735. {
  736. RT_ASSERT(hdr < can->config.maxhdr && hdr >= 0);
  737. if (can->hdr[hdr].connected)
  738. {
  739. rt_list_insert_before(&can->hdr[hdr].list, &listmsg->hdrlist);
  740. listmsg->owner = &can->hdr[hdr];
  741. can->hdr[hdr].msgs++;
  742. }
  743. }
  744. #endif
  745. rt_hw_interrupt_enable(level);
  746. }
  747. /* invoke callback */
  748. #ifdef RT_CAN_USING_HDR
  749. if (can->hdr != RT_NULL && can->hdr[hdr].connected && can->hdr[hdr].filter.ind)
  750. {
  751. rt_size_t rx_length;
  752. RT_ASSERT(hdr < can->config.maxhdr && hdr >= 0);
  753. level = rt_hw_interrupt_disable();
  754. rx_length = can->hdr[hdr].msgs * sizeof(struct rt_can_msg);
  755. rt_hw_interrupt_enable(level);
  756. if (rx_length)
  757. {
  758. can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length);
  759. }
  760. }
  761. else
  762. #endif
  763. {
  764. if (can->parent.rx_indicate != RT_NULL)
  765. {
  766. rt_size_t rx_length;
  767. level = rt_hw_interrupt_disable();
  768. /* get rx length */
  769. rx_length = rt_list_len(&rx_fifo->uselist)* sizeof(struct rt_can_msg);
  770. rt_hw_interrupt_enable(level);
  771. if (rx_length)
  772. {
  773. can->parent.rx_indicate(&can->parent, rx_length);
  774. }
  775. }
  776. }
  777. break;
  778. }
  779. case RT_CAN_EVENT_TX_DONE:
  780. case RT_CAN_EVENT_TX_FAIL:
  781. {
  782. struct rt_can_tx_fifo *tx_fifo;
  783. rt_uint32_t no;
  784. no = event >> 8;
  785. tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
  786. RT_ASSERT(tx_fifo != RT_NULL);
  787. if (can->status.sndchange&(1<<no))
  788. {
  789. if ((event & 0xff) == RT_CAN_EVENT_TX_DONE)
  790. {
  791. tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_OK;
  792. }
  793. else
  794. {
  795. tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_ERR;
  796. }
  797. rt_completion_done(&(tx_fifo->buffer[no].completion));
  798. }
  799. break;
  800. }
  801. }
  802. }
  803. #ifdef RT_USING_FINSH
  804. #include <finsh.h>
  805. int cmd_canstat(int argc, void **argv)
  806. {
  807. static const char *ErrCode[] =
  808. {
  809. "No Error!",
  810. "Warning !",
  811. "Passive !",
  812. "Bus Off !"
  813. };
  814. if (argc >= 2)
  815. {
  816. struct rt_can_status status;
  817. rt_device_t candev = rt_device_find(argv[1]);
  818. if (!candev)
  819. {
  820. rt_kprintf(" Can't find can device %s\n", argv[1]);
  821. return -1;
  822. }
  823. rt_kprintf(" Found can device: %s...", argv[1]);
  824. rt_device_control(candev, RT_CAN_CMD_GET_STATUS, &status);
  825. rt_kprintf("\n Receive...error..count: %010ld. Send.....error....count: %010ld.",
  826. status.rcverrcnt, status.snderrcnt);
  827. rt_kprintf("\n Bit..pad..error..count: %010ld. Format...error....count: %010ld",
  828. status.bitpaderrcnt, status.formaterrcnt);
  829. rt_kprintf("\n Ack.......error..count: %010ld. Bit......error....count: %010ld.",
  830. status.ackerrcnt, status.biterrcnt);
  831. rt_kprintf("\n CRC.......error..count: %010ld. Error.code.[%010ld]: ",
  832. status.crcerrcnt, status.errcode);
  833. switch (status.errcode)
  834. {
  835. case 0:
  836. rt_kprintf("%s.", ErrCode[0]);
  837. break;
  838. case 1:
  839. rt_kprintf("%s.", ErrCode[1]);
  840. break;
  841. case 2:
  842. case 3:
  843. rt_kprintf("%s.", ErrCode[2]);
  844. break;
  845. case 4:
  846. case 5:
  847. case 6:
  848. case 7:
  849. rt_kprintf("%s.", ErrCode[3]);
  850. break;
  851. }
  852. rt_kprintf("\n Total.receive.packages: %010ld. Dropped.receive.packages: %010ld.",
  853. status.rcvpkg, status.dropedrcvpkg);
  854. rt_kprintf("\n Total..send...packages: %010ld. Dropped...send..packages: %010ld.\n",
  855. status.sndpkg + status.dropedsndpkg, status.dropedsndpkg);
  856. }
  857. else
  858. {
  859. rt_kprintf(" Invalid Call %s\n", argv[0]);
  860. rt_kprintf(" Please using %s cannamex .Here canname is driver name and x is candrive number.\n", argv[0]);
  861. }
  862. return 0;
  863. }
  864. MSH_CMD_EXPORT_ALIAS(cmd_canstat, canstat, stat can device status);
  865. #endif