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