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

📄 can_lpc2xxx.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
        // configuration
        //
        case CYGNUM_CAN_MSGBUF_RESET_ALL :
             {
                 lpc2xxx_can_config_rx_none(chan);
             }
             break;

        //
        // setup driver for reception of all standard and extended messages
        //
        case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL :
             {
                 if (!(info->flags & INFO_FLAG_RX_ALL)) // if rx_all is enabled we do not need to do anything
                 {
                    lpc2xxx_can_config_rx_all(chan);  // setup RX all state
                 }
             }
             break;
        
        //
        // add single message filter, message with filter ID will be received
        //     
        case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD :
             {
                 cyg_can_filter *filter   = (cyg_can_filter*) buf;
                 
                 //
                 // if the acceptance filter is configured to receive all messages then 
                 // it is not allowed to add single message filters because then more 
                 // than one acceptance filter would receive the same CAN id
                 //
                 if (info->flags & INFO_FLAG_RX_ALL)
                 {
                    return -EPERM;
                 }
                 
                 //
                 // try to allocate a free acceptance filter entry - if we have a free one
                 // then we can prepare the acceptance filter table for reception of
                 // this message
                 //
                 if (!lpc2xxx_can_add_rx_filter(info, filter))
                 {
                     return -EPERM;
                 }
             }
             break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD
             

#ifdef CYGOPT_IO_CAN_REMOTE_BUF
        //
        // Try to add a new RTR response message buffer for automatic transmisson
        // of data frame on reception of a remote frame
        //
        case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD :
             {
                 // $$$$ TODO implement remote repsonse buffers in software
                 return -ENOSUPP;
             }
             break;
                     
        //
        // write data into remote response buffer
        //
        case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE :
             {
                 // $$$$ TODO implement remote response buffers in software
                 return -ENOSUPP;
             }
             break;
#endif // #ifdef CYGOPT_IO_CAN_REMOTE_BUF
        default:
            return -EINVAL;
    } // switch (buf->cfg_id)
    
    return res;
}
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG


//===========================================================================
// Read state of CAN controller
// The CAN state variable for each channel is modiefied by DSR so if we 
// read the state we need to lock DSRs to protect the data access
//===========================================================================
static cyg_can_state lpc2xxx_get_state(lpc2xxx_can_info_t *info)
{
    cyg_can_state result;
    
    cyg_drv_dsr_lock();
    result = info->state;
    cyg_drv_dsr_unlock();
    
    return result;
}


//===========================================================================
// Set state of CAN controller
// The CAN state variable for each channel is modiefied by DSR so if we 
// write the state we need to lock DSRs to protect the data access
//===========================================================================
static void lpc2xxx_set_state(lpc2xxx_can_info_t *info, cyg_can_state state)
{   
    cyg_drv_dsr_lock();
    info->state = state;
    cyg_drv_dsr_unlock();
}


//===========================================================================
// Enter low power mode
//===========================================================================
static Cyg_ErrNo lpc2xxx_enter_lowpower_mode(can_channel *chan)
{
    cyg_uint32          regval;
    lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
    
    //
    // Before we enter low power mode, we have to enable wake up interrupt
    // Normally this interrupt is always enabled so we do not need to do
    // anything here
    //
    HAL_READ_UINT32(CAN_CTRL_MOD(info), regval); 
    
    //
    // Software can only set SM when RM in the CAN Mode register is 0
    //
    if (regval & CANMOD_RESET)
    {
        return -EPERM;
    }
    
    //regval &= CANMOD_SLEEP;
    lpc2xxx_set_state(info, CYGNUM_CAN_STATE_STANDBY);
    HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_SLEEP); 
    return ENOERR;
}


//===========================================================================
// Start CAN module - set CANMOD operational and enable all interrupts
//===========================================================================
static void lpc2xxx_start_module(can_channel *chan)
{
    cyg_uint32          regval;
    lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
    
    HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_OPERATIONAL);  
    //
    // The interrupt enable register is also modified by ISR and DSR so
    // we need to protect acces here
    //
    cyg_drv_isr_lock();
    HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
    regval = regval | IER_RX | CAN_MISC_INT;           // enable all interrupts     
    HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval); 
    info->state = CYGNUM_CAN_STATE_ACTIVE; 
    cyg_drv_isr_unlock();
}


//===========================================================================
// Enter reset mode
//===========================================================================
static void lpc2xx_enter_reset_mode(can_channel *chan)
{
    lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;  
    
    info->state = CYGNUM_CAN_STATE_STOPPED;
    HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET);
}


#ifdef CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
//===========================================================================
// Add message filter group
//===========================================================================
static Cyg_ErrNo lpc2xxx_can_config_accfilt_group(can_channel *chan, const void* buf, cyg_uint32* len)
{
    bool                     res;
    cyg_can_filtergroup_cfg *filter_grp = (cyg_can_filtergroup_cfg *)buf;
    lpc2xxx_can_info_t      *info = (lpc2xxx_can_info_t *)chan->dev_priv; 
    
    
    if (*len != sizeof(cyg_can_filtergroup_cfg))
    {
        return -EINVAL;
    }
    
    if (filter_grp->lower_id_bound >= filter_grp->upper_id_bound)
    {
        return -EINVAL;
    }
    
    //
    // if the acceptance filter is configured to receive all messages then 
    // it is not allowed to add single message filter groups because then more 
    // than one acceptance filter would receive the same CAN id
    //
    if (info->flags & INFO_FLAG_RX_ALL)
    {
        return -EPERM;
    }
    
    res = lpc2xxx_can_accfilt_add(info, 
                                  filter_grp->lower_id_bound, 
                                  filter_grp->upper_id_bound, 
                                  filter_grp->ext);
    
    
    return res ? ENOERR : -EPERM;
}
#endif // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS


//===========================================================================
// Change device configuration
//===========================================================================
static Cyg_ErrNo lpc2xxx_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
{
    Cyg_ErrNo  res = ENOERR;
    
    switch (key)
    {   
        //
        // Setup a new CAN configuration. This will i.e. setup a new baud rate
        //
        case CYG_IO_SET_CONFIG_CAN_INFO:
             {
                 cyg_can_info_t*  config = (cyg_can_info_t*) buf;
                 if (*len < sizeof(cyg_can_info_t))
                 {
                     return -EINVAL;
                 }
                 *len = sizeof(cyg_can_info_t);
                 if (!lpc2xxx_can_config_channel(chan, config, false))
                 {
                     return -EINVAL;
                 }
             }
             break;

#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG            
        //
        // configure message buffers
        //
        case CYG_IO_SET_CONFIG_CAN_MSGBUF :
             {               
                res = lpc2xxx_can_config_msgbuf(chan, buf, len);
             }
             break;
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
         
#ifdef CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
        //
        // Add message filter group to acceptance filter
        //
        case CYG_IO_SET_CONFIG_LPC2XXX_ACCFILT_GROUP :
             {
                 return lpc2xxx_can_config_accfilt_group(chan, buf, len);
             }
             break;
#endif // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS 
                        
        //
        // Change CAN state of CAN module
        //    
        case CYG_IO_SET_CONFIG_CAN_MODE :
             {
                cyg_can_mode   *can_mode  = (cyg_can_mode*) buf;
                
                if (*len != sizeof(cyg_can_mode)) 
                {
                    return -EINVAL;
                }
                *len = sizeof(cyg_can_mode);
                
                //
                // decide what to do acording to mode
                //
                switch (*can_mode)
                {
                    //
                    // The controller does not support a stopped and standby state so we
                    // simply enter the low power state here. This state is also safe for
                    // message buffer configuration
                    //
                    case CYGNUM_CAN_MODE_STOP :    lpc2xx_enter_reset_mode(chan);     break; 
                    case CYGNUM_CAN_MODE_START :   lpc2xxx_start_module(chan);        break;                       
                    case CYGNUM_CAN_MODE_STANDBY : lpc2xxx_enter_lowpower_mode(chan); break;
                    case CYGNUM_CAN_MODE_CONFIG :  lpc2xx_enter_reset_mode(chan);     break;
                }
             }
             break; // case CYG_IO_SET_CONFIG_CAN_MODE :
        //
        // Unknown config key - indicate this by returning -EINVAL
        //
        default:
                    return -EINVAL;
    } // switch (key)
    
    return res;
}


//===========================================================================
// Query device configuration
//===========================================================================
static Cyg_ErrNo lpc2xxx_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
{
    Cyg_ErrNo            res  = ENOERR;
    lpc2xxx_can_info_t  *info = (lpc2xxx_can_info_t *)chan->dev_priv;
    
    switch(key)
    {
        //
        // query state of CAN controller
        //
        case CYG_IO_GET_CONFIG_CAN_STATE :
             {
                cyg_can_state *can_state  = (cyg_can_state*) buf;
                
                if (*len != sizeof(cyg_can_state)) 
                {
                    return -EINVAL;
                }
                *len = sizeof(cyg_can_state);
                *can_state = lpc2xxx_get_state(info);
             }
             break;

#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG       
        //
        // Query message box information - returns available and free message
        // boxes
        //     
        case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO :

⌨️ 快捷键说明

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