can_mcf52xx.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,632 行 · 第 1/5 页

C
1,632
字号
//==========================================================================
//
//      devs/serial/m68k/flexcan/current/src/can_mcf_flexcan.c
//
//      CAN driver for Motorola coldfire processors
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    Uwe Kindler
// Contributors: Uwe Kindler
// Date:         2005-05-12
// Purpose:      support coldfire on-chip flexcan moduls
// Description: 
//
//####DESCRIPTIONEND####
//
//==========================================================================


//==========================================================================
//                              INCLUDES
//==========================================================================
#include <pkgconf/system.h>
#include <pkgconf/io_can.h>
#include <pkgconf/devs_can_mcf52xx_flexcan.h>

#include <cyg/infra/diag.h>

#include <cyg/io/io.h>
#include <cyg/io/devtab.h>
#include <cyg/io/can.h>

#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/hal_io.h>


//===========================================================================
//                                DEFINES  
//===========================================================================

//
// we define our own ste of register bits in order to be independent from
// platform specific names
//

//---------------------------------------------------------------------------
// MCR regsiter bits
//
#define FLEXCAN_MCR_STOP                    (0x01 << 15)
#define FLEXCAN_MCR_FRZ                     (0x01 << 14)
#define FLEXCAN_MCR_HALT                    (0x01 << 12)
#define FLEXCAN_MCR_NOTRDY                  (0x01 << 11)
#define FLEXCAN_MCR_WAKEMSK                 (0x01 << 10)
#define FLEXCAN_MCR_SOFTRST                 (0x01 << 9)
#define FLEXCAN_MCR_FRZACK                  (0x01 << 8)
#define FLEXCAN_MCR_SUPV                    (0x01 << 7)
#define FLEXCAN_MCR_SELFWAKE                (0x01 << 6)
#define FLEXCAN_MCR_APS                     (0x01 << 5)
#define FLEXCAN_MCR_STOPACK                 (0x01 << 4)


//---------------------------------------------------------------------------
// CTRL0 register bits
//
#define FLEXCAN_CTRL0_BOFFMSK                   (0x01 << 7)
#define FLEXCAN_CTRL0_ERRMASK                   (0x01 << 6)
#define FLEXCAN_CTRL0_RXMODE                    (0x01 << 2)
#define FLEXCAN_CTRL0_RXMODE_0_DOMINANT         (0x00 << 2)
#define FLEXCAN_CTRL0_RXMODE_1_DOMINANT         (0x01 << 2)
#define FLEXCAN_CTRL0_TXMODE_MASK               (0x03 << 0)
#define FLEXCAN_CTRL0_TXMODE_SHIFT              0
#define FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT    (0x00 << 0)
#define FLEXCAN_CTRL0_TXMODE_FULL_1_DOMINANT    (0x01 << 0)
#define FLEXCAN_CTRL0_TXMODE_OPEN_0_DOMINANT    (0x02 << 0)


//---------------------------------------------------------------------------
// CTRL1 register bits
//
#define FLEXCAN_CTRL1_SAMP                      (0x01 << 7)
#define FLEXCAN_CTRL1_TSYNC                     (0x01 << 5)
#define FLEXCAN_CTRL1_LBUF                      (0x01 << 4)
#define FLEXCAN_CTRL1_LOM                       (0x01 << 3)
#define FLEXCAN_CTRL1_PROPSEG_MASK              (0x07 << 0)
#define FLEXCAN_CTRL1_PROPSEG_SHIFT             0


//---------------------------------------------------------------------------
// CTRL2 register bits
//
#define FLEXCAN_CTRL2_RJW_MASK                  (0x03 << 6)
#define FLEXCAN_CTRL2_RJW_SHIFT                 6
#define FLEXCAN_CTRL2_PSEG1_MASK                (0x07 << 3)
#define FLEXCAN_CTRL2_PSEG1_SHIFT               3
#define FLEXCAN_CTRL2_PSEG2_MASK                (0x07 << 0)
#define FLEXCAN_CTRL2_PSEG2_SHIFT               0

//---------------------------------------------------------------------------
// ESTAT register bits
//
#define FLEXCAN_ESTAT_BITERR_MASK               (0x03 << 14)
#define FLEXCAN_ESTAT_BITERR_SHIFT              14
#define FLEXCAN_ESTAT_BITERR_NONE               (0x00 << 14)
#define FLEXCAN_ESTAT_BITERR_DOMINANT_RECESSIVE (0x01 << 14)
#define FLEXCAN_ESTAT_BITERR_RECESSIVE_DOMINANT (0x02 << 14)
#define FLEXCAN_ESTAT_ACKERR                    (0x01 << 13)
#define FLEXCAN_ESTAT_CRCERR                    (0x01 << 12)
#define FLEXCAN_ESTAT_FORMERR                   (0x01 << 11)
#define FLEXCAN_ESTAT_STUFFERR                  (0x01 << 10)
#define FLEXCAN_ESTAT_TXWARN                    (0x01 << 9)
#define FLEXCAN_ESTAT_RXWARN                    (0x01 << 8)
#define FLEXCAN_ESTAT_IDLE                      (0x01 << 7)
#define FLEXCAN_ESTAT_TX_RX                     (0x01 << 6)
#define FLEXCAN_ESTAT_FCS_MASK                  (0x03 << 4)
#define FLEXCAN_ESTAT_FCS_SHIFT                 4
#define FLEXCAN_ESTAT_FCS_ERROR_ACTIVE          (0x00 << 4)
#define FLEXCAN_ESTAT_FCS_ERROR_PASSIVE         (0x01 << 4)
#define FLEXCAN_ESTAT_BOFFINT                   (0x01 << 2)
#define FLEXCAN_ESTAT_ERRINT                    (0x01 << 1)
#define FLEXCAN_ESTAT_WAKEINT                   (0x01 << 0)

//
// For receive event calls we use these two identifiers for
// err and bus off events - message boxes use 0 - 15
//
#define FLEXCAN_ERR_EVENT                       16
#define FLEXCAN_BUSOFF_EVENT                    17
#define FLEXCAN_WAKE_EVENT                      18

//
// Acceptance mask
//
#define FLEXCAN_ACCEPTANCE_MASK_RX_ALL          0x00       // receive all messages - mbox ID does not matter
#define FLEXCAN_ACCEPTANCE_MASK_RX_ID           0x1FFFFFFF // receive only messages where ID exactly matches mbox ID


//---------------------------------------------------------------------------
// message buffer cfg bits
//
#define MBOX_RXCODE_NOT_ACTIVE 0x00
#define MBOX_RXCODE_BUSY       0x10
#define MBOX_RXCODE_EMPTY      0x40
#define MBOX_RXCODE_FULL       0x20
#define MBOX_RXCODE_OVERRUN    0x60

#define MBOX_TXCODE_NOT_READY  0x80
#define MBOX_TXCODE_TRANSMIT   0xC0
#define MBOX_TXCODE_RESPONSE   0xA0

#define MBOX_DATA_FRAME        0x00 // data frame
#define MBOX_REMOTE_FRAME      0x01 // remote frame
#define MBOX_STD_ID            0x00 // standard identifier
#define MBOX_EXT_ID            0x01 // remote identifier
#define MBOX_TX                0x08 // tx message box
#define MBOX_RX                0x00 // rx messge box

#define MBOX_CFG_IDE           0x08
#define MBOX_CFG_RTR_EXT       0x01
#define MBOX_CFG_RTR_STD       0x10
#define MBOX_CFG_SSR           0x10
#define MBOX_CFG_DLC_MASK      0x0F
#define MBOX_CFG_STAT_MASK     0xF0


//---------------------------------------------------------------------------
// flexcan message buffer configuration
//
#define FLEXCAN_MBOX_MIN      0
#define FLEXCAN_MBOX_MAX       15
#define FLEXCAN_MBOX_CNT      16
#define FLEXCAN_MBOX_TX       CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX
#define FLEXCAN_MBOX_RX_MIN   0
#define FLEXCAN_MBOX_RX_MAX   (FLEXCAN_MBOX_MAX - 1) // one msg box is tx
#define FLEXCAN_MBOX_RX_CNT   (FLEXCAN_MBOX_CNT - 1) // one msg box is tx


#define FLEXCAN_CTRLSTAT_NOT_READ 0 // indicates that control status register is not read


//===========================================================================
//                                 DATA TYPES
//===========================================================================
//
// Type of message buffer - required for function getevent in order to
// identify the type of message box that cause event
//
typedef enum
{
    MBOX_STATE_DISABLED,  // message box unused (free)
    MBOX_STATE_TX,        // TX message box
    MBOX_STATE_REMOTE_TX, // remote TX msaage box (data will be sent on reception of rtr frame) 
    MBOX_STATE_RX_ALL_STD, // RX message box for standard IDs
    MBOX_STATE_RX_ALL_EXT, // RX message box for standard IDs
    MBOX_STATE_RX_FILT     // RX message box for filter mboxes
} flexcan_mbox_state;


//
// configuration info for flexcan message buffer
//
typedef struct flexcan_mbox_info_st
{
    cyg_vector_t       isr_vec;           // isr vector
    int                isr_priority;      // isr priority
    cyg_interrupt      interrupt;         // stores interrupt data
    cyg_handle_t       interrupt_handle;  // stores interrupt number 
    cyg_uint8          num;               // number of message buffer
    bool               busy;              // if true, then transmission or reception is in progress
    flexcan_mbox_state state;             // message box state
    cyg_uint8          ctrlstat_shadow;   // shadow register of message box ctrlstat register
} flexcan_mbox_info; 

//
// Between ISR and DSR handling there is some kind of circular buffer.
// A DSR is only invoked if no other message box invoked a DSR before
// the DSR will read all available message buffers. This structure
// is for exchange of information between ISR and DSR
//
typedef struct st_rxmbox_circbuf
{
    cyg_uint8 idx_rd;       // the message box the DSR will read from
    cyg_uint8 idx_wr;       // the message box that will receive the next message
    cyg_uint8 count;        // the number of received message before DSR starts (number of ISR nesting)
} flexcan_rxmbox_circbuf;

//
// flexcan interrupt (busoff, err, wake) data - stores interrupt data for
// a non message box interrupt (bus off, err or wake interrupt)
//
typedef struct flexcan_int_st
{
    cyg_vector_t        isr_vec;  
    int                 isr_priority;
    cyg_interrupt       interrupt;
    cyg_handle_t        interrupt_handle;
} flexcan_int;

//
// flexcan message box initialisation
//
#define FLEXCAN_MBOX_INIT(_mbox0_vec, _prio, _mbox_no) { \
    isr_vec      : (_mbox0_vec) + (_mbox_no),            \
    isr_priority : (_prio),                              \
    num          : (_mbox_no),                           \
    busy         : false                                 \
}

//
// Interrupt initialisation
//
#define FLEXCAN_INT_INIT(_vec, _prio) \
{                                     \
    isr_vec      : (_vec),            \
    isr_priority : (_prio)            \
}

//
// flexcan configuration 
//
typedef struct flexcan_info 
{
    cyg_uint8          *base;            // base address of flexcan modul
    cyg_vector_t        isr_vec_mbox0;   // vector number of ISR vector of first message box
    flexcan_mbox_info   mboxes[FLEXCAN_MBOX_CNT];// message boxes
    cyg_uint32          last_tx_id;      // last transmitted message identifier
    
    flexcan_int         boff_int;        // bus off interrupt data
    flexcan_int         err_int;         // error interrupt data
    flexcan_int         wake_int;        // wake interrupt data
    
    cyg_uint8           tx_all_mbox;     // number of message box for all transmit messages
    cyg_uint8           free_mboxes;     // number of free message boxes for msg filters and rtr buffers
    cyg_can_state       state;           // state of CAN controller
    
    flexcan_rxmbox_circbuf rxmbox_std_circbuf;
    flexcan_rxmbox_circbuf rxmbox_ext_circbuf;

    cyg_uint8           mboxes_std_cnt;   // contains number of standard message boxes available
    cyg_uint8           mboxes_ext_cnt;   // number of message boxes with ext id
    cyg_uint8           mboxes_rx_all_cnt;// number of all available mboxes

    bool                rx_all;           // true if reception of call can messages is active
    cyg_uint16          imask_shadow;    // interrupt mask shadow register
#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
    cyg_can_message     last_tx_msg;     // stores last transmitted message for TX events
#endif

#ifdef FLEXCAN_CAN_STATS
    cyg_uint32          isr_count;
    cyg_uint32          dsr_count;
    cyg_uint32          rx_bytes;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?