xref: /nrf52832-nimble/rt-thread/components/drivers/can/can.c (revision 104654410c56c573564690304ae786df310c91fc)
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