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