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

📄 can_at91sam7.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
        for (i = (CAN_MBOX_RX_CNT - info->free_mboxes); i <= CAN_MBOX_RX_MAX; ++i)
        {
            cyg_uint32 mmr;
            HAL_READ_UINT32(CAN_MB_MMR(info, i), mmr);
            if ((mmr & MMR_MB_TYPE_BITMASK) == MMR_MB_TYPE_DISABLED)
            {
                info->free_mboxes--;
                res = i;
                break;
            }             
        }
    } // if (info->free_mboxes)
    
    return res;
}
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG


#ifdef CYGOPT_IO_CAN_REMOTE_BUF
//===========================================================================
// Setup a RTR response message box
//===========================================================================
static bool at91sam7_can_setup_rtrmbox(can_channel      *chan,
                                       cyg_uint32        mbox,
                                       cyg_can_message  *pmsg,
                                       bool              init)
{
    CAN_DECLARE_INFO(chan);
    cyg_uint32 mcr;

    //
    // To prevent concurrent access with the internal CAN core, the application
    // must disable the mailbox before writing to CAN_MIDx registers - so we
    // do this here
    //
    if (init)
    {
        if (pmsg->ext)
        {
            at91sam7_can_setup_mbox(chan, mbox, MID_SET_EXT(pmsg->id), MAM_SET_EXT, MMR_MB_TYPE_PRODUCE); 
        }
        else
        {
            at91sam7_can_setup_mbox(chan, mbox, MID_SET_STD(pmsg->id), MAM_SET_STD, MMR_MB_TYPE_PRODUCE);    
        }   
        HAL_WRITE_UINT32(CAN_IER(info), 0x01 << mbox); // enable interrupt
    }
    else
    {
        cyg_uint32 msr;
        //
        // Check if this message box is ready for transmission or if it still transmits
        // a message - we read the MSR register to check the ready flag
        //
        HAL_READ_UINT32(CAN_MB_MSR(info, mbox), msr);    
        if (!(msr & MSR_RDY))
        {
            AT91SAM7_DBG_PRINT("(RTR) !MSR_RDY\n");
            return false;
        }
    }
    
    HAL_WRITE_UINT32(CAN_MB_MDL(info, mbox), pmsg->data.dwords[0]); // set data
    HAL_WRITE_UINT32(CAN_MB_MDH(info, mbox), pmsg->data.dwords[1]); // set data
    mcr = (pmsg->dlc << MCR_DLC_SHIFTER) | MCR_TRANSFER_CMD;        // set data lengt and transfer request
    HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), mcr);                  // transfer request    
    return true;
}
#endif // CYGOPT_IO_CAN_REMOTE_BUF


#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
//===========================================================================
// Configure message buffers
//===========================================================================
static Cyg_ErrNo at91sam7_can_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf)
{
    Cyg_ErrNo             res  = ENOERR;
    at91sam7_can_info_t *info = (at91sam7_can_info_t *)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 :
             {
                 at91sam7_can_config_rx_none(chan);
             }
             break;

        //
        // setup AT91SAM7 CAN module 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
                 {
                    at91sam7_can_mbox_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 AT91SAM7 CAN module 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 = at91sam7_can_alloc_mbox(info);
                 if (filter->handle > CYGNUM_CAN_MSGBUF_NA)
                 {
                     at91sam7_can_add_rx_filter(chan, filter->handle, &filter->msg);
                 }
             }
             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 :
             {
                 cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;
                 rtr_buf->handle = at91sam7_can_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
                     //
                     at91sam7_can_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg, true);
                 }
             }
             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 <= CAN_MBOX_RX_MAX))
                 {
                      if (!at91sam7_can_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg, false))
                      {
                          res = -EAGAIN;
                      }
                 }
                 else
                 {
                    res = -EINVAL;
                 }  
             }
             break;
#endif // #ifdef CYGOPT_IO_CAN_REMOTE_BUF
    } // 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 at91sam7_get_state(at91sam7_can_info_t *info)
{
    cyg_can_state result;
    
    cyg_drv_dsr_lock();
    result = info->state;
    cyg_drv_dsr_unlock();
    
    return result;
}


//===========================================================================
// Enter low power mode
// Before stopping the CAN clock (PMC), the CAN Controller must be in 
// Low-power Mode to complete the current transfer. After restarting the 
// clock, the application must disable the Low-power Mode of the 
// CAN controller. If the power mode is entered, a sleep interrupt is 
// generated.
//===========================================================================
static void at91sam7_enter_lowpower_mode(can_channel *chan)
{
    CAN_DECLARE_INFO(chan);
    
    
    cyg_uint32 mr;
    HAL_READ_UINT32(CAN_MR(info), mr);
    HAL_WRITE_UINT32(CAN_MR(info), mr | MR_LOW_POWER); 
    HAL_WRITE_UINT32(CAN_IER(info), INT_SLEEP);
}


//===========================================================================
// Start CAN module (or leave the low power mode)
// If the CAN module is in STANDBY state then we enable the module clock
// and leave the low power mode by clearing the low power flag.
//===========================================================================
static void at91sam7_start_module(can_channel *chan)
{
    CAN_DECLARE_INFO(chan);
    cyg_uint32           mr;
    
    HAL_WRITE_UINT32(CAN_IER(info), INT_DEFAULT);                  // enable wakeup interrupt 
    HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, 1 << CAN_PID(info));  // restart peripheral clock
    HAL_READ_UINT32(CAN_MR(info), mr);                             
    mr &= ~MR_LOW_POWER ;
    HAL_WRITE_UINT32(CAN_MR(info), mr | MR_CAN_ENABLE);            // clear the low power flag to leave standby     
}

//===========================================================================
// Change device configuration
//===========================================================================
static Cyg_ErrNo at91sam7_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 (!at91sam7_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 :
             {
                cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *)buf;

                if (*len != sizeof(cyg_can_msgbuf_cfg))
                {
                    return -EINVAL;
                }
                
                res = at91sam7_can_set_config_msgbuf(chan, msg_buf);
             }
             break;
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
             
        //
        // Change CAN state of AT91SAM7 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 :    at91sam7_enter_lowpower_mode(chan); break; 
                    case CYGNUM_CAN_MODE_START :   at91sam7_start_module(chan);        break;                       
                    case CYGNUM_CAN_MODE_STANDBY : at91sam7_enter_lowpower_mode(chan); break;
                    case CYGNUM_CAN_MODE_CONFIG :  at91sam7_enter_lowpower_mode(chan); break;
                }
             }
             break; // case CYG_IO_SET_CONFIG_CAN_MODE :         
    } // switch (key)
    
    return res;

⌨️ 快捷键说明

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