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