can_mcf52xx.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,632 行 · 第 1/5 页
C
1,632 行
cyg_uint32 tx_bytes;
cyg_uint32 rx_errors;
#endif
} flexcan_info;
//
// flexcan info initialisation
//
#define FLEXCAN_INFO(_l, \
_baseaddr, \
_isr_vec_mbox0, \
_mbox0_isr_prio, \
_mbox1_isr_prio, \
_mbox2_isr_prio, \
_mbox3_isr_prio, \
_mbox4_isr_prio, \
_mbox5_isr_prio, \
_mbox6_isr_prio, \
_mbox7_isr_prio, \
_mbox8_isr_prio, \
_mbox9_isr_prio, \
_mbox10_isr_prio, \
_mbox11_isr_prio, \
_mbox12_isr_prio, \
_mbox13_isr_prio, \
_mbox14_isr_prio, \
_mbox15_isr_prio, \
_boff_isr_vec, _boff_isr_prio, \
_err_isr_vec, _err_isr_prio, \
_wake_isr_vec, _wake_isr_prio, \
_tx_all_mbox, \
_std_mboxes, _ext_mboxes) \
flexcan_info _l = { \
(void *)( _baseaddr), \
(_isr_vec_mbox0), \
mboxes : { \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox0_isr_prio), 0), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox1_isr_prio), 1), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox2_isr_prio), 2), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox3_isr_prio), 3), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox4_isr_prio), 4), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox5_isr_prio), 5), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox6_isr_prio), 6), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox7_isr_prio), 7), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox8_isr_prio), 8), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox9_isr_prio), 9), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox10_isr_prio),10), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox11_isr_prio),11), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox12_isr_prio),12), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox13_isr_prio),13), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox14_isr_prio),14), \
FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox15_isr_prio),15), \
}, \
last_tx_id : 0xFFFFFFFF, \
boff_int : FLEXCAN_INT_INIT(_boff_isr_vec, _boff_isr_prio), \
err_int : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio), \
wake_int : FLEXCAN_INT_INIT(_wake_isr_vec, _wake_isr_prio), \
tx_all_mbox : _tx_all_mbox, \
free_mboxes : ((_std_mboxes) + (_ext_mboxes)), \
state : CYGNUM_CAN_STATE_ACTIVE, \
rx_all : true, \
mboxes_std_cnt : _std_mboxes, \
mboxes_ext_cnt : _ext_mboxes, \
mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes)) \
};
//===========================================================================
// GLOBAL DATA
//===========================================================================
//
// Note: two levels of macro are required to get proper expansion.
//
#define _FLEXCAN_MBOX_INTPRIO(n) CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX##n
#define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n)
//
// Define number of message boxes if they are not defined yet
//
#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES
#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES 0
#endif
#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES
#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES 0
#endif
#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES
#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES 0
#endif
#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES
#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES 0
#endif
#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0
//
// FlexCAN channel initialisation for FlexCAN channel 0
//
FLEXCAN_INFO(flexcan_can0_info,
HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
HAL_MCF52xx_FLEXCAN0_MBOX0_ISRVEC,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX0,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX1,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX2,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX3,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX4,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX5,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX6,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX7,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX8,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX9,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX10,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX11,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX12,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX13,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX14,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX15,
HAL_MCF52xx_FLEXCAN0_BOFF_ISRVEC,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_BOFFINT,
HAL_MCF52xx_FLEXCAN0_ERR_ISRVEC,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_ERRINT,
HAL_MCF52xx_FLEXCAN0_WAKE_ISRVEC,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_WAKEINT,
CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX,
CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES,
CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES);
#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1
//
// FlexCAN channel initialisation for FlexCAN channel 1
//
FLEXCAN_INFO(flexcan_can0_info,
HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
HAL_MCF52xx_FLEXCAN1_MBOX0_ISRVEC,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX0,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX1,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX2,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX3,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX4,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX5,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX6,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX7,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX8,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX9,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX10,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX11,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX12,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX13,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX14,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX15,
HAL_MCF52xx_FLEXCAN1_BOFF_ISRVEC,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_BOFFINT,
HAL_MCF52xx_FLEXCAN1_ERR_ISRVEC,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_ERRINT,
HAL_MCF52xx_FLEXCAN1_WAKE_ISRVEC,
CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_WAKEINT,
CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_DEFAULT_TX_MBOX,
CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES,
CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES);
#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1
//
// message box structure for hardware access of message box
//
typedef struct flexcan_mbox
{
cyg_uint8 timestamp;
cyg_uint8 ctrlstat;
cyg_uint16 id_hi;
cyg_uint16 id_lo;
cyg_uint8 data[8];
cyg_uint16 reserved;
} flexcan_mbox;
//
// flexcan register layout for hardware register access of FlexCAN modul
//
typedef struct flexcan_regs
{
cyg_uint16 CANMCR; // 0x00
cyg_uint16 reserved0[2]; // 0x02
cyg_uint8 CANCTRL0; // 0x06
cyg_uint8 CANCTRL1; // 0x07
cyg_uint8 PRESDIV; // 0x08
cyg_uint8 CANCTRL2; // 0x09
cyg_uint16 TIMER; // 0x0A
cyg_uint16 reserved1[2]; // 0x0C
cyg_uint16 RXGMASK_HI; // 0x10
cyg_uint16 RXGMASK_LO; // 0x12
cyg_uint16 RX14MASK_HI; // 0x14
cyg_uint16 RX14MASK_LO; // 0x16
cyg_uint16 RX15MASK_HI; // 0x18
cyg_uint16 RX15MASK_LO; // 0x1A
cyg_uint16 reserved2[2]; // 0x1C
cyg_uint16 ESTAT; // 0x20
cyg_uint16 IMASK; // 0x22
cyg_uint16 IFLAG; // 0x24
cyg_uint8 RXERRCNT; // 0x26
cyg_uint8 TXERRCNT; // 0x27
cyg_uint16 reserved3[44];// 0x28
flexcan_mbox mbox[16]; // 0x80
} flexcan_regs;
//===========================================================================
// LOCAL DATA
//===========================================================================
static cyg_uint16 flexcan_baud_rates[] = {
0, // Unused
10, // 10 kbit/s
20, // 20
50, // 50
100, // 100
125, // 125
250, // 250
500, // 500
800, // 800
1000, // 1000 kbit/s
};
//===========================================================================
// PROTOTYPES
//===========================================================================
static bool flexcan_init(struct cyg_devtab_entry* devtab_entry);
static Cyg_ErrNo flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
static Cyg_ErrNo flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
static Cyg_ErrNo flexcan_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
static bool flexcan_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
static bool flexcan_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
static void flexcan_start_xmit(can_channel* chan);
static void flexcan_stop_xmit(can_channel* chan);
//
// TX and RX ISRs and DSRs
//
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
static cyg_uint32 flexcan_mbox_rx_std_isr(cyg_vector_t, cyg_addrword_t);
static void flexcan_mbox_rx_std_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
#endif // CYGOPT_IO_CAN_STD_CAN_ID
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
static cyg_uint32 flexcan_mbox_rx_ext_isr(cyg_vector_t, cyg_addrword_t);
static void flexcan_mbox_rx_ext_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
#endif // CYGOPT_IO_CAN_EXT_CAN_ID
static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t, cyg_addrword_t);
static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t, cyg_addrword_t);
static void flexcan_mbox_tx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
static void flexcan_mbox_rx_filt_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t );
//
// All other flexcan interrupt handlers
//
static cyg_uint32 flexcan_err_isr(cyg_vector_t, cyg_addrword_t);
static void flexcan_err_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
static cyg_uint32 flexcan_busoff_isr(cyg_vector_t, cyg_addrword_t);
static void flexcan_busoff_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
static cyg_uint32 flexcan_wake_isr(cyg_vector_t, cyg_addrword_t);
static void flexcan_wake_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
//
// Flexcan utility functions
//
static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox, cyg_can_message *pmsg, bool rtr);
static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_can_message *pmsg, bool enable);
static void flexcan_read_from_mbox(can_channel *chan, cyg_uint8 mbox, cyg_can_event *pevent, cyg_uint8 *ctrlstat);
static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_can_id_type ext);
static void flexcan_start_chip(can_channel *chan);
static void flexcan_enter_standby(can_channel *chan, bool selfwake);
static void flexcan_stop_chip(can_channel *chan);
static void flexcan_leave_standby(can_channel *chan);
static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baudrate);
static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
static cyg_int8 flexcan_alloc_mbox(flexcan_info *info);
static void flexcan_disable_mbox(can_channel *chan, cyg_uint32 mbox_id);
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);
static void flexcan_setup_txmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg);
static void flexcan_setup_rtrmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg);
static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id);
static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id);
static void flexcan_config_rx_all(can_channel *chan);
static void flexcan_enable_rxmbox(can_channel *chan, cyg_uint32 mbox_id);
CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs,
flexcan_putmsg,
flexcan_getevent,
flexcan_get_config,
flexcan_set_config,
flexcan_start_xmit,
flexcan_stop_xmit
);
cyg_can_event flexcan_can0_rxbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX]; // buffer for 32 rx can events
cyg_can_message flexcan_can0_txbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX]; // buffer for 32 tx can messageds
CAN_CHANNEL_USING_INTERRUPTS(flexcan_can0_chan,
flexcan_lowlevel_funs,
flexcan_can0_info,
CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD),
flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX,
flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX
);
DEVTAB_ENTRY(flexcan_devtab,
CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME,
0, // Does not depend on a lower level interface
&cyg_io_can_devio,
flexcan_init,
flexcan_lookup, // CAN driver may need initializing
&flexcan_can0_chan
);
//===========================================================================
// Lookup the device and return its handle
//===========================================================================
static Cyg_ErrNo
flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
{
can_channel* chan = (can_channel*) (*tab)->priv;
(chan->callbacks->can_init)(chan);
return ENOERR;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?