📄 can_at91sam7.c
字号:
//==========================================================================
//
// devs/can/arm/at91sam7x/current/src/can_at91sam7x.c
//
// CAN driver for Atmel AT91SAM7X microcontrollers
//
//==========================================================================
//####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: 2007-01-06
// Purpose: Support at91sam7 on-chip CAN moduls
// Description:
//
//####DESCRIPTIONEND####
//
//==========================================================================
//==========================================================================
// INCLUDES
//==========================================================================
#include <pkgconf/system.h>
#include <pkgconf/io_can.h>
#include <pkgconf/io.h>
#include <pkgconf/devs_can_at91sam7.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>
#include <cyg/hal/hal_diag.h>
#include <cyg/infra/cyg_ass.h>
//===========================================================================
// DEFINES
//===========================================================================
//
// Support debug output if this option is enabled in CDL file
//
#ifdef CYGDBG_DEVS_CAN_AT91SAM7_DEBUG
#define AT91SAM7_DBG_PRINT diag_printf
#else
#define AT91SAM7_DBG_PRINT( fmt, ... )
#endif
//
// we define our own set of register bits in order to be independent from
// platform specific names
//
//---------------------------------------------------------------------------
// Mailbox bits
//
#define BIT_MB0 (0x01 << 0)
#define BIT_MB1 (0x01 << 1)
#define BIT_MB2 (0x01 << 2)
#define BIT_MB3 (0x01 << 3)
#define BIT_MB4 (0x01 << 4)
#define BIT_MB5 (0x01 << 5)
#define BIT_MB6 (0x01 << 6)
#define BIT_MB7 (0x01 << 7)
//---------------------------------------------------------------------------
// CAN Mode Register bits (CAN_MR)
//
#define MR_CAN_ENABLE (0x01 << 0)
#define MR_LOW_POWER (0x01 << 1)
#define MR_AUTOBAUD (0x01 << 2)
#define MR_OVERLOAD (0x01 << 3)
#define MR_TIMESTAMP_EOF (0x01 << 4)
#define MR_TIME_TRIG (0x01 << 5)
#define MR_TIMER_FREEZE (0x01 << 6)
#define MR_DISABLE_REPEAT (0x01 << 7)
//---------------------------------------------------------------------------
// CAN Interrupt Enable/Disable, Mask and Status Register bits (CAN_IER, CAN_IDR, CAN_IMR)
//
#define INT_ERR_ACTIVE (0x01 << 16)
#define INT_WARN (0x01 << 17)
#define INT_ERR_PASSIVE (0x01 << 18)
#define INT_BUS_OFF (0x01 << 19)
#define INT_SLEEP (0x01 << 20)
#define INT_WAKEUP (0x01 << 21)
#define INT_TMR_OVF (0x01 << 22)
#define INT_TIMESTAMP (0x01 << 23)
#define INT_CRC_ERR (0x01 << 24)
#define INT_STUFF_ERR (0x01 << 25)
#define INT_ACKN_ERR (0x01 << 26)
#define INT_FORM_ERR (0x01 << 27)
#define INT_BIT_ERR (0x01 << 28)
#define INT_MB 0xFF // message box intterupt (mbox 1 - 8)
#define INT_MB_RX 0x7F // rx message box interrupts
#define INT_MB_TX 0x80 // tx message box interrupts
//
// We do not enable INT_WARN by default because this flug is buggy and causes interrupts
// event if no counter reached warning level.
//
#define INT_ALL_ERR (INT_CRC_ERR | INT_STUFF_ERR | INT_ACKN_ERR | INT_FORM_ERR | INT_BIT_ERR)
#define INT_DEFAULT (INT_ERR_PASSIVE | INT_BUS_OFF | INT_SLEEP | INT_WAKEUP | INT_ALL_ERR)
//
// these bits are only in status register (CAN_SR)
//
#define SR_RX_BUSY (0x01 << 29)
#define SR_TX_BUSY (0x01 << 30)
#define SR_OVL_BUSY (0x01 << 31)
//---------------------------------------------------------------------------
// CAN Baudrate Register (CAN_BR)
//
#define BR_PHASE2_BITMASK 0x00000007
#define BR_PHASE1_BITMASK 0x00000070
#define BR_PROPAG_BITMASK 0x00000700
#define BR_SJW_BITMASK 0x00003000
#define BR_BRP_BITMASK 0x007F0000
#define BR_SMP_BITMASK 0x01000000
//---------------------------------------------------------------------------
// CAN Error Counter Register (CAN_ECR)
//
#define ECR_GET_TEC(_ecr_) (((_ecr_) >> 16) & 0xFF)
#define ECR_GET_REC(_ecr_) ((_ecr_) & 0xFF)
//---------------------------------------------------------------------------
// CAN Transfer Command Resgister (CAN_TCR)
//
#define TCR_TMR_RESET 0x80000000
//---------------------------------------------------------------------------
// CAN Message Mode Register (CAN_MMRx)
//
#define MMR_TIMEMARK_BITMASK 0x0000FFFF
#define MMR_PRIOR_BITMASK 0x000F0000
#define MMR_MB_SHIFTER 24
#define MMR_MB_TYPE_BITMASK (0x07 << MMR_MB_SHIFTER) // mask the mot bits
#define MMR_MB_TYPE_DISABLED (0x00 << MMR_MB_SHIFTER) // message box disabled
#define MMR_MB_TYPE_RX (0x01 << MMR_MB_SHIFTER) // rx message box
#define MMR_MB_TYPE_RX_OVW (0x02 << MMR_MB_SHIFTER) // rx message box with overwrite
#define MMR_MB_TYPE_TX (0x03 << MMR_MB_SHIFTER) // tx message box
#define MMR_MB_TYPE_CONSUME (0x04 << MMR_MB_SHIFTER) // consumer - receives RTR and sends its content
#define MMR_MB_TYPE_PRODUCE (0x05 << MMR_MB_SHIFTER) // producer - sends a RTR and waits for answer
#define MMR_MB_GET_TYPE(_mb_) ((_mb_) & MMR_MB_TYPE_BITMASK)
//---------------------------------------------------------------------------
// CAN Message Acceptance Mask/ID Register (CAN_MAMx, CAN_MIDx)
//
#define MID_MIDvB_BITMASK 0x0003FFFF
#define MID_MIDvA_BITMASK 0x1FFC0000
#define MID_MIDE 0x20000000
#define MID_MIDvA_SHIFTER 18
#define MID_SET_STD(_id_) (((_id_) << MID_MIDvA_SHIFTER) & MID_MIDvA_BITMASK)
#define MID_SET_EXT(_id_) ((_id_) | MID_MIDE)
#define MAM_SET_STD ((((0x7FF << MID_MIDvA_SHIFTER) & MID_MIDvA_BITMASK) | MID_MIDE))
#define MAM_SET_EXT 0xFFFFFFFF
#define MID_GET_STD(_mid_) (((_mid_) >> MID_MIDvA_SHIFTER) & CYG_CAN_STD_ID_MASK)
#define MID_GET_EXT(_mid_) ((_mid_) & CYG_CAN_EXT_ID_MASK)
//---------------------------------------------------------------------------
// CAN Message Status Register (CAN_MSRx)
//
#define MSR_TIMESTAMP 0x0000FFFF
#define MSR_DLC 0x000F0000
#define MSR_RTR 0x00100000
#define MSR_MSG_ABORT 0x00400000
#define MSR_RDY 0x00800000
#define MSR_MSG_IGNORED 0x01000000
#define MSR_DLC_SHIFTER 16
#define MSR_DLC_GET(_msr_) (((_msr_) >> 16) & 0x0F)
//---------------------------------------------------------------------------
// CAN Message Control Register (CAN_MCRx)
//
#define MCR_DLC 0x000F0000 // MDLC
#define MCR_RTR 0x00100000 // MRTR
#define MCR_MSG_ABORT 0x00400000 // MACR
#define MCR_TRANSFER_CMD 0x00800000 // MTCR
#define MCR_DLC_SHIFTER 16
#define MCR_DLC_CREATE(_len_) ((_len_) << MCR_DLC_SHIFTER)
//---------------------------------------------------------------------------
// CAN Module Register Layout
//
#define CANREG_MR 0x0000
#define CANREG_IER 0x0004
#define CANREG_IDR 0x0008
#define CANREG_IMR 0x000C
#define CANREG_SR 0x0010
#define CANREG_BR 0x0014
#define CANREG_TIM 0x0018
#define CANREG_TIMESTAMP 0x001C
#define CANREG_ECR 0x0020
#define CANREG_TCR 0x0024
#define CANREG_ACR 0x0028
#define CANREG_MB_BASE 0x0200
//
// Register layout of message box relativ to base register of a certain
// message box
//
#define CANREG_MMR 0x0000
#define CANREG_MAM 0x0004
#define CANREG_MID 0x0008
#define CANREG_MFID 0x000C
#define CANREG_MSR 0x0010
#define CANREG_MDL 0x0014
#define CANREG_MDH 0x0018
#define CANREG_MCR 0x001C
#define AT91SAM7_CAN_PERIPHERAL_ID 15
#define CAN_MBOX_MIN 0
#define CAN_MBOX_MAX 7
#define CAN_MBOX_CNT 8
#define CAN_MBOX_RX_MIN 0
#define CAN_MBOX_RX_MAX (CAN_MBOX_MAX - 1) // one message box is tx
#define CAN_MBOX_RX_CNT (CAN_MBOX_CNT - 1) // one message box is tx
#define CAN_MR(_extra_) (CAN_BASE(_extra_) + CANREG_MR)
#define CAN_IER(_extra_) (CAN_BASE(_extra_) + CANREG_IER)
#define CAN_IDR(_extra_) (CAN_BASE(_extra_) + CANREG_IDR)
#define CAN_IMR(_etxra_) (CAN_BASE(_extra_) + CANREG_IMR)
#define CAN_SR(_etxra_) (CAN_BASE(_extra_) + CANREG_SR)
#define CAN_BR(_etxra_) (CAN_BASE(_extra_) + CANREG_BR)
#define CAN_TIM(_etxra_) (CAN_BASE(_extra_) + CANREG_TIM)
#define CAN_TIMESTAMP(_etxra_) (CAN_BASE(_extra_) + CANREG_TIMESTAMP)
#define CAN_ECR(_etxra_) (CAN_BASE(_extra_) + CANREG_ECR)
#define CAN_TCR(_etxra_) (CAN_BASE(_extra_) + CANREG_TCR)
#define CAN_ACR(_etxra_) (CAN_BASE(_extra_) + CANREG_ACR)
//
// Message box registers
//
#define CAN_MB_BASE(_extra_) (CAN_BASE(_extra_) + CANREG_MB_BASE)
#define CAN_MB_MMR(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MMR)
#define CAN_MB_MAM(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MAM)
#define CAN_MB_MID(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MID)
#define CAN_MB_MFID(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MFID)
#define CAN_MB_MSR(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MSR)
#define CAN_MB_MDL(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MDL)
#define CAN_MB_MDH(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MDH)
#define CAN_MB_MCR(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MCR)
//---------------------------------------------------------------------------
// Optimize for the case of a single CAN channel, while still allowing
// multiple channels. At the moment only AT91SAM7 controllers with one
// CAN channel are known.
//
#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1
#define CAN_PID(_extra_) AT91SAM7_CAN_PERIPHERAL_ID
#define CAN_ISRVEC(_extra_) CAN_PID(_extra_)
#define CAN_ISRPRIO(_extra_) CYGNUM_DEVS_CAN_AT91SAM7_CAN0_ISR_PRIORITY
#define CAN_BASE(_extra_) AT91_CAN
#define CAN_DECLARE_INFO(_chan_)
#define CAN_MBOX_TX(_extra_) CYGNUM_DEVS_CAN_AT91SAM7_CAN0_DEFAULT_TX_MBOX
#define CAN_MBOX_STD_CNT(_extra_) CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES
#define CAN_MBOX_EXT_CNT(_extra_) CYGNUM_DEVS_CAN_AT91SAM7_CAN0_EXT_MBOXES
#define CAN_MBOX_RX_ALL_CNT(_extra) (CAN_MBOX_STD_CNT(_extra_) + CAN_MBOX_EXT_CNT(_extra_))
#ifndef CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES
#define CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES 0
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -