can_mcf52xx.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,632 行 · 第 1/5 页

C
1,632
字号
        //
    // We need to receive all available CAN messages so we have to set the acceptance filter
    // properly
    //
    flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  FLEXCAN_ACCEPTANCE_MASK_RX_ALL,  CYGNUM_CAN_ID_EXT);
    flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT);
    info->free_mboxes = FLEXCAN_MBOX_RX_CNT - info->mboxes_rx_all_cnt;
    info->rx_all = true;

    //
    // now finally setup the first active message boxes and enable ist
        //     
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
    if (info->mboxes_std_cnt)
             { 
        flexcan_setup_rxmbox_circbuf(&info->rxmbox_std_circbuf);
        flexcan_enable_rxmbox(chan, 0);
    }
#endif // CYGOPT_IO_CAN_STD_CAN_ID
                             
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
    if (info->mboxes_ext_cnt)
                 {
        flexcan_setup_rxmbox_circbuf(&info->rxmbox_ext_circbuf);
        flexcan_enable_rxmbox(chan, info->mboxes_std_cnt);
                 }
#endif // CYGOPT_IO_CAN_EXT_CAN_ID

}

//===========================================================================
// Setup Flex CAN moduls in a state where all message boxes are disabled
// After this call single message filters and buffers can be added
//===========================================================================
static void flexcan_config_rx_none(can_channel *chan)
{
    flexcan_info       *info = (flexcan_info *)chan->dev_priv;
    flexcan_regs       *flexcan = (flexcan_regs *)info->base;
    cyg_int8           i;
                 
                 //
    // setup all RX messages moxes into a disabled state
                 //
    for (i = 0; i < FLEXCAN_MBOX_RX_CNT; ++i)
                 {
        flexcan_disable_mbox(chan, i);
    }
                     
    //
    // If we want to receive only certain CAN identiffiers then the ID does matter and
    // we have to setup the acceptance mask properly
    //
    flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  FLEXCAN_ACCEPTANCE_MASK_RX_ID,  CYGNUM_CAN_ID_EXT);
    flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID,  CYGNUM_CAN_ID_EXT);
    info->free_mboxes = FLEXCAN_MBOX_RX_CNT;
    info->rx_all = false;
}


//===========================================================================
// Configure message buffers
//===========================================================================
static Cyg_ErrNo flexcan_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf)
{
    Cyg_ErrNo     res = ENOERR;
    flexcan_info *info = (flexcan_info *)chan->dev_priv;

    switch (buf->cfg_id)
                     {
                         //
        // clear all message filters and remote buffers - prepare for message buffer
        // configuration
                         //
        case CYGNUM_CAN_MSGBUF_RESET_ALL :
                     {
                 flexcan_config_rx_none(chan);
                     }
            break;

                     //
        // setup FlexCAN modul for reception of all standard and extended messages
                     //
        case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL :
                     {
                if (!info->rx_all) // if rx_all is enabled we do not need to do anything
                     {
                    flexcan_config_rx_none(chan); // set into default state
                    flexcan_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 FlexCAN is configured to receive all messages then it is not
                 // allowed to add single message filters because then more than
                 // one message buffer would receive the same CAN id
                 //
                 if (info->rx_all)
                 {
                    return -EPERM;
                 }
                 
                 //
                 // try to allocate a free message box - if we have a free one
                 // then we can prepare the message box for reception of the
                 // desired message id
                 //
                 filter->handle = flexcan_alloc_mbox(info);
                 if (filter->handle > CYGNUM_CAN_MSGBUF_NA)
                 {
                     flexcan_setup_rxmbox(chan, filter->handle, &flexcan_mbox_rx_filt_isr, &filter->msg, true, true);
                 }
             }
             break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD

                     //
        // 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 :
                     {
                 cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;
                 rtr_buf->handle = flexcan_alloc_mbox(info);
                     
                 if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA)
                     {
                     //
                     // if we have a free message buffer then we setup this buffer
                     // for remote frame reception
                     //
                     flexcan_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg);
                 }
                     }
             break;
                     
                     //
        // write data into remote response buffer
        //
        case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE :
             {
                 cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;

                 //
                 // If we have a valid rtr buf handle then we can store data into
                 // rtr message box
                     // 
                 if ((rtr_buf->handle >= 0) && (rtr_buf->handle <= FLEXCAN_MBOX_RX_MAX))
                 {
                     flexcan_regs *flexcan = (flexcan_regs *)info->base;
                     flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true);
                 }
                 else
                 {
                    return -EINVAL;
                 }    
             }
             break;
    } // switch (buf->cfg_id)
        
     return res;
}

//===========================================================================
// Set device configuration
//===========================================================================
static Cyg_ErrNo
flexcan_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 (!flexcan_config(chan, config, false))
                 {
                    return -EINVAL;
                     }
                 }
            break;
                 
                 //
        // configure message buffers
                 //
        case CYG_IO_SET_CONFIG_CAN_MSGBUF :
             {
                cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *) buf;

                if (*len != sizeof(cyg_can_msgbuf_cfg))
                {
                    return -EINVAL;
                }

                flexcan_set_config_msgbuf(chan, msg_buf);
             }
             break;
        
        //
        // Change CAN state of FlexCAN modul. This function will set the FlexCAN
        // modul into STOPPED, ACTIVE or STANDBY state
        //    
        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)
                {
                    case CYGNUM_CAN_MODE_STOP :      // stop FlexCANm modul
                         flexcan_stop_chip(chan);
                         break;
                         
                    case CYGNUM_CAN_MODE_START :     // start FlexCAN modul
                         flexcan_leave_standby(chan);
                         break;
                          
                    case CYGNUM_CAN_MODE_STANDBY :   // set FlexCAN modul into standby state
                         flexcan_enter_standby(chan, true);
                         break;
                         
                    case CYGNUM_CAN_MODE_CONFIG : // stop FlexCAN modul for configuration
                    	 flexcan_stop_chip(chan);
                    	 break;
                }
             }
             break; // case CYG_IO_SET_CONFIG_CAN_MODE :         
    } // switch (key)
    
    return res;
}


//===========================================================================
//  Query device configuration
//===========================================================================
static Cyg_ErrNo
flexcan_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
{
    Cyg_ErrNo     res  = ENOERR;
    flexcan_info *info = (flexcan_info *)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 = info->state;
             }
             break;
        
        //
        // Query message box information - returns available and free message
        // boxes
        //     
        case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO :
             {
                 cyg_can_msgbuf_info *mbox_info  = (cyg_can_msgbuf_info*) buf;
                
                 if (*len != sizeof(cyg_can_msgbuf_info)) 
                 {
                     return -EINVAL;
                 }
                *len = sizeof(cyg_can_msgbuf_info);
                
                 mbox_info->count = FLEXCAN_MBOX_RX_CNT;
                 mbox_info->free  = info->free_mboxes;
             }
             break;
        
        //
        // Query hardware description of FlexCAN device driver
        //     
        case CYG_IO_GET_CONFIG_CAN_HDI :
             {
                cyg_can_hdi *hdi = (cyg_can_hdi *)buf;
                //
                // comes from high level driver so we do not need to
                // check buffer size here
                //             
                hdi->support_flags = CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE
                                   | CYGNUM_CAN_HDI_FULLCAN;
#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP 
                hdi->support_flags |= CYGNUM_CAN_HDI_TIMESTAMP;
#endif
             }
             break;
             
        default :
            res = -EINVAL;
    }// switch(key)
    
    return res;
} 

⌨️ 快捷键说明

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