⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
                {
                    pbuf_info->tx_count = 0;
                }
            }
            break; // case CYG_IO_GET_CONFIG_CAN_BUFFER_INFO

#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS            
            //
            // return current timeouts
            //
            case CYG_IO_GET_CONFIG_CAN_TIMEOUT :
                 {
                     cyg_can_timeout_info_t *ptimeout_info;
                     if (*len < sizeof(cyg_can_timeout_info_t))
                     {
                         return -EINVAL; 
                     } 
                     
                     *len = sizeof(cyg_can_timeout_info_t);
                      ptimeout_info = (cyg_can_timeout_info_t *)xbuf;
                      
                      ptimeout_info->rx_timeout = in_cbuf->timeout;
                      ptimeout_info->tx_timeout = out_cbuf->timeout;
                 }
                 break; // case CYG_IO_GET_CONFIG_CAN_TIMEOUT_INFO
#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)) 
                     {
                         return -EINVAL;
                     }
                     *(cyg_uint32*)xbuf = (in_cbuf->blocking) ? 1 : 0;
                 }
                 break;

            //
            // check if nonblocking calls are enabled
            // 
            case CYG_IO_GET_CONFIG_WRITE_BLOCKING:
                 {
                     if (*len < sizeof(cyg_uint32))
                     {
                         return -EINVAL;
                     }
                     *(cyg_uint32*)xbuf = (out_cbuf->blocking) ? 1 : 0;
                 }
                 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 = (funs->get_config)(chan, key, xbuf, len);
    } // switch (key)
    
    return res;
}


//===========================================================================
// Set CAN channel configuration
//===========================================================================
static Cyg_ErrNo can_set_config(cyg_io_handle_t handle, 
               cyg_uint32      key,
               const void     *xbuf, 
               cyg_uint32     *len)
{
    cyg_devtab_entry_t *t         = (cyg_devtab_entry_t *)handle;
    can_channel        *chan      = (can_channel *)t->priv;
    Cyg_ErrNo           res       = ENOERR;
    can_lowlevel_funs  *funs      = chan->funs;
    can_cbuf_t         *out_cbuf  = &chan->out_cbuf;
    can_cbuf_t         *in_cbuf   = &chan->in_cbuf;
    
    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) 
                 {
                     return -EINVAL;
                 }
                 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) 
                 {
                     return -EINVAL;
                 }
                 out_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
             }
             break;
#endif // CYGOPT_IO_CAN_SUPPORT_NONBLOCKING

#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS            
        //
        // return current timeouts
        //
        case CYG_IO_SET_CONFIG_CAN_TIMEOUT :
             {
                 cyg_can_timeout_info_t *ptimeout_info;
                 if (*len < sizeof(cyg_can_timeout_info_t))
                 {
                     return -EINVAL; 
                 } 
                   
                 *len = sizeof(cyg_can_timeout_info_t);
                  ptimeout_info = (cyg_can_timeout_info_t *)xbuf;
                   
                  in_cbuf->timeout = ptimeout_info->rx_timeout;
                  out_cbuf->timeout = ptimeout_info->tx_timeout;
             }
             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
            //
            res = (funs->set_config)(chan, key, xbuf, len);
    } // switch (key)
    
    return res;
}


//===========================================================================
// Select support for CAN channel
//===========================================================================
static cyg_bool can_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
{
    //
    // do nothing here because we currently do not support select
    //
    return true;
}


//===========================================================================
// Callback for received events
//===========================================================================
static void can_rcv_event(can_channel *chan, void *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. 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)
        {
            cbuf->data_cnt++;
        }
        else
        {
            //
            // the buffer is full but a new message arrived. We store this new
            // message and overwrite the oldest one, but at least we tell the user
            // that there is an overrun in RX queue
            //
            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();
}


//===========================================================================
// Callback function for transmit events
//===========================================================================
static void can_xmt_msg(can_channel *chan, void *pdata)
{
    can_cbuf_t        *cbuf    = &chan->out_cbuf;
    can_lowlevel_funs *funs    = chan->funs;  
    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 
    //
    while (cbuf->data_cnt > 0)
    {
        pbuf_txmsg = &ptxbuf[cbuf->get];
        
        if (funs->putmsg(chan, pbuf_txmsg, pdata))
        {
            cbuf->get = (cbuf->get + 1) % cbuf->len;
            cbuf->data_cnt--;
        }
        else
        {
            //
            // we are here because the hardware is busy at the moment and
            // we can't send another message - now we check if there is already
            // some space in buffer so we can wakeup the writer
            //
            if ((cbuf->len - cbuf->data_cnt) > 0)
            {
                if (cbuf->waiting)
                {
                    cbuf->waiting = false;
                    cyg_drv_cond_broadcast(&cbuf->wait);
                }
            }
            return;
        }
    } // while (cbuf->data_cnt > 0)
    funs->stop_xmit(chan);  // Done with transmit
    
    if (cbuf->waiting)
    {
        cbuf->waiting = false;
        cyg_drv_cond_broadcast(&cbuf->wait);
    }            
}


//---------------------------------------------------------------------------
// end of can.c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -