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