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 + -
显示快捷键?