//
// there is enougth space left so we can store additional data
//
- cyg_can_message *ptxbuf = (cyg_can_message *)cbuf->pdata;
- cyg_can_message *pbuf_message = &ptxbuf[cbuf->put];
+ CYG_CAN_MSG_T *ptxbuf = (CYG_CAN_MSG_T *)cbuf->pdata;
+ CYG_CAN_MSG_T *pbuf_message = &ptxbuf[cbuf->put];
cyg_can_message *pmessage = (cyg_can_message *)_buf;
- *pbuf_message = *pmessage; // copy message
-
+ CYG_CAN_WRITE_MSG(pbuf_message, pmessage); // copy message
+
cbuf->put = (cbuf->put + 1) % cbuf->len;
cbuf->data_cnt++;
size -= sizeof(cyg_can_message);
//
if (cbuf->data_cnt > 0)
{
- cyg_can_event *prxbuf = (cyg_can_event *)cbuf->pdata;
- cyg_can_event *pbuf_event = &prxbuf[cbuf->get];
- cyg_can_event *pevent = (cyg_can_event *)_buf;
-
- *pevent = *pbuf_event; // copy event
+ CYG_CAN_EVENT_T *prxbuf = (CYG_CAN_EVENT_T *)cbuf->pdata;
+ CYG_CAN_EVENT_T *pbuf_event = &prxbuf[cbuf->get];
+ cyg_can_event *pevent = (cyg_can_event *)_buf;
+
+ CYG_CAN_READ_EVENT(pevent, pbuf_event); // copy event
cbuf->get = (cbuf->get + 1) % cbuf->len;
cbuf->data_cnt--;
cyg_can_info_t *pcan_info = (cyg_can_info_t *)xbuf;
can_cbuf_t *out_cbuf = &chan->out_cbuf;
can_cbuf_t *in_cbuf = &chan->in_cbuf;
+ can_lowlevel_funs *funs = chan->funs;
switch (key)
{
+ //
+ // query about CAN configuration like baud rate
+ //
case CYG_IO_GET_CONFIG_CAN_INFO :
if (*len < sizeof(cyg_can_info_t))
{
#endif // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
#ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+ //
+ // check if blocking calls are enabled
+ //
case CYG_IO_GET_CONFIG_READ_BLOCKING:
{
if (*len < sizeof(cyg_uint32))
}
break;
+ //
+ // check if nonblocking calls are enabled
+ //
case CYG_IO_GET_CONFIG_WRITE_BLOCKING:
{
if (*len < sizeof(cyg_uint32))
break;
#endif // CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+ //
+ // return hardware description interface
+ //
+ case CYG_IO_GET_CONFIG_CAN_HDI :
+ {
+ cyg_can_hdi *hdi = (cyg_can_hdi *)xbuf;
+ if (*len != sizeof(cyg_can_hdi))
+ {
+ return -EINVAL;
+ }
+ hdi = hdi; // avoid compiler warnings
+ *len = sizeof(cyg_can_hdi);
+ //
+ // pass down to low level to gather more information about
+ // CAN hardware
+ //
+ res = (funs->get_config)(chan, key, xbuf, len);
+ }
+ break;
+
default:
- res = -EINVAL;
+ res = (funs->get_config)(chan, key, xbuf, len);
} // switch (key)
return res;
switch (key)
{
#ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+ //
+ // Set calls to read function to blocking / nonblocking mode
+ //
case CYG_IO_SET_CONFIG_READ_BLOCKING:
{
if (*len < sizeof(cyg_uint32) || 0 == in_cbuf->len)
in_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
}
break;
-
+
+ //
+ // set calls to write functions to blocking / nonblocking mode
+ //
case CYG_IO_SET_CONFIG_WRITE_BLOCKING:
{
if (*len < sizeof(cyg_uint32) || 0 == out_cbuf->len)
}
break; // case CYG_IO_GET_CONFIG_CAN_TIMEOUT_INFO
#endif // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+
+ case CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH:
+ {
+ //
+ // Flush any buffered input
+ //
+ if (in_cbuf->len == 0)
+ {
+ break; // Nothing to do if not buffered
+ }
+ cyg_drv_mutex_lock(&in_cbuf->lock); // Stop any further input processing
+ cyg_drv_dsr_lock();
+ if (in_cbuf->waiting)
+ {
+ in_cbuf->abort = true;
+ cyg_drv_cond_broadcast(&in_cbuf->wait);
+ in_cbuf->waiting = false;
+ }
+ in_cbuf->get = in_cbuf->put = in_cbuf->data_cnt = 0; // Flush buffered input
+
+ //
+ // Pass to the hardware driver in case it wants to flush FIFOs etc.
+ //
+ (funs->set_config)(chan,
+ CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH,
+ NULL, NULL);
+ cyg_drv_dsr_unlock();
+ cyg_drv_mutex_unlock(&in_cbuf->lock);
+ } // CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH:
+
+ //
+ // flush any buffered output
+ //
+ case CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH:
+ {
+ // Throw away any pending output
+ if (out_cbuf->len == 0)
+ {
+ break; // Nothing to do if not buffered
+ }
+ cyg_drv_mutex_lock(&out_cbuf->lock); // Stop any further output processing
+ cyg_drv_dsr_lock();
+ if (out_cbuf->data_cnt > 0)
+ {
+ out_cbuf->get = out_cbuf->put = out_cbuf->data_cnt = 0; // Empties queue!
+ (funs->stop_xmit)(chan); // Done with transmit
+ }
+
+ //
+ // Pass to the hardware driver in case it wants to flush FIFOs etc.
+ //
+ (funs->set_config)(chan,
+ CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH,
+ NULL, NULL);
+ if (out_cbuf->waiting)
+ {
+ out_cbuf->abort = true;
+ cyg_drv_cond_broadcast(&out_cbuf->wait);
+ out_cbuf->waiting = false;
+ }// if (out_cbuf->waiting)
+ cyg_drv_dsr_unlock();
+ cyg_drv_mutex_unlock(&out_cbuf->lock);
+ }
+ break; // CYG_IO_GET_CONFIG_CAN_OUTPUT_FLUSH:
+
+ //
+ // wait until all messages in outbut buffer are sent
+ //
+ case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN:
+ {
+ // Wait for any pending output to complete
+ if (out_cbuf->len == 0)
+ {
+ break; // Nothing to do if not buffered
+ }
+ cyg_drv_mutex_lock(&out_cbuf->lock); // Stop any further output processing
+ cyg_drv_dsr_lock();
+ while (out_cbuf->pending || (out_cbuf->data_cnt > 0))
+ {
+ out_cbuf->waiting = true;
+ if(!cyg_drv_cond_wait(&out_cbuf->wait))
+ {
+ res = -EINTR;
+ }
+ }
+ cyg_drv_dsr_unlock();
+ cyg_drv_mutex_unlock(&out_cbuf->lock);
+ }
+ break;// CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN:
+
+ //
+ // Abort any outstanding I/O, including blocked reads
+ // Caution - assumed to be called from 'timeout' (i.e. DSR) code
+ //
+ case CYG_IO_SET_CONFIG_CAN_ABORT :
+ {
+ in_cbuf->abort = true;
+ cyg_drv_cond_broadcast(&in_cbuf->wait);
+
+ out_cbuf->abort = true;
+ cyg_drv_cond_broadcast(&out_cbuf->wait);
+ }
+ break;
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK
+ //
+ // Set callback configuration
+ // To disable callback set flag_mask = 0
+ //
+ case CYG_IO_SET_CONFIG_CAN_CALLBACK:
+ {
+ if (*len != sizeof(cyg_can_callback_cfg))
+ {
+ return -EINVAL;
+ }
+
+ // Copy data under DSR locking
+ cyg_drv_dsr_lock();
+ chan->callback_cfg = *((cyg_can_callback_cfg*) xbuf);
+ cyg_drv_dsr_unlock();
+ }
+ break;
+#endif //CYGOPT_IO_CAN_SUPPORT_CALLBACK
+
default:
//
// pass down to lower layers
//===========================================================================
static void can_rcv_event(can_channel *chan, void *pdata)
{
- can_cbuf_t *cbuf = &chan->in_cbuf;
- cyg_can_event *prxbuf = (cyg_can_event *)cbuf->pdata;
+ can_cbuf_t *cbuf = &chan->in_cbuf;
+ CYG_CAN_EVENT_T *prxbuf = (CYG_CAN_EVENT_T *)cbuf->pdata;
+#ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK
+ cyg_uint16 flags;
+#endif
//
// cbuf is a ring buffer - if the buffer is full, then we overwrite the
// oldest message in buffer so the user will always get the actual and
// last state of the external hardware that is connected to the
- // CAN bus.
+ // CAN bus. We need to call cyg_drv_dsr_lock() here because this function
+ // may be called from different message box interrupts and so we have to
+ // protect data access here
//
+ cyg_drv_dsr_lock();
+ prxbuf[cbuf->put].flags = 0; // clear flags because it is a new event
if (chan->funs->getevent(chan, &prxbuf[cbuf->put], pdata))
{
if (cbuf->data_cnt < cbuf->len)
prxbuf[cbuf->put].flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
cbuf->get = (cbuf->get + 1) % cbuf->len;
}
-
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK
+ flags = prxbuf[cbuf->put].flags;
+#endif
+
cbuf->put = (cbuf->put + 1) % cbuf->len;
if (cbuf->waiting)
cbuf->waiting = false;
cyg_drv_cond_broadcast(&cbuf->wait);
}
+#ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK
+ // Call application callback function, if any of the flag events
+ // are unmasked.
+ if((flags & chan->callback_cfg.flag_mask) &&
+ (chan->callback_cfg.callback_func))
+ {
+ chan->callback_cfg.callback_func(flags,
+ chan->callback_cfg.data);
+ }
+#endif
}
+
+ cyg_drv_dsr_unlock();
}
{
can_cbuf_t *cbuf = &chan->out_cbuf;
can_lowlevel_funs *funs = chan->funs;
- cyg_can_message *ptxbuf = (cyg_can_message *)cbuf->pdata;
- cyg_can_message *pbuf_txmsg;
+ CYG_CAN_MSG_T *ptxbuf = (CYG_CAN_MSG_T *)cbuf->pdata;
+ CYG_CAN_MSG_T *pbuf_txmsg;
//
// transmit messages as long as there are messages in the buffer