📄 can_lpc2xxx.c
字号:
// 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 + -