can_mcf52xx.c

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

C
1,632
字号
}


//===========================================================================
// Enable hardware message box for reception
//===========================================================================
static __inline__  void flexcan_hwmbox_enable_rx(flexcan_regs *flexcan, cyg_uint32 mbox_id)
{
    HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_EMPTY);
}


//===========================================================================
// Disable hardware message box
//===========================================================================
static __inline__  void flexcan_hwmbox_disable(flexcan_regs *flexcan, cyg_uint32 mbox_id)
{
    HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_NOT_ACTIVE);
}


//===========================================================================
// lock mbox by reading control status register
//===========================================================================
static __inline__  void flexcan_hwmbox_lock(flexcan_regs *flexcan, cyg_uint32 mbox_id, cyg_uint8 *pctrlstat)
{
    HAL_READ_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), *pctrlstat); // this read will lock the mbox
}


//===========================================================================
//  Enable message box interrupt for one message box
//===========================================================================
static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id)
{
    flexcan_regs *flexcan = (flexcan_regs *)info->base;
    
    info->imask_shadow |= (0x0001 << mbox_id);
    HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
}


//===========================================================================
//  Disable message box interrupt for one message box
//===========================================================================
static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id)
{
    flexcan_regs *flexcan = (flexcan_regs *)info->base;
    
    info->imask_shadow &= ~(0x0001 << mbox_id);
    HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
}


//===========================================================================
// Allocate message box
// Try to find a free message box and return its ID
//===========================================================================
static cyg_int8 flexcan_alloc_mbox(flexcan_info *info)
{
    cyg_uint8     i;
    cyg_int8      res = CYGNUM_CAN_MSGBUF_NA;
    
    if (info->free_mboxes)
    {  
        for (i = (FLEXCAN_MBOX_RX_CNT - info->free_mboxes); i <= FLEXCAN_MBOX_RX_MAX; ++i)
        {
            if (MBOX_STATE_DISABLED == info->mboxes[i].state)
            {
                info->free_mboxes--;
                res = i;
                break;
            }               
        }
    } // if (info->free_mboxes)
    
    return res;
}


//===========================================================================
// Enable a previously configured rx mbox - a mbox ready to recive
//===========================================================================
static void flexcan_enable_rxmbox(can_channel     *chan,
                                  cyg_uint32       mbox_id)
{
    flexcan_info *info = (flexcan_info *)chan->dev_priv;
    flexcan_regs *flexcan = (flexcan_regs *)info->base;

    flexcan_hwmbox_enable_rx(flexcan, mbox_id);
    flexcan_mboxint_enable(info, mbox_id);
}

//===========================================================================
// Prepare message buffer filter
// Setup a RX message box for reception of a certain CAN identifier but do
// not enable it
//===========================================================================
static void flexcan_setup_rxmbox(can_channel     *chan, 
                                 cyg_uint32       mbox_id,
                                 cyg_ISR_t       *isr,
                                 cyg_can_message *pmsg,
                                 bool             enable,
                                 bool             int_enable)
{
    flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
    flexcan_mbox_info *pmbox;
    cyg_DSR_t         *dsr_func = &flexcan_mbox_rx_filt_dsr;
    
    //
    // Set state of message buffer accoring to ISR function that
    // will be registered
    //
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
    if (*isr == flexcan_mbox_rx_std_isr)
    {
        //
        // If we have only one single RX all message box then we use
        // the filter ISR instead of RX all standard ISR because it
        // is better suited for a single RX mbox
    //
        if (info->mboxes_std_cnt > 1)
        {
            info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_STD;
            dsr_func = &flexcan_mbox_rx_std_dsr;
        }
        else
        {
            info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
            isr = flexcan_mbox_rx_filt_isr;
        }
    }
    else
#endif // CYGOPT_IO_CAN_STD_CAN_ID
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
    if (*isr == flexcan_mbox_rx_ext_isr)
    {
        //
        // If we have only one single RX all message box then we use
        // the filter ISR instead of RX all standard ISR because it
        // is better suited for a single RX mbox
        //
        if (info->mboxes_ext_cnt > 1)
        {
            info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_EXT;
            dsr_func = &flexcan_mbox_rx_ext_dsr;
        }
        else
        {
            info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
            isr = flexcan_mbox_rx_filt_isr;
        }
    }
    else
#endif // CYGOPT_IO_CAN_EXT_CAN_ID
    if (*isr == flexcan_mbox_rx_filt_isr)
    {
        info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
    }
    else
    {
        CYG_ASSERT(0, "Invalid ISR function pointer");
    }

    pmbox = &info->mboxes[mbox_id];
    flexcan_cfg_mbox_rx(&flexcan->mbox[mbox_id], pmsg, enable);

    cyg_drv_interrupt_create(pmbox->isr_vec,
                             pmbox->isr_priority,
                             (cyg_addrword_t) chan,
                             isr,
                             dsr_func,
                             &(pmbox->interrupt_handle),
                             &(pmbox->interrupt));
    cyg_drv_interrupt_attach(pmbox->interrupt_handle);
    cyg_drv_interrupt_unmask(pmbox->isr_vec);
    
    //
    // now enable interrupt for this message box - but only if we
    // really should do it
    //
    if (int_enable)
    {
    flexcan_mboxint_enable(info, mbox_id);
    }
}


//===========================================================================
// Disable a message box - after this call a message box is available
// again for message filters or remote buffers
//===========================================================================
static void flexcan_disable_mbox(can_channel *chan, cyg_uint32 mbox_id)
{
    flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
    flexcan_mbox_info *pmbox;
    
    //
    // if message box is already disabled we do not need to disable it
    // here
    //
    if (MBOX_STATE_DISABLED == info->mboxes[mbox_id].state)
    {
        return;
    }
    
    HAL_WRITE_UINT8(&flexcan->mbox[mbox_id].ctrlstat, MBOX_RXCODE_NOT_ACTIVE);
    info->mboxes[mbox_id].state = MBOX_STATE_DISABLED;
    pmbox = &info->mboxes[mbox_id];
    
    //
    // now disable interrupts for this message box and free all
    // interrupt resources
    //
    flexcan_mboxint_disable(info, mbox_id);
    cyg_drv_interrupt_mask(pmbox->isr_vec);
    cyg_drv_interrupt_detach(pmbox->interrupt_handle);
    cyg_drv_interrupt_delete(pmbox->interrupt_handle);
    
    info->free_mboxes++;
}


//===========================================================================
// Setup a transmit message box
//===========================================================================
static void flexcan_setup_txmbox(can_channel      *chan,
                                 cyg_uint32        mbox_id,
                                 cyg_can_message  *pmsg)
{
    flexcan_info      *info   = (flexcan_info *)chan->dev_priv;
    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
    flexcan_mbox_info *pmbox;
    
    info->mboxes[mbox_id].state = MBOX_STATE_TX;
    pmbox = &info->mboxes[mbox_id];
    flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, false);

    //
    // prepare message box interrupt for message box 
    //
    cyg_drv_interrupt_create(pmbox->isr_vec,
                             pmbox->isr_priority,
                             (cyg_addrword_t) chan,
                             &flexcan_mbox_tx_isr,
                             &flexcan_mbox_tx_dsr,
                             &(pmbox->interrupt_handle),
                             &(pmbox->interrupt));
    cyg_drv_interrupt_attach(pmbox->interrupt_handle);
    cyg_drv_interrupt_unmask(pmbox->isr_vec);
    
    //
    // now enable interrupt for this message box
    //
    flexcan_mboxint_enable(info, mbox_id);
}


//===========================================================================
// Setup a RTR response message box
//===========================================================================
static void flexcan_setup_rtrmbox(can_channel      *chan,
                                  cyg_uint32        mbox_id,
                                  cyg_can_message  *pmsg)
{
    flexcan_info      *info   = (flexcan_info *)chan->dev_priv;
    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
    
    info->mboxes[mbox_id].state = MBOX_STATE_REMOTE_TX;
    flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, true);
}


//===========================================================================
// Setup the list of message boxes ready to receive a message
//===========================================================================
static void flexcan_setup_rxmbox_circbuf(flexcan_rxmbox_circbuf *pbuf)
{
    pbuf->count  = 0;
    pbuf->idx_rd = 0;
    pbuf->idx_wr = 0;
}


//===========================================================================
// Setup flexCAN modul for reception of any kind of message
//===========================================================================
static void flexcan_config_rx_all(can_channel *chan)
{
    flexcan_info *info       = (flexcan_info *)chan->dev_priv;
    flexcan_regs       *flexcan = (flexcan_regs *)info->base;
    cyg_int8           i;
    
        //
    // setup all available message boxes for reception of of messages
    // All standard and extended message buffers will be configured
        //
    for (i = 0; i < info->mboxes_rx_all_cnt; ++i)
             {
        cyg_can_message filter_param;
        filter_param.id  = 0;

        //
        // configure message buffers for standard frames
        //
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
        if (i < info->mboxes_std_cnt)
                 {
            filter_param.ext = CYGNUM_CAN_ID_STD;
            flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_std_isr, &filter_param, false, true);
                 }
#endif // CYGOPT_IO_CAN_STD_CAN_ID

       //
       // configure message buffers for extended frames
       //
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
        else
                 {
            filter_param.ext = CYGNUM_CAN_ID_EXT;
            flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_ext_isr, &filter_param, false, true);
                 }
#endif // CYGOPT_IO_CAN_EXT_CAN_ID
            }
       

⌨️ 快捷键说明

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