1 //==========================================================================
5 // High level CAN driver
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
44 // Author(s): Uwe Kindler
45 // Contributors: Uwe Kindler
47 // Purpose: Top level CAN driver
50 //####DESCRIPTIONEND####
52 //==========================================================================
55 //==========================================================================
57 //==========================================================================
58 #include <pkgconf/io.h>
59 #include <pkgconf/io_can.h>
61 #include <cyg/io/io.h>
62 #include <cyg/io/devtab.h>
63 #include <cyg/io/can.h>
64 #include <cyg/infra/cyg_ass.h> // assertion support
65 #include <cyg/infra/diag.h> // diagnostic output
68 //==========================================================================
70 //==========================================================================
71 #ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
72 #define CYG_DRV_COND_WAIT(_cond, _time) cyg_cond_timed_wait(_cond, cyg_current_time() + (_time))
74 #define CYG_DRV_COND_WAIT(_cond, _time) cyg_drv_cond_wait(_cond)
78 //==========================================================================
80 //==========================================================================
82 // Device I/O functions
84 static Cyg_ErrNo can_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len);
85 static Cyg_ErrNo can_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len);
86 static cyg_bool can_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);
87 static Cyg_ErrNo can_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf, cyg_uint32 *len);
88 static Cyg_ErrNo can_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *xbuf, cyg_uint32 *len);
91 // Callback functions into upper layer driver
93 static void can_init(can_channel *chan);
94 static void can_rcv_event(can_channel *chan, void *pdata);
95 static void can_xmt_msg(can_channel *chan, void *pdata);
100 DEVIO_TABLE(cyg_io_can_devio,
110 // Callbacks into upper layer driver
112 CAN_CALLBACKS(cyg_io_can_callbacks,
118 //===========================================================================
119 // Initialize CAN driver
120 //===========================================================================
121 static void can_init(can_channel *chan)
130 cbuf = &chan->in_cbuf;
131 cbuf->waiting = false;
133 #ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
134 cbuf->blocking = true;
136 cyg_drv_mutex_init(&cbuf->lock);
137 cyg_drv_cond_init(&cbuf->wait, &cbuf->lock);
139 cbuf = &chan->out_cbuf;
140 cbuf->waiting = false;
142 #ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
143 cbuf->blocking = true;
145 cyg_drv_mutex_init(&cbuf->lock);
146 cyg_drv_cond_init(&cbuf->wait, &cbuf->lock);
152 //===========================================================================
153 // Write exactly one CAN message to CAN bus
154 //===========================================================================
155 static Cyg_ErrNo can_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len)
157 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
158 can_channel *chan = (can_channel *)t->priv;
159 can_lowlevel_funs *funs = chan->funs;
160 Cyg_ErrNo res = ENOERR;
161 can_cbuf_t *cbuf = &chan->out_cbuf;
162 cyg_uint32 size = *len;
165 // the user need to provide a can message buffer
167 if (*len != sizeof(cyg_can_message))
172 cyg_drv_mutex_lock(&cbuf->lock);
174 cyg_drv_dsr_lock(); // avoid race condition while testing pointers
178 if (cbuf->data_cnt == cbuf->len)
180 cbuf->waiting = true; // Buffer full - wait for space
181 funs->start_xmit(chan); // Make sure xmit is running
183 // Check flag: 'start_xmit' may have obviated the need
188 cbuf->pending += size; // Have this much more to send [eventually]
189 #if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
190 #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
192 // If timeouts are enabled and we use nonblocking calls then we
193 // can use the timeout values
197 if(!CYG_DRV_COND_WAIT(&cbuf->wait, cbuf->timeout))
201 } // if (!cbuf->blocking)#
203 #else // #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
205 // if this is a nonblocking call then we return immediatelly
214 #endif // #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
215 #endif //defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
217 if(!cyg_drv_cond_wait(&cbuf->wait))
222 cbuf->pending -= size;
226 *len -= size; // number of characters actually sent
228 cbuf->waiting = false;
231 } // if (cbuf->abort)
232 } // if (cbuf->waiting)
233 } // if (cbuf->data_cnt == cbuf->len)
237 // there is enougth space left so we can store additional data
239 CYG_CAN_MSG_T *ptxbuf = (CYG_CAN_MSG_T *)cbuf->pdata;
240 CYG_CAN_MSG_T *pbuf_message = &ptxbuf[cbuf->put];
241 cyg_can_message *pmessage = (cyg_can_message *)_buf;
243 CYG_CAN_WRITE_MSG(pbuf_message, pmessage); // copy message
245 cbuf->put = (cbuf->put + 1) % cbuf->len;
247 size -= sizeof(cyg_can_message);
249 } // while (size > 0)
251 (funs->start_xmit)(chan); // Start output as necessary
252 cyg_drv_dsr_unlock();
253 cyg_drv_mutex_unlock(&cbuf->lock);
258 //===========================================================================
259 // Read one single CAN event from hw
260 //===========================================================================
261 static Cyg_ErrNo can_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len)
263 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
264 can_channel *chan = (can_channel *)t->priv;
265 can_cbuf_t *cbuf = &chan->in_cbuf;
267 Cyg_ErrNo res = ENOERR;
270 // the user need to provide a can event buffer
272 if (*len != sizeof(cyg_can_event))
277 cyg_drv_mutex_lock(&cbuf->lock);
280 cyg_drv_dsr_lock(); // avoid race conditions
284 // if message buffer contains at least one message then read the
285 // oldest message from buffer and return
287 if (cbuf->data_cnt > 0)
289 CYG_CAN_EVENT_T *prxbuf = (CYG_CAN_EVENT_T *)cbuf->pdata;
290 CYG_CAN_EVENT_T *pbuf_event = &prxbuf[cbuf->get];
291 cyg_can_event *pevent = (cyg_can_event *)_buf;
293 CYG_CAN_READ_EVENT(pevent, pbuf_event); // copy event
295 cbuf->get = (cbuf->get + 1) % cbuf->len;
297 size += sizeof(cyg_can_event);
302 // if messaeg buffer does not contain any message, then wait until
303 // a message arrives or return immediatelly if nonblocking calls are
306 cbuf->waiting = true;
307 #if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
308 #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
310 // If timeouts are enabled and we use nonblocking calls then we
311 // can use the timeout values
315 if(!CYG_DRV_COND_WAIT(&cbuf->wait, cbuf->timeout))
319 } // if (!cbuf->blocking)#
321 #else // #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
323 // if this is a nonblocking call then we return immediatelly
332 #endif // #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
333 #endif // #if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
335 if(!cyg_drv_cond_wait(&cbuf->wait))
345 cbuf->waiting = false;
350 } // while (size < *len)
351 cyg_drv_dsr_unlock();
353 cyg_drv_mutex_unlock(&cbuf->lock);
359 //===========================================================================
360 // Query CAN channel configuration data
361 //===========================================================================
362 static Cyg_ErrNo can_get_config(cyg_io_handle_t handle,
367 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
368 can_channel *chan = (can_channel *)t->priv;
369 Cyg_ErrNo res = ENOERR;
370 cyg_can_info_t *pcan_info = (cyg_can_info_t *)xbuf;
371 can_cbuf_t *out_cbuf = &chan->out_cbuf;
372 can_cbuf_t *in_cbuf = &chan->in_cbuf;
373 can_lowlevel_funs *funs = chan->funs;
378 // query about CAN configuration like baud rate
380 case CYG_IO_GET_CONFIG_CAN_INFO :
381 if (*len < sizeof(cyg_can_info_t))
385 *pcan_info = chan->config;
386 *len = sizeof(chan->config);
389 // return rx/tx buffer sizes and counts
391 case CYG_IO_GET_CONFIG_CAN_BUFFER_INFO :
393 cyg_can_buf_info_t *pbuf_info;
394 if (*len < sizeof(cyg_can_buf_info_t))
399 *len = sizeof(cyg_can_buf_info_t);
400 pbuf_info = (cyg_can_buf_info_t *)xbuf;
401 pbuf_info->rx_bufsize = in_cbuf->len;
402 if (pbuf_info->rx_bufsize)
404 pbuf_info->rx_count = in_cbuf->data_cnt ;
408 pbuf_info->rx_count = 0;
410 pbuf_info->tx_bufsize = out_cbuf->len;
411 if (pbuf_info->tx_bufsize)
413 pbuf_info->tx_count = out_cbuf->data_cnt;
417 pbuf_info->tx_count = 0;
420 break; // case CYG_IO_GET_CONFIG_CAN_BUFFER_INFO
422 #ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
424 // return current timeouts
426 case CYG_IO_GET_CONFIG_CAN_TIMEOUT :
428 cyg_can_timeout_info_t *ptimeout_info;
429 if (*len < sizeof(cyg_can_timeout_info_t))
434 *len = sizeof(cyg_can_timeout_info_t);
435 ptimeout_info = (cyg_can_timeout_info_t *)xbuf;
437 ptimeout_info->rx_timeout = in_cbuf->timeout;
438 ptimeout_info->tx_timeout = out_cbuf->timeout;
440 break; // case CYG_IO_GET_CONFIG_CAN_TIMEOUT_INFO
441 #endif // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
443 #ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
445 // check if blocking calls are enabled
447 case CYG_IO_GET_CONFIG_READ_BLOCKING:
449 if (*len < sizeof(cyg_uint32))
453 *(cyg_uint32*)xbuf = (in_cbuf->blocking) ? 1 : 0;
458 // check if nonblocking calls are enabled
460 case CYG_IO_GET_CONFIG_WRITE_BLOCKING:
462 if (*len < sizeof(cyg_uint32))
466 *(cyg_uint32*)xbuf = (out_cbuf->blocking) ? 1 : 0;
469 #endif // CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
472 // return hardware description interface
474 case CYG_IO_GET_CONFIG_CAN_HDI :
476 cyg_can_hdi *hdi = (cyg_can_hdi *)xbuf;
477 if (*len != sizeof(cyg_can_hdi))
481 hdi = hdi; // avoid compiler warnings
482 *len = sizeof(cyg_can_hdi);
484 // pass down to low level to gather more information about
487 res = (funs->get_config)(chan, key, xbuf, len);
492 res = (funs->get_config)(chan, key, xbuf, len);
499 //===========================================================================
500 // Set CAN channel configuration
501 //===========================================================================
502 static Cyg_ErrNo can_set_config(cyg_io_handle_t handle,
507 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
508 can_channel *chan = (can_channel *)t->priv;
509 Cyg_ErrNo res = ENOERR;
510 can_lowlevel_funs *funs = chan->funs;
511 can_cbuf_t *out_cbuf = &chan->out_cbuf;
512 can_cbuf_t *in_cbuf = &chan->in_cbuf;
516 #ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
518 // Set calls to read function to blocking / nonblocking mode
520 case CYG_IO_SET_CONFIG_READ_BLOCKING:
522 if (*len < sizeof(cyg_uint32) || 0 == in_cbuf->len)
526 in_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
531 // set calls to write functions to blocking / nonblocking mode
533 case CYG_IO_SET_CONFIG_WRITE_BLOCKING:
535 if (*len < sizeof(cyg_uint32) || 0 == out_cbuf->len)
539 out_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
542 #endif // CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
544 #ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
546 // return current timeouts
548 case CYG_IO_SET_CONFIG_CAN_TIMEOUT :
550 cyg_can_timeout_info_t *ptimeout_info;
551 if (*len < sizeof(cyg_can_timeout_info_t))
556 *len = sizeof(cyg_can_timeout_info_t);
557 ptimeout_info = (cyg_can_timeout_info_t *)xbuf;
559 in_cbuf->timeout = ptimeout_info->rx_timeout;
560 out_cbuf->timeout = ptimeout_info->tx_timeout;
562 break; // case CYG_IO_GET_CONFIG_CAN_TIMEOUT_INFO
563 #endif // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
565 case CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH:
568 // Flush any buffered input
570 if (in_cbuf->len == 0)
572 break; // Nothing to do if not buffered
574 cyg_drv_mutex_lock(&in_cbuf->lock); // Stop any further input processing
576 if (in_cbuf->waiting)
578 in_cbuf->abort = true;
579 cyg_drv_cond_broadcast(&in_cbuf->wait);
580 in_cbuf->waiting = false;
582 in_cbuf->get = in_cbuf->put = in_cbuf->data_cnt = 0; // Flush buffered input
585 // Pass to the hardware driver in case it wants to flush FIFOs etc.
587 (funs->set_config)(chan,
588 CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH,
590 cyg_drv_dsr_unlock();
591 cyg_drv_mutex_unlock(&in_cbuf->lock);
592 } // CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH:
595 // flush any buffered output
597 case CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH:
599 // Throw away any pending output
600 if (out_cbuf->len == 0)
602 break; // Nothing to do if not buffered
604 cyg_drv_mutex_lock(&out_cbuf->lock); // Stop any further output processing
606 if (out_cbuf->data_cnt > 0)
608 out_cbuf->get = out_cbuf->put = out_cbuf->data_cnt = 0; // Empties queue!
609 (funs->stop_xmit)(chan); // Done with transmit
613 // Pass to the hardware driver in case it wants to flush FIFOs etc.
615 (funs->set_config)(chan,
616 CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH,
618 if (out_cbuf->waiting)
620 out_cbuf->abort = true;
621 cyg_drv_cond_broadcast(&out_cbuf->wait);
622 out_cbuf->waiting = false;
623 }// if (out_cbuf->waiting)
624 cyg_drv_dsr_unlock();
625 cyg_drv_mutex_unlock(&out_cbuf->lock);
627 break; // CYG_IO_GET_CONFIG_CAN_OUTPUT_FLUSH:
630 // wait until all messages in outbut buffer are sent
632 case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN:
634 // Wait for any pending output to complete
635 if (out_cbuf->len == 0)
637 break; // Nothing to do if not buffered
639 cyg_drv_mutex_lock(&out_cbuf->lock); // Stop any further output processing
641 while (out_cbuf->pending || (out_cbuf->data_cnt > 0))
643 out_cbuf->waiting = true;
644 if(!cyg_drv_cond_wait(&out_cbuf->wait))
649 cyg_drv_dsr_unlock();
650 cyg_drv_mutex_unlock(&out_cbuf->lock);
652 break;// CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN:
655 // Abort any outstanding I/O, including blocked reads
656 // Caution - assumed to be called from 'timeout' (i.e. DSR) code
658 case CYG_IO_SET_CONFIG_CAN_ABORT :
660 in_cbuf->abort = true;
661 cyg_drv_cond_broadcast(&in_cbuf->wait);
663 out_cbuf->abort = true;
664 cyg_drv_cond_broadcast(&out_cbuf->wait);
669 #ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK
671 // Set callback configuration
672 // To disable callback set flag_mask = 0
674 case CYG_IO_SET_CONFIG_CAN_CALLBACK:
676 if (*len != sizeof(cyg_can_callback_cfg))
681 // Copy data under DSR locking
683 chan->callback_cfg = *((cyg_can_callback_cfg*) xbuf);
684 cyg_drv_dsr_unlock();
687 #endif //CYGOPT_IO_CAN_SUPPORT_CALLBACK
691 // pass down to lower layers
693 res = (funs->set_config)(chan, key, xbuf, len);
700 //===========================================================================
701 // Select support for CAN channel
702 //===========================================================================
703 static cyg_bool can_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
706 // do nothing here because we currently do not support select
712 //===========================================================================
713 // Callback for received events
714 //===========================================================================
715 static void can_rcv_event(can_channel *chan, void *pdata)
717 can_cbuf_t *cbuf = &chan->in_cbuf;
718 CYG_CAN_EVENT_T *prxbuf = (CYG_CAN_EVENT_T *)cbuf->pdata;
719 #ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK
724 // cbuf is a ring buffer - if the buffer is full, then we overwrite the
725 // oldest message in buffer so the user will always get the actual and
726 // last state of the external hardware that is connected to the
727 // CAN bus. We need to call cyg_drv_dsr_lock() here because this function
728 // may be called from different message box interrupts and so we have to
729 // protect data access here
732 prxbuf[cbuf->put].flags = 0; // clear flags because it is a new event
733 if (chan->funs->getevent(chan, &prxbuf[cbuf->put], pdata))
735 if (cbuf->data_cnt < cbuf->len)
742 // the buffer is full but a new message arrived. We store this new
743 // message and overwrite the oldest one, but at least we tell the user
744 // that there is an overrun in RX queue
746 prxbuf[cbuf->put].flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
747 cbuf->get = (cbuf->get + 1) % cbuf->len;
750 #ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK
751 flags = prxbuf[cbuf->put].flags;
754 cbuf->put = (cbuf->put + 1) % cbuf->len;
758 cbuf->waiting = false;
759 cyg_drv_cond_broadcast(&cbuf->wait);
761 #ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK
762 // Call application callback function, if any of the flag events
764 if((flags & chan->callback_cfg.flag_mask) &&
765 (chan->callback_cfg.callback_func))
767 chan->callback_cfg.callback_func(flags,
768 chan->callback_cfg.data);
773 cyg_drv_dsr_unlock();
777 //===========================================================================
778 // Callback function for transmit events
779 //===========================================================================
780 static void can_xmt_msg(can_channel *chan, void *pdata)
782 can_cbuf_t *cbuf = &chan->out_cbuf;
783 can_lowlevel_funs *funs = chan->funs;
784 CYG_CAN_MSG_T *ptxbuf = (CYG_CAN_MSG_T *)cbuf->pdata;
785 CYG_CAN_MSG_T *pbuf_txmsg;
788 // transmit messages as long as there are messages in the buffer
790 while (cbuf->data_cnt > 0)
792 pbuf_txmsg = &ptxbuf[cbuf->get];
794 if (funs->putmsg(chan, pbuf_txmsg, pdata))
796 cbuf->get = (cbuf->get + 1) % cbuf->len;
802 // we are here because the hardware is busy at the moment and
803 // we can't send another message - now we check if there is already
804 // some space in buffer so we can wakeup the writer
806 if ((cbuf->len - cbuf->data_cnt) > 0)
810 cbuf->waiting = false;
811 cyg_drv_cond_broadcast(&cbuf->wait);
816 } // while (cbuf->data_cnt > 0)
817 funs->stop_xmit(chan); // Done with transmit
821 cbuf->waiting = false;
822 cyg_drv_cond_broadcast(&cbuf->wait);
827 //---------------------------------------------------------------------------