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