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