2251 lines
73 KiB
C
2251 lines
73 KiB
C
//*****************************************************************************
|
|
//
|
|
// can.c - Driver for the CAN module.
|
|
//
|
|
// Copyright (c) 2006-2010 Texas Instruments Incorporated. All rights reserved.
|
|
// Software License Agreement
|
|
//
|
|
// Texas Instruments (TI) is supplying this software for use solely and
|
|
// exclusively on TI's microcontroller products. The software is owned by
|
|
// TI and/or its suppliers, and is protected under applicable copyright
|
|
// laws. You may not combine this software with "viral" open-source
|
|
// software in order to form a larger program.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
|
|
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
|
|
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
|
|
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
|
|
// DAMAGES, FOR ANY REASON WHATSOEVER.
|
|
//
|
|
// This is part of revision 6459 of the Stellaris Peripheral Driver Library.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \addtogroup can_api
|
|
//! @{
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#include "inc/hw_can.h"
|
|
#include "inc/hw_ints.h"
|
|
#include "inc/hw_nvic.h"
|
|
#include "inc/hw_memmap.h"
|
|
#include "inc/hw_types.h"
|
|
#include "driverlib/can.h"
|
|
#include "driverlib/debug.h"
|
|
#include "driverlib/interrupt.h"
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This is the maximum number that can be stored as an 11bit Message
|
|
// identifier.
|
|
//
|
|
//*****************************************************************************
|
|
#define CAN_MAX_11BIT_MSG_ID 0x7ff
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This is used as the loop delay for accessing the CAN controller registers.
|
|
//
|
|
//*****************************************************************************
|
|
#define CAN_RW_DELAY 5
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// The maximum CAN bit timing divisor is 19.
|
|
//
|
|
//*****************************************************************************
|
|
#define CAN_MAX_BIT_DIVISOR 19
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// The minimum CAN bit timing divisor is 4.
|
|
//
|
|
//*****************************************************************************
|
|
#define CAN_MIN_BIT_DIVISOR 4
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// The maximum CAN pre-divisor is 1024.
|
|
//
|
|
//*****************************************************************************
|
|
#define CAN_MAX_PRE_DIVISOR 1024
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// The minimum CAN pre-divisor is 1.
|
|
//
|
|
//*****************************************************************************
|
|
#define CAN_MIN_PRE_DIVISOR 1
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Converts a set of CAN bit timing values into the value that needs to be
|
|
// programmed into the CAN_BIT register to achieve those timings.
|
|
//
|
|
//*****************************************************************************
|
|
#define CAN_BIT_VALUE(seg1, seg2, sjw) \
|
|
((((seg1 - 1) << CAN_BIT_TSEG1_S) & \
|
|
CAN_BIT_TSEG1_M) | \
|
|
(((seg2 - 1) << CAN_BIT_TSEG2_S) & \
|
|
CAN_BIT_TSEG2_M) | \
|
|
(((sjw - 1) << CAN_BIT_SJW_S) & \
|
|
CAN_BIT_SJW_M))
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This table is used by the CANBitRateSet() API as the register defaults for
|
|
// the bit timing values.
|
|
//
|
|
//*****************************************************************************
|
|
static const unsigned short g_usCANBitValues[] =
|
|
{
|
|
CAN_BIT_VALUE(2, 1, 1), // 4 clocks/bit
|
|
CAN_BIT_VALUE(3, 1, 1), // 5 clocks/bit
|
|
CAN_BIT_VALUE(3, 2, 2), // 6 clocks/bit
|
|
CAN_BIT_VALUE(4, 2, 2), // 7 clocks/bit
|
|
CAN_BIT_VALUE(4, 3, 3), // 8 clocks/bit
|
|
CAN_BIT_VALUE(5, 3, 3), // 9 clocks/bit
|
|
CAN_BIT_VALUE(5, 4, 4), // 10 clocks/bit
|
|
CAN_BIT_VALUE(6, 4, 4), // 11 clocks/bit
|
|
CAN_BIT_VALUE(6, 5, 4), // 12 clocks/bit
|
|
CAN_BIT_VALUE(7, 5, 4), // 13 clocks/bit
|
|
CAN_BIT_VALUE(7, 6, 4), // 14 clocks/bit
|
|
CAN_BIT_VALUE(8, 6, 4), // 15 clocks/bit
|
|
CAN_BIT_VALUE(8, 7, 4), // 16 clocks/bit
|
|
CAN_BIT_VALUE(9, 7, 4), // 17 clocks/bit
|
|
CAN_BIT_VALUE(9, 8, 4), // 18 clocks/bit
|
|
CAN_BIT_VALUE(10, 8, 4) // 19 clocks/bit
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \internal
|
|
//! Checks a CAN base address.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//!
|
|
//! This function determines if a CAN controller base address is valid.
|
|
//!
|
|
//! \return Returns \b true if the base address is valid and \b false
|
|
//! otherwise.
|
|
//
|
|
//*****************************************************************************
|
|
#ifdef DEBUG
|
|
static tBoolean
|
|
CANBaseValid(unsigned long ulBase)
|
|
{
|
|
return((ulBase == CAN0_BASE) || (ulBase == CAN1_BASE) ||
|
|
(ulBase == CAN2_BASE));
|
|
}
|
|
#endif
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \internal
|
|
//!
|
|
//! Returns the CAN controller interrupt number.
|
|
//!
|
|
//! \param ulBase is the base address of the selected CAN controller
|
|
//!
|
|
//! Given a CAN controller base address, returns the corresponding interrupt
|
|
//! number.
|
|
//!
|
|
//! This function replaces the original CANGetIntNumber() API and performs the
|
|
//! same actions. A macro is provided in <tt>can.h</tt> to map the original
|
|
//! API to this API.
|
|
//!
|
|
//! \return Returns a CAN interrupt number, or -1 if \e ulPort is invalid.
|
|
//
|
|
//*****************************************************************************
|
|
static long
|
|
CANIntNumberGet(unsigned long ulBase)
|
|
{
|
|
long lIntNumber;
|
|
|
|
//
|
|
// Return the interrupt number for the given CAN controller.
|
|
//
|
|
switch(ulBase)
|
|
{
|
|
//
|
|
// Return the interrupt number for CAN 0
|
|
//
|
|
case CAN0_BASE:
|
|
{
|
|
lIntNumber = INT_CAN0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Return the interrupt number for CAN 1
|
|
//
|
|
case CAN1_BASE:
|
|
{
|
|
lIntNumber = INT_CAN1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Return the interrupt number for CAN 2
|
|
//
|
|
case CAN2_BASE:
|
|
{
|
|
lIntNumber = INT_CAN2;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Return -1 to indicate a bad address was passed in.
|
|
//
|
|
default:
|
|
{
|
|
lIntNumber = -1;
|
|
}
|
|
}
|
|
return(lIntNumber);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \internal
|
|
//!
|
|
//! Reads a CAN controller register.
|
|
//!
|
|
//! \param ulRegAddress is the full address of the CAN register to be read.
|
|
//!
|
|
//! This function performs the necessary synchronization to read from a CAN
|
|
//! controller register.
|
|
//!
|
|
//! This function replaces the original CANReadReg() API and performs the same
|
|
//! actions. A macro is provided in <tt>can.h</tt> to map the original API to
|
|
//! this API.
|
|
//!
|
|
//! \note This function provides the delay required to access CAN registers.
|
|
//! This delay is required when accessing CAN registers directly.
|
|
//!
|
|
//! \return Returns the value read from the register.
|
|
//
|
|
//*****************************************************************************
|
|
static unsigned long
|
|
CANRegRead(unsigned long ulRegAddress)
|
|
{
|
|
volatile int iDelay;
|
|
unsigned long ulRetVal;
|
|
unsigned long ulIntNumber;
|
|
unsigned long ulReenableInts;
|
|
|
|
//
|
|
// Get the CAN interrupt number from the register base address.
|
|
//
|
|
ulIntNumber = CANIntNumberGet(ulRegAddress & 0xfffff000);
|
|
|
|
//
|
|
// Make sure that the CAN base address was valid.
|
|
//
|
|
ASSERT(ulIntNumber != (unsigned long)-1);
|
|
|
|
//
|
|
// Remember current state so that CAN interrupts are only re-enabled if
|
|
// they were already enabled.
|
|
//
|
|
ulReenableInts = HWREG(NVIC_EN1) & (1 << (ulIntNumber - 48));
|
|
|
|
//
|
|
// If the CAN interrupt was enabled then disable it.
|
|
//
|
|
if(ulReenableInts)
|
|
{
|
|
IntDisable(ulIntNumber);
|
|
}
|
|
|
|
//
|
|
// Trigger the initial read to the CAN controller. The value returned at
|
|
// this point is not valid.
|
|
//
|
|
HWREG(ulRegAddress);
|
|
|
|
//
|
|
// This delay is necessary for the CAN have the correct data on the bus.
|
|
//
|
|
for(iDelay = 0; iDelay < CAN_RW_DELAY; iDelay++)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Do the final read that has the valid value of the register.
|
|
//
|
|
ulRetVal = HWREG(ulRegAddress);
|
|
|
|
//
|
|
// Enable CAN interrupts if they were enabled before this call.
|
|
//
|
|
if(ulReenableInts)
|
|
{
|
|
IntEnable(ulIntNumber);
|
|
}
|
|
|
|
return(ulRetVal);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \internal
|
|
//!
|
|
//! Writes a CAN controller register.
|
|
//!
|
|
//! \param ulRegAddress is the full address of the CAN register to be written.
|
|
//! \param ulRegValue is the value to write into the register specified by
|
|
//! \e ulRegAddress.
|
|
//!
|
|
//! This function takes care of the synchronization necessary to write to a
|
|
//! CAN controller register.
|
|
//!
|
|
//! This function replaces the original CANWriteReg() API and performs the same
|
|
//! actions. A macro is provided in <tt>can.h</tt> to map the original API to
|
|
//! this API.
|
|
//!
|
|
//! \note The delays in this function are required when accessing CAN registers
|
|
//! directly.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
static void
|
|
CANRegWrite(unsigned long ulRegAddress, unsigned long ulRegValue)
|
|
{
|
|
volatile int iDelay;
|
|
|
|
//
|
|
// Trigger the initial write to the CAN controller. The value will not make
|
|
// it out to the CAN controller for CAN_RW_DELAY cycles.
|
|
//
|
|
HWREG(ulRegAddress) = ulRegValue;
|
|
|
|
//
|
|
// Delay to allow the CAN controller to receive the new data.
|
|
//
|
|
for(iDelay = 0; iDelay < CAN_RW_DELAY; iDelay++)
|
|
{
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \internal
|
|
//!
|
|
//! Copies data from a buffer to the CAN Data registers.
|
|
//!
|
|
//! \param pucData is a pointer to the data to be written out to the CAN
|
|
//! controller's data registers.
|
|
//! \param pulRegister is an unsigned long pointer to the first register of the
|
|
//! CAN controller's data registers. For example, in order to use the IF1
|
|
//! register set on CAN controller 0, the value would be: \b CAN0_BASE \b +
|
|
//! \b CAN_O_IF1DA1.
|
|
//! \param iSize is the number of bytes to copy into the CAN controller.
|
|
//!
|
|
//! This function takes the steps necessary to copy data from a contiguous
|
|
//! buffer in memory into the non-contiguous data registers used by the CAN
|
|
//! controller. This function is rarely used outside of the CANMessageSet()
|
|
//! function.
|
|
//!
|
|
//! This function replaces the original CANWriteDataReg() API and performs the
|
|
//! same actions. A macro is provided in <tt>can.h</tt> to map the original
|
|
//! API to this API.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
static void
|
|
CANDataRegWrite(unsigned char *pucData, unsigned long *pulRegister, int iSize)
|
|
{
|
|
int iIdx;
|
|
unsigned long ulValue;
|
|
|
|
//
|
|
// Loop always copies 1 or 2 bytes per iteration.
|
|
//
|
|
for(iIdx = 0; iIdx < iSize; )
|
|
{
|
|
|
|
//
|
|
// Write out the data 16 bits at a time since this is how the registers
|
|
// are aligned in memory.
|
|
//
|
|
ulValue = pucData[iIdx++];
|
|
|
|
//
|
|
// Only write the second byte if needed otherwise it will be zero.
|
|
//
|
|
if(iIdx < iSize)
|
|
{
|
|
ulValue |= (pucData[iIdx++] << 8);
|
|
}
|
|
CANRegWrite((unsigned long)(pulRegister++), ulValue);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \internal
|
|
//!
|
|
//! Copies data from a buffer to the CAN Data registers.
|
|
//!
|
|
//! \param pucData is a pointer to the location to store the data read from the
|
|
//! CAN controller's data registers.
|
|
//! \param pulRegister is an unsigned long pointer to the first register of the
|
|
//! CAN controller's data registers. For example, in order to use the IF1
|
|
//! register set on CAN controller 1, the value would be: \b CAN0_BASE \b +
|
|
//! \b CAN_O_IF1DA1.
|
|
//! \param iSize is the number of bytes to copy from the CAN controller.
|
|
//!
|
|
//! This function takes the steps necessary to copy data to a contiguous buffer
|
|
//! in memory from the non-contiguous data registers used by the CAN
|
|
//! controller. This function is rarely used outside of the CANMessageGet()
|
|
//! function.
|
|
//!
|
|
//! This function replaces the original CANReadDataReg() API and performs the
|
|
//! same actions. A macro is provided in <tt>can.h</tt> to map the original
|
|
//! API to this API.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
static void
|
|
CANDataRegRead(unsigned char *pucData, unsigned long *pulRegister, int iSize)
|
|
{
|
|
int iIdx;
|
|
unsigned long ulValue;
|
|
|
|
//
|
|
// Loop always copies 1 or 2 bytes per iteration.
|
|
//
|
|
for(iIdx = 0; iIdx < iSize; )
|
|
{
|
|
//
|
|
// Read out the data 16 bits at a time since this is how the registers
|
|
// are aligned in memory.
|
|
//
|
|
ulValue = CANRegRead((unsigned long)(pulRegister++));
|
|
|
|
//
|
|
// Store the first byte.
|
|
//
|
|
pucData[iIdx++] = (unsigned char)ulValue;
|
|
|
|
//
|
|
// Only read the second byte if needed.
|
|
//
|
|
if(iIdx < iSize)
|
|
{
|
|
pucData[iIdx++] = (unsigned char)(ulValue >> 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Initializes the CAN controller after reset.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//!
|
|
//! After reset, the CAN controller is left in the disabled state. However,
|
|
//! the memory used for message objects contains undefined values and must be
|
|
//! cleared prior to enabling the CAN controller the first time. This prevents
|
|
//! unwanted transmission or reception of data before the message objects are
|
|
//! configured. This function must be called before enabling the controller
|
|
//! the first time.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANInit(unsigned long ulBase)
|
|
{
|
|
int iMsg;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
//
|
|
// Place CAN controller in init state, regardless of previous state. This
|
|
// will put controller in idle, and allow the message object RAM to be
|
|
// programmed.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_CTL, CAN_CTL_INIT);
|
|
|
|
//
|
|
// Wait for busy bit to clear
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Clear the message value bit in the arbitration register. This indicates
|
|
// the message is not valid and is a "safe" condition to leave the message
|
|
// object. The same arb reg is used to program all the message objects.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CMSK, CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB |
|
|
CAN_IF1CMSK_CONTROL);
|
|
CANRegWrite(ulBase + CAN_O_IF1ARB2, 0);
|
|
CANRegWrite(ulBase + CAN_O_IF1MCTL, 0);
|
|
|
|
//
|
|
// Loop through to program all 32 message objects
|
|
//
|
|
for(iMsg = 1; iMsg <= 32; iMsg++)
|
|
{
|
|
//
|
|
// Wait for busy bit to clear
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Initiate programming the message object
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CRQ, iMsg);
|
|
}
|
|
|
|
//
|
|
// Make sure that the interrupt and new data flags are updated for the
|
|
// message objects.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CMSK, CAN_IF1CMSK_NEWDAT |
|
|
CAN_IF1CMSK_CLRINTPND);
|
|
|
|
//
|
|
// Loop through to program all 32 message objects
|
|
//
|
|
for(iMsg = 1; iMsg <= 32; iMsg++)
|
|
{
|
|
//
|
|
// Wait for busy bit to clear.
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Initiate programming the message object
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CRQ, iMsg);
|
|
}
|
|
|
|
//
|
|
// Acknowledge any pending status interrupts.
|
|
//
|
|
CANRegRead(ulBase + CAN_O_STS);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Enables the CAN controller.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller to enable.
|
|
//!
|
|
//! Enables the CAN controller for message processing. Once enabled, the
|
|
//! controller will automatically transmit any pending frames, and process any
|
|
//! received frames. The controller can be stopped by calling CANDisable().
|
|
//! Prior to calling CANEnable(), CANInit() should have been called to
|
|
//! initialize the controller and the CAN bus clock should be configured by
|
|
//! calling CANBitTimingSet().
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANEnable(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
//
|
|
// Clear the init bit in the control register.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_CTL,
|
|
CANRegRead(ulBase + CAN_O_CTL) & ~CAN_CTL_INIT);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Disables the CAN controller.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller to disable.
|
|
//!
|
|
//! Disables the CAN controller for message processing. When disabled, the
|
|
//! controller will no longer automatically process data on the CAN bus. The
|
|
//! controller can be restarted by calling CANEnable(). The state of the CAN
|
|
//! controller and the message objects in the controller are left as they were
|
|
//! before this call was made.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANDisable(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
//
|
|
// Set the init bit in the control register.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_CTL,
|
|
CANRegRead(ulBase + CAN_O_CTL) | CAN_CTL_INIT);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Reads the current settings for the CAN controller bit timing.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param pClkParms is a pointer to a structure to hold the timing parameters.
|
|
//!
|
|
//! This function reads the current configuration of the CAN controller bit
|
|
//! clock timing, and stores the resulting information in the structure
|
|
//! supplied by the caller. Refer to CANBitTimingSet() for the meaning of the
|
|
//! values that are returned in the structure pointed to by \e pClkParms.
|
|
//!
|
|
//! This function replaces the original CANGetBitTiming() API and performs the
|
|
//! same actions. A macro is provided in <tt>can.h</tt> to map the original
|
|
//! API to this API.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANBitTimingGet(unsigned long ulBase, tCANBitClkParms *pClkParms)
|
|
{
|
|
unsigned int uBitReg;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT(pClkParms != 0);
|
|
|
|
//
|
|
// Read out all the bit timing values from the CAN controller registers.
|
|
//
|
|
uBitReg = CANRegRead(ulBase + CAN_O_BIT);
|
|
|
|
//
|
|
// Set the phase 2 segment.
|
|
//
|
|
pClkParms->uPhase2Seg =
|
|
((uBitReg & CAN_BIT_TSEG2_M) >> CAN_BIT_TSEG2_S) + 1;
|
|
|
|
//
|
|
// Set the phase 1 segment.
|
|
//
|
|
pClkParms->uSyncPropPhase1Seg =
|
|
((uBitReg & CAN_BIT_TSEG1_M) >> CAN_BIT_TSEG1_S) + 1;
|
|
|
|
//
|
|
// Set the synchronous jump width.
|
|
//
|
|
pClkParms->uSJW = ((uBitReg & CAN_BIT_SJW_M) >> CAN_BIT_SJW_S) + 1;
|
|
|
|
//
|
|
// Set the pre-divider for the CAN bus bit clock.
|
|
//
|
|
pClkParms->uQuantumPrescaler =
|
|
((uBitReg & CAN_BIT_BRP_M) |
|
|
((CANRegRead(ulBase + CAN_O_BRPE) & CAN_BRPE_BRPE_M) << 6)) + 1;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! This function is used to set the CAN bit timing values to a nominal setting
|
|
//! based on a desired bit rate.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param ulSourceClock is the system clock for the device in Hz.
|
|
//! \param ulBitRate is the desired bit rate.
|
|
//!
|
|
//! This function will set the CAN bit timing for the bit rate passed in the
|
|
//! \e ulBitRate parameter based on the \e ulSourceClock parameter. Since the
|
|
//! CAN clock is based off of the system clock the calling function should pass
|
|
//! in the source clock rate either by retrieving it from SysCtlClockGet() or
|
|
//! using a specific value in Hz. The CAN bit timing is calculated assuming a
|
|
//! minimal amount of propagation delay, which will work for most cases where
|
|
//! the network length is short. If tighter timing requirements or longer
|
|
//! network lengths are needed, then the CANBitTimingSet() function is
|
|
//! available for full customization of all of the CAN bit timing values.
|
|
//! Since not all bit rates can be matched exactly, the bit rate is set to the
|
|
//! value closest to the desired bit rate without being higher than the
|
|
//! \e ulBitRate value.
|
|
//!
|
|
//! \note On some devices the source clock is fixed at 8MHz so the
|
|
//! \e ulSourceClock should be set to 8000000.
|
|
//!
|
|
//! \return This function returns the bit rate that the CAN controller was
|
|
//! configured to use or it returns 0 to indicate that the bit rate was not
|
|
//! changed because the requested bit rate was not valid.
|
|
//!
|
|
//*****************************************************************************
|
|
unsigned long
|
|
CANBitRateSet(unsigned long ulBase, unsigned long ulSourceClock,
|
|
unsigned long ulBitRate)
|
|
{
|
|
unsigned long ulDesiredRatio;
|
|
unsigned long ulCANBits;
|
|
unsigned long ulPreDivide;
|
|
unsigned long ulRegValue;
|
|
unsigned short usCANCTL;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT(ulSourceClock != 0);
|
|
ASSERT(ulBitRate != 0);
|
|
|
|
//
|
|
// Calculate the desired clock rate.
|
|
//
|
|
ulDesiredRatio = ulSourceClock / ulBitRate;
|
|
|
|
//
|
|
// Make sure that the ratio of CAN bit rate to processor clock is not too
|
|
// small or too large.
|
|
//
|
|
ASSERT(ulDesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR));
|
|
ASSERT(ulDesiredRatio >= (CAN_MIN_PRE_DIVISOR * CAN_MIN_BIT_DIVISOR));
|
|
|
|
//
|
|
// Make sure that the Desired Ratio is not too large. This enforces the
|
|
// requirement that the bit rate is larger than requested.
|
|
//
|
|
if((ulSourceClock / ulDesiredRatio) > ulBitRate)
|
|
{
|
|
ulDesiredRatio += 1;
|
|
}
|
|
|
|
//
|
|
// Check all possible values to find a matching value.
|
|
//
|
|
while(ulDesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR))
|
|
{
|
|
//
|
|
// Loop through all possible CAN bit divisors.
|
|
//
|
|
for(ulCANBits = CAN_MAX_BIT_DIVISOR; ulCANBits >= CAN_MIN_BIT_DIVISOR;
|
|
ulCANBits--)
|
|
{
|
|
//
|
|
// For a given CAN bit divisor save the pre divisor.
|
|
//
|
|
ulPreDivide = ulDesiredRatio / ulCANBits;
|
|
|
|
//
|
|
// If the calculated divisors match the desired clock ratio then
|
|
// return these bit rate and set the CAN bit timing.
|
|
//
|
|
if((ulPreDivide * ulCANBits) == ulDesiredRatio)
|
|
{
|
|
//
|
|
// Start building the bit timing value by adding the bit timing
|
|
// in time quanta.
|
|
//
|
|
ulRegValue = g_usCANBitValues[ulCANBits - CAN_MIN_BIT_DIVISOR];
|
|
|
|
//
|
|
// To set the bit timing register, the controller must be placed
|
|
// in init mode (if not already), and also configuration change
|
|
// bit enabled. The state of the register should be saved
|
|
// so it can be restored.
|
|
//
|
|
usCANCTL = CANRegRead(ulBase + CAN_O_CTL);
|
|
CANRegWrite(ulBase + CAN_O_CTL,
|
|
usCANCTL | CAN_CTL_INIT | CAN_CTL_CCE);
|
|
|
|
//
|
|
// Now add in the pre-scalar on the bit rate.
|
|
//
|
|
ulRegValue |= ((ulPreDivide - 1) & CAN_BIT_BRP_M);
|
|
|
|
//
|
|
// Set the clock bits in the and the lower bits of the
|
|
// pre-scalar.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_BIT, ulRegValue);
|
|
|
|
//
|
|
// Set the divider upper bits in the extension register.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_BRPE,
|
|
((ulPreDivide - 1) >> 6) & CAN_BRPE_BRPE_M);
|
|
|
|
//
|
|
// Restore the saved CAN Control register.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_CTL, usCANCTL);
|
|
|
|
//
|
|
// Return the computed bit rate.
|
|
//
|
|
return(ulSourceClock / ( ulPreDivide * ulCANBits));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Move the divisor up one and look again. Only in rare cases are
|
|
// more than 2 loops required to find the value.
|
|
//
|
|
ulDesiredRatio++;
|
|
}
|
|
|
|
//
|
|
// A valid combination could not be found, so return 0 to indicate that the
|
|
// bit rate was not changed.
|
|
//
|
|
return(0);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Configures the CAN controller bit timing.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param pClkParms points to the structure with the clock parameters.
|
|
//!
|
|
//! Configures the various timing parameters for the CAN bus bit timing:
|
|
//! Propagation segment, Phase Buffer 1 segment, Phase Buffer 2 segment, and
|
|
//! the Synchronization Jump Width. The values for Propagation and Phase
|
|
//! Buffer 1 segments are derived from the combination
|
|
//! \e pClkParms->uSyncPropPhase1Seg parameter. Phase Buffer 2 is determined
|
|
//! from the \e pClkParms->uPhase2Seg parameter. These two parameters, along
|
|
//! with \e pClkParms->uSJW are based in units of bit time quanta. The actual
|
|
//! quantum time is determined by the \e pClkParms->uQuantumPrescaler value,
|
|
//! which specifies the divisor for the CAN module clock.
|
|
//!
|
|
//! The total bit time, in quanta, will be the sum of the two Seg parameters,
|
|
//! as follows:
|
|
//!
|
|
//! bit_time_q = uSyncPropPhase1Seg + uPhase2Seg + 1
|
|
//!
|
|
//! Note that the Sync_Seg is always one quantum in duration, and will be added
|
|
//! to derive the correct duration of Prop_Seg and Phase1_Seg.
|
|
//!
|
|
//! The equation to determine the actual bit rate is as follows:
|
|
//!
|
|
//! CAN Clock /
|
|
//! ((\e uSyncPropPhase1Seg + \e uPhase2Seg + 1) * (\e uQuantumPrescaler))
|
|
//!
|
|
//! This means that with \e uSyncPropPhase1Seg = 4, \e uPhase2Seg = 1,
|
|
//! \e uQuantumPrescaler = 2 and an 8 MHz CAN clock, that the bit rate will be
|
|
//! (8 MHz) / ((5 + 2 + 1) * 2) or 500 Kbit/sec.
|
|
//!
|
|
//! This function replaces the original CANSetBitTiming() API and performs the
|
|
//! same actions. A macro is provided in <tt>can.h</tt> to map the original
|
|
//! API to this API.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANBitTimingSet(unsigned long ulBase, tCANBitClkParms *pClkParms)
|
|
{
|
|
unsigned int uBitReg;
|
|
unsigned int uSavedInit;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT(pClkParms != 0);
|
|
|
|
//
|
|
// The phase 1 segment must be in the range from 2 to 16.
|
|
//
|
|
ASSERT((pClkParms->uSyncPropPhase1Seg >= 2) &&
|
|
(pClkParms->uSyncPropPhase1Seg <= 16));
|
|
|
|
//
|
|
// The phase 2 segment must be in the range from 1 to 8.
|
|
//
|
|
ASSERT((pClkParms->uPhase2Seg >= 1) && (pClkParms->uPhase2Seg <= 8));
|
|
|
|
//
|
|
// The synchronous jump windows must be in the range from 1 to 4.
|
|
//
|
|
ASSERT((pClkParms->uSJW >= 1) && (pClkParms->uSJW <= 4));
|
|
|
|
//
|
|
// The CAN clock pre-divider must be in the range from 1 to 1024.
|
|
//
|
|
ASSERT((pClkParms->uQuantumPrescaler <= 1024) &&
|
|
(pClkParms->uQuantumPrescaler >= 1));
|
|
|
|
//
|
|
// To set the bit timing register, the controller must be placed in init
|
|
// mode (if not already), and also configuration change bit enabled. State
|
|
// of the init bit should be saved so it can be restored at the end.
|
|
//
|
|
uSavedInit = CANRegRead(ulBase + CAN_O_CTL);
|
|
CANRegWrite(ulBase + CAN_O_CTL, uSavedInit | CAN_CTL_INIT | CAN_CTL_CCE);
|
|
|
|
//
|
|
// Set the bit fields of the bit timing register according to the parms.
|
|
//
|
|
uBitReg = (((pClkParms->uPhase2Seg - 1) << CAN_BIT_TSEG2_S) &
|
|
CAN_BIT_TSEG2_M);
|
|
uBitReg |= (((pClkParms->uSyncPropPhase1Seg - 1) << CAN_BIT_TSEG1_S) &
|
|
CAN_BIT_TSEG1_M);
|
|
uBitReg |= ((pClkParms->uSJW - 1) << CAN_BIT_SJW_S) & CAN_BIT_SJW_M;
|
|
uBitReg |= (pClkParms->uQuantumPrescaler - 1) & CAN_BIT_BRP_M;
|
|
CANRegWrite(ulBase + CAN_O_BIT, uBitReg);
|
|
|
|
//
|
|
// Set the divider upper bits in the extension register.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_BRPE,
|
|
((pClkParms->uQuantumPrescaler - 1) >> 6) & CAN_BRPE_BRPE_M);
|
|
|
|
//
|
|
// Clear the config change bit, and restore the init bit.
|
|
//
|
|
uSavedInit &= ~CAN_CTL_CCE;
|
|
|
|
//
|
|
// If Init was not set before, then clear it.
|
|
//
|
|
if(uSavedInit & CAN_CTL_INIT)
|
|
{
|
|
uSavedInit &= ~CAN_CTL_INIT;
|
|
}
|
|
CANRegWrite(ulBase + CAN_O_CTL, uSavedInit);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Registers an interrupt handler for the CAN controller.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param pfnHandler is a pointer to the function to be called when the
|
|
//! enabled CAN interrupts occur.
|
|
//!
|
|
//! This function registers the interrupt handler in the interrupt vector
|
|
//! table, and enables CAN interrupts on the interrupt controller; specific CAN
|
|
//! interrupt sources must be enabled using CANIntEnable(). The interrupt
|
|
//! handler being registered must clear the source of the interrupt using
|
|
//! CANIntClear().
|
|
//!
|
|
//! If the application is using a static interrupt vector table stored in
|
|
//! flash, then it is not necessary to register the interrupt handler this way.
|
|
//! Instead, IntEnable() should be used to enable CAN interrupts on the
|
|
//! interrupt controller.
|
|
//!
|
|
//! \sa IntRegister() for important information about registering interrupt
|
|
//! handlers.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
|
|
{
|
|
unsigned long ulIntNumber;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
//
|
|
// Get the actual interrupt number for this CAN controller.
|
|
//
|
|
ulIntNumber = CANIntNumberGet(ulBase);
|
|
|
|
//
|
|
// Register the interrupt handler.
|
|
//
|
|
IntRegister(ulIntNumber, pfnHandler);
|
|
|
|
//
|
|
// Enable the Ethernet interrupt.
|
|
//
|
|
IntEnable(ulIntNumber);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Unregisters an interrupt handler for the CAN controller.
|
|
//!
|
|
//! \param ulBase is the base address of the controller.
|
|
//!
|
|
//! This function unregisters the previously registered interrupt handler and
|
|
//! disables the interrupt on the interrupt controller.
|
|
//!
|
|
//! \sa IntRegister() for important information about registering interrupt
|
|
//! handlers.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANIntUnregister(unsigned long ulBase)
|
|
{
|
|
unsigned long ulIntNumber;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
//
|
|
// Get the actual interrupt number for this CAN controller.
|
|
//
|
|
ulIntNumber = CANIntNumberGet(ulBase);
|
|
|
|
//
|
|
// Register the interrupt handler.
|
|
//
|
|
IntUnregister(ulIntNumber);
|
|
|
|
//
|
|
// Disable the CAN interrupt.
|
|
//
|
|
IntDisable(ulIntNumber);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Enables individual CAN controller interrupt sources.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param ulIntFlags is the bit mask of the interrupt sources to be enabled.
|
|
//!
|
|
//! Enables specific interrupt sources of the CAN controller. Only enabled
|
|
//! sources will cause a processor interrupt.
|
|
//!
|
|
//! The \e ulIntFlags parameter is the logical OR of any of the following:
|
|
//!
|
|
//! - \b CAN_INT_ERROR - a controller error condition has occurred
|
|
//! - \b CAN_INT_STATUS - a message transfer has completed, or a bus error has
|
|
//! been detected
|
|
//! - \b CAN_INT_MASTER - allow CAN controller to generate interrupts
|
|
//!
|
|
//! In order to generate any interrupts, \b CAN_INT_MASTER must be enabled.
|
|
//! Further, for any particular transaction from a message object to generate
|
|
//! an interrupt, that message object must have interrupts enabled (see
|
|
//! CANMessageSet()). \b CAN_INT_ERROR will generate an interrupt if the
|
|
//! controller enters the ``bus off'' condition, or if the error counters reach
|
|
//! a limit. \b CAN_INT_STATUS will generate an interrupt under quite a few
|
|
//! status conditions and may provide more interrupts than the application
|
|
//! needs to handle. When an interrupt occurs, use CANIntStatus() to determine
|
|
//! the cause.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT((ulIntFlags & ~(CAN_CTL_EIE | CAN_CTL_SIE | CAN_CTL_IE)) == 0);
|
|
|
|
//
|
|
// Enable the specified interrupts.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_CTL,
|
|
CANRegRead(ulBase + CAN_O_CTL) | ulIntFlags);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Disables individual CAN controller interrupt sources.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param ulIntFlags is the bit mask of the interrupt sources to be disabled.
|
|
//!
|
|
//! Disables the specified CAN controller interrupt sources. Only enabled
|
|
//! interrupt sources can cause a processor interrupt.
|
|
//!
|
|
//! The \e ulIntFlags parameter has the same definition as in the
|
|
//! CANIntEnable() function.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT((ulIntFlags & ~(CAN_CTL_EIE | CAN_CTL_SIE | CAN_CTL_IE)) == 0);
|
|
|
|
//
|
|
// Disable the specified interrupts.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_CTL,
|
|
CANRegRead(ulBase + CAN_O_CTL) & ~(ulIntFlags));
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Returns the current CAN controller interrupt status.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param eIntStsReg indicates which interrupt status register to read
|
|
//!
|
|
//! Returns the value of one of two interrupt status registers. The interrupt
|
|
//! status register read is determined by the \e eIntStsReg parameter, which
|
|
//! can have one of the following values:
|
|
//!
|
|
//! - \b CAN_INT_STS_CAUSE - indicates the cause of the interrupt
|
|
//! - \b CAN_INT_STS_OBJECT - indicates pending interrupts of all message
|
|
//! objects
|
|
//!
|
|
//! \b CAN_INT_STS_CAUSE returns the value of the controller interrupt register
|
|
//! and indicates the cause of the interrupt. It will be a value of
|
|
//! \b CAN_INT_INTID_STATUS if the cause is a status interrupt. In this case,
|
|
//! the status register should be read with the CANStatusGet() function.
|
|
//! Calling this function to read the status will also clear the status
|
|
//! interrupt. If the value of the interrupt register is in the range 1-32,
|
|
//! then this indicates the number of the highest priority message object that
|
|
//! has an interrupt pending. The message object interrupt can be cleared by
|
|
//! using the CANIntClear() function, or by reading the message using
|
|
//! CANMessageGet() in the case of a received message. The interrupt handler
|
|
//! can read the interrupt status again to make sure all pending interrupts are
|
|
//! cleared before returning from the interrupt.
|
|
//!
|
|
//! \b CAN_INT_STS_OBJECT returns a bit mask indicating which message objects
|
|
//! have pending interrupts. This can be used to discover all of the pending
|
|
//! interrupts at once, as opposed to repeatedly reading the interrupt register
|
|
//! by using \b CAN_INT_STS_CAUSE.
|
|
//!
|
|
//! \return Returns the value of one of the interrupt status registers.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
CANIntStatus(unsigned long ulBase, tCANIntStsReg eIntStsReg)
|
|
{
|
|
unsigned long ulStatus;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
//
|
|
// See which status the caller is looking for.
|
|
//
|
|
switch(eIntStsReg)
|
|
{
|
|
//
|
|
// The caller wants the global interrupt status for the CAN controller
|
|
// specified by ulBase.
|
|
//
|
|
case CAN_INT_STS_CAUSE:
|
|
{
|
|
ulStatus = CANRegRead(ulBase + CAN_O_INT);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// The caller wants the current message status interrupt for all
|
|
// messages.
|
|
//
|
|
case CAN_INT_STS_OBJECT:
|
|
{
|
|
//
|
|
// Read and combine both 16 bit values into one 32bit status.
|
|
//
|
|
ulStatus = (CANRegRead(ulBase + CAN_O_MSG1INT) &
|
|
CAN_MSG1INT_INTPND_M);
|
|
ulStatus |= (CANRegRead(ulBase + CAN_O_MSG2INT) << 16);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Request was for unknown status so just return 0.
|
|
//
|
|
default:
|
|
{
|
|
ulStatus = 0;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Return the interrupt status value
|
|
//
|
|
return(ulStatus);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Clears a CAN interrupt source.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param ulIntClr is a value indicating which interrupt source to clear.
|
|
//!
|
|
//! This function can be used to clear a specific interrupt source. The
|
|
//! \e ulIntClr parameter should be one of the following values:
|
|
//!
|
|
//! - \b CAN_INT_INTID_STATUS - Clears a status interrupt.
|
|
//! - 1-32 - Clears the specified message object interrupt
|
|
//!
|
|
//! It is not necessary to use this function to clear an interrupt. This
|
|
//! should only be used if the application wants to clear an interrupt source
|
|
//! without taking the normal interrupt action.
|
|
//!
|
|
//! Normally, the status interrupt is cleared by reading the controller status
|
|
//! using CANStatusGet(). A specific message object interrupt is normally
|
|
//! cleared by reading the message object using CANMessageGet().
|
|
//!
|
|
//! \note Since there is a write buffer in the Cortex-M3 processor, it may take
|
|
//! several clock cycles before the interrupt source is actually cleared.
|
|
//! Therefore, it is recommended that the interrupt source be cleared early in
|
|
//! the interrupt handler (as opposed to the very last action) to avoid
|
|
//! returning from the interrupt handler before the interrupt source is
|
|
//! actually cleared. Failure to do so may result in the interrupt handler
|
|
//! being immediately reentered (since NVIC still sees the interrupt source
|
|
//! asserted).
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANIntClear(unsigned long ulBase, unsigned long ulIntClr)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT((ulIntClr == CAN_INT_INTID_STATUS) ||
|
|
((ulIntClr>=1) && (ulIntClr <=32)));
|
|
|
|
if(ulIntClr == CAN_INT_INTID_STATUS)
|
|
{
|
|
//
|
|
// Simply read and discard the status to clear the interrupt.
|
|
//
|
|
CANRegRead(ulBase + CAN_O_STS);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Wait to be sure that this interface is not busy.
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Only change the interrupt pending state by setting only the
|
|
// CAN_IF1CMSK_CLRINTPND bit.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CMSK, CAN_IF1CMSK_CLRINTPND);
|
|
|
|
//
|
|
// Send the clear pending interrupt command to the CAN controller.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CRQ, ulIntClr & CAN_IF1CRQ_MNUM_M);
|
|
|
|
//
|
|
// Wait to be sure that this interface is not busy.
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Sets the CAN controller automatic retransmission behavior.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param bAutoRetry enables automatic retransmission.
|
|
//!
|
|
//! Enables or disables automatic retransmission of messages with detected
|
|
//! errors. If \e bAutoRetry is \b true, then automatic retransmission is
|
|
//! enabled, otherwise it is disabled.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANRetrySet(unsigned long ulBase, tBoolean bAutoRetry)
|
|
{
|
|
unsigned long ulCtlReg;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
ulCtlReg = CANRegRead(ulBase + CAN_O_CTL);
|
|
|
|
//
|
|
// Conditionally set the DAR bit to enable/disable auto-retry.
|
|
//
|
|
if(bAutoRetry)
|
|
{
|
|
//
|
|
// Clearing the DAR bit tells the controller to not disable the
|
|
// auto-retry of messages which were not transmitted or received
|
|
// correctly.
|
|
//
|
|
ulCtlReg &= ~CAN_CTL_DAR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Setting the DAR bit tells the controller to disable the auto-retry
|
|
// of messages which were not transmitted or received correctly.
|
|
//
|
|
ulCtlReg |= CAN_CTL_DAR;
|
|
}
|
|
|
|
CANRegWrite(ulBase + CAN_O_CTL, ulCtlReg);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Returns the current setting for automatic retransmission.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//!
|
|
//! Reads the current setting for the automatic retransmission in the CAN
|
|
//! controller and returns it to the caller.
|
|
//!
|
|
//! \return Returns \b true if automatic retransmission is enabled, \b false
|
|
//! otherwise.
|
|
//
|
|
//*****************************************************************************
|
|
tBoolean
|
|
CANRetryGet(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
//
|
|
// Read the disable automatic retry setting from the CAN controller.
|
|
//
|
|
if(CANRegRead(ulBase + CAN_O_CTL) & CAN_CTL_DAR)
|
|
{
|
|
//
|
|
// Automatic data retransmission is not enabled.
|
|
//
|
|
return(false);
|
|
}
|
|
|
|
//
|
|
// Automatic data retransmission is enabled.
|
|
//
|
|
return(true);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Reads one of the controller status registers.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param eStatusReg is the status register to read.
|
|
//!
|
|
//! Reads a status register of the CAN controller and returns it to the caller.
|
|
//! The different status registers are:
|
|
//!
|
|
//! - \b CAN_STS_CONTROL - the main controller status
|
|
//! - \b CAN_STS_TXREQUEST - bit mask of objects pending transmission
|
|
//! - \b CAN_STS_NEWDAT - bit mask of objects with new data
|
|
//! - \b CAN_STS_MSGVAL - bit mask of objects with valid configuration
|
|
//!
|
|
//! When reading the main controller status register, a pending status
|
|
//! interrupt will be cleared. This should be used in the interrupt handler
|
|
//! for the CAN controller if the cause is a status interrupt. The controller
|
|
//! status register fields are as follows:
|
|
//!
|
|
//! - \b CAN_STATUS_BUS_OFF - controller is in bus-off condition
|
|
//! - \b CAN_STATUS_EWARN - an error counter has reached a limit of at least 96
|
|
//! - \b CAN_STATUS_EPASS - CAN controller is in the error passive state
|
|
//! - \b CAN_STATUS_RXOK - a message was received successfully (independent of
|
|
//! any message filtering).
|
|
//! - \b CAN_STATUS_TXOK - a message was successfully transmitted
|
|
//! - \b CAN_STATUS_LEC_MSK - mask of last error code bits (3 bits)
|
|
//! - \b CAN_STATUS_LEC_NONE - no error
|
|
//! - \b CAN_STATUS_LEC_STUFF - stuffing error detected
|
|
//! - \b CAN_STATUS_LEC_FORM - a format error occurred in the fixed format part
|
|
//! of a message
|
|
//! - \b CAN_STATUS_LEC_ACK - a transmitted message was not acknowledged
|
|
//! - \b CAN_STATUS_LEC_BIT1 - dominant level detected when trying to send in
|
|
//! recessive mode
|
|
//! - \b CAN_STATUS_LEC_BIT0 - recessive level detected when trying to send in
|
|
//! dominant mode
|
|
//! - \b CAN_STATUS_LEC_CRC - CRC error in received message
|
|
//!
|
|
//! The remaining status registers are 32-bit bit maps to the message objects.
|
|
//! They can be used to quickly obtain information about the status of all the
|
|
//! message objects without needing to query each one. They contain the
|
|
//! following information:
|
|
//!
|
|
//! - \b CAN_STS_TXREQUEST - if a message object's TxRequest bit is set, that
|
|
//! means that a transmission is pending on that object. The application can
|
|
//! use this to determine which objects are still waiting to send a message.
|
|
//! - \b CAN_STS_NEWDAT - if a message object's NewDat bit is set, that means
|
|
//! that a new message has been received in that object, and has not yet been
|
|
//! picked up by the host application
|
|
//! - \b CAN_STS_MSGVAL - if a message object's MsgVal bit is set, that means
|
|
//! it has a valid configuration programmed. The host application can use this
|
|
//! to determine which message objects are empty/unused.
|
|
//!
|
|
//! \return Returns the value of the status register.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
CANStatusGet(unsigned long ulBase, tCANStsReg eStatusReg)
|
|
{
|
|
unsigned long ulStatus;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
switch(eStatusReg)
|
|
{
|
|
//
|
|
// Just return the global CAN status register since that is what was
|
|
// requested.
|
|
//
|
|
case CAN_STS_CONTROL:
|
|
{
|
|
ulStatus = CANRegRead(ulBase + CAN_O_STS);
|
|
CANRegWrite(ulBase + CAN_O_STS,
|
|
~(CAN_STS_RXOK | CAN_STS_TXOK | CAN_STS_LEC_M));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Combine the Transmit status bits into one 32bit value.
|
|
//
|
|
case CAN_STS_TXREQUEST:
|
|
{
|
|
ulStatus = CANRegRead(ulBase + CAN_O_TXRQ1);
|
|
ulStatus |= CANRegRead(ulBase + CAN_O_TXRQ2) << 16;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Combine the New Data status bits into one 32bit value.
|
|
//
|
|
case CAN_STS_NEWDAT:
|
|
{
|
|
ulStatus = CANRegRead(ulBase + CAN_O_NWDA1);
|
|
ulStatus |= CANRegRead(ulBase + CAN_O_NWDA2) << 16;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Combine the Message valid status bits into one 32bit value.
|
|
//
|
|
case CAN_STS_MSGVAL:
|
|
{
|
|
ulStatus = CANRegRead(ulBase + CAN_O_MSG1VAL);
|
|
ulStatus |= CANRegRead(ulBase + CAN_O_MSG2VAL) << 16;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Unknown CAN status requested so return 0.
|
|
//
|
|
default:
|
|
{
|
|
ulStatus = 0;
|
|
break;
|
|
}
|
|
}
|
|
return(ulStatus);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Reads the CAN controller error counter register.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param pulRxCount is a pointer to storage for the receive error counter.
|
|
//! \param pulTxCount is a pointer to storage for the transmit error counter.
|
|
//!
|
|
//! Reads the error counter register and returns the transmit and receive error
|
|
//! counts to the caller along with a flag indicating if the controller receive
|
|
//! counter has reached the error passive limit. The values of the receive and
|
|
//! transmit error counters are returned through the pointers provided as
|
|
//! parameters.
|
|
//!
|
|
//! After this call, \e *pulRxCount will hold the current receive error count
|
|
//! and \e *pulTxCount will hold the current transmit error count.
|
|
//!
|
|
//! \return Returns \b true if the receive error count has reached the error
|
|
//! passive limit, and \b false if the error count is below the error passive
|
|
//! limit.
|
|
//
|
|
//*****************************************************************************
|
|
tBoolean
|
|
CANErrCntrGet(unsigned long ulBase, unsigned long *pulRxCount,
|
|
unsigned long *pulTxCount)
|
|
{
|
|
unsigned long ulCANError;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
|
|
//
|
|
// Read the current count of transmit/receive errors.
|
|
//
|
|
ulCANError = CANRegRead(ulBase + CAN_O_ERR);
|
|
|
|
//
|
|
// Extract the error numbers from the register value.
|
|
//
|
|
*pulRxCount = (ulCANError & CAN_ERR_REC_M) >> CAN_ERR_REC_S;
|
|
*pulTxCount = (ulCANError & CAN_ERR_TEC_M) >> CAN_ERR_TEC_S;
|
|
|
|
if(ulCANError & CAN_ERR_RP)
|
|
{
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Configures a message object in the CAN controller.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param ulObjID is the object number to configure (1-32).
|
|
//! \param pMsgObject is a pointer to a structure containing message object
|
|
//! settings.
|
|
//! \param eMsgType indicates the type of message for this object.
|
|
//!
|
|
//! This function is used to configure any one of the 32 message objects in the
|
|
//! CAN controller. A message object can be configured as any type of CAN
|
|
//! message object as well as several options for automatic transmission and
|
|
//! reception. This call also allows the message object to be configured to
|
|
//! generate interrupts on completion of message receipt or transmission. The
|
|
//! message object can also be configured with a filter/mask so that actions
|
|
//! are only taken when a message that meets certain parameters is seen on the
|
|
//! CAN bus.
|
|
//!
|
|
//! The \e eMsgType parameter must be one of the following values:
|
|
//!
|
|
//! - \b MSG_OBJ_TYPE_TX - CAN transmit message object.
|
|
//! - \b MSG_OBJ_TYPE_TX_REMOTE - CAN transmit remote request message object.
|
|
//! - \b MSG_OBJ_TYPE_RX - CAN receive message object.
|
|
//! - \b MSG_OBJ_TYPE_RX_REMOTE - CAN receive remote request message object.
|
|
//! - \b MSG_OBJ_TYPE_RXTX_REMOTE - CAN remote frame receive remote, then
|
|
//! transmit message object.
|
|
//!
|
|
//! The message object pointed to by \e pMsgObject must be populated by the
|
|
//! caller, as follows:
|
|
//!
|
|
//! - \e ulMsgID - contains the message ID, either 11 or 29 bits.
|
|
//! - \e ulMsgIDMask - mask of bits from \e ulMsgID that must match if
|
|
//! identifier filtering is enabled.
|
|
//! - \e ulFlags
|
|
//! - Set \b MSG_OBJ_TX_INT_ENABLE flag to enable interrupt on transmission.
|
|
//! - Set \b MSG_OBJ_RX_INT_ENABLE flag to enable interrupt on receipt.
|
|
//! - Set \b MSG_OBJ_USE_ID_FILTER flag to enable filtering based on the
|
|
//! identifier mask specified by \e ulMsgIDMask.
|
|
//! - \e ulMsgLen - the number of bytes in the message data. This should be
|
|
//! non-zero even for a remote frame; it should match the expected bytes of the
|
|
//! data responding data frame.
|
|
//! - \e pucMsgData - points to a buffer containing up to 8 bytes of data for a
|
|
//! data frame.
|
|
//!
|
|
//! \b Example: To send a data frame or remote frame(in response to a remote
|
|
//! request), take the following steps:
|
|
//!
|
|
//! -# Set \e eMsgType to \b MSG_OBJ_TYPE_TX.
|
|
//! -# Set \e pMsgObject->ulMsgID to the message ID.
|
|
//! -# Set \e pMsgObject->ulFlags. Make sure to set \b MSG_OBJ_TX_INT_ENABLE to
|
|
//! allow an interrupt to be generated when the message is sent.
|
|
//! -# Set \e pMsgObject->ulMsgLen to the number of bytes in the data frame.
|
|
//! -# Set \e pMsgObject->pucMsgData to point to an array containing the bytes
|
|
//! to send in the message.
|
|
//! -# Call this function with \e ulObjID set to one of the 32 object buffers.
|
|
//!
|
|
//! \b Example: To receive a specific data frame, take the following steps:
|
|
//!
|
|
//! -# Set \e eMsgObjType to \b MSG_OBJ_TYPE_RX.
|
|
//! -# Set \e pMsgObject->ulMsgID to the full message ID, or a partial mask to
|
|
//! use partial ID matching.
|
|
//! -# Set \e pMsgObject->ulMsgIDMask bits that should be used for masking
|
|
//! during comparison.
|
|
//! -# Set \e pMsgObject->ulFlags as follows:
|
|
//! - Set \b MSG_OBJ_RX_INT_ENABLE flag to be interrupted when the data frame
|
|
//! is received.
|
|
//! - Set \b MSG_OBJ_USE_ID_FILTER flag to enable identifier based filtering.
|
|
//! -# Set \e pMsgObject->ulMsgLen to the number of bytes in the expected data
|
|
//! frame.
|
|
//! -# The buffer pointed to by \e pMsgObject->pucMsgData is not used by this
|
|
//! call as no data is present at the time of the call.
|
|
//! -# Call this function with \e ulObjID set to one of the 32 object buffers.
|
|
//!
|
|
//! If you specify a message object buffer that already contains a message
|
|
//! definition, it will be overwritten.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANMessageSet(unsigned long ulBase, unsigned long ulObjID,
|
|
tCANMsgObject *pMsgObject, tMsgObjType eMsgType)
|
|
{
|
|
unsigned short usCmdMaskReg;
|
|
unsigned short usMaskReg0, usMaskReg1;
|
|
unsigned short usArbReg0, usArbReg1;
|
|
unsigned short usMsgCtrl;
|
|
tBoolean bTransferData;
|
|
tBoolean bUseExtendedID;
|
|
|
|
bTransferData = 0;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT((ulObjID <= 32) && (ulObjID != 0));
|
|
ASSERT((eMsgType == MSG_OBJ_TYPE_TX) ||
|
|
(eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
|
|
(eMsgType == MSG_OBJ_TYPE_RX) ||
|
|
(eMsgType == MSG_OBJ_TYPE_RX_REMOTE) ||
|
|
(eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
|
|
(eMsgType == MSG_OBJ_TYPE_RXTX_REMOTE));
|
|
|
|
//
|
|
// Wait for busy bit to clear
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
|
|
//
|
|
// See if we need to use an extended identifier or not.
|
|
//
|
|
if((pMsgObject->ulMsgID > CAN_MAX_11BIT_MSG_ID) ||
|
|
(pMsgObject->ulFlags & MSG_OBJ_EXTENDED_ID))
|
|
{
|
|
bUseExtendedID = 1;
|
|
}
|
|
else
|
|
{
|
|
bUseExtendedID = 0;
|
|
}
|
|
|
|
//
|
|
// This is always a write to the Message object as this call is setting a
|
|
// message object. This call will also always set all size bits so it sets
|
|
// both data bits. The call will use the CONTROL register to set control
|
|
// bits so this bit needs to be set as well.
|
|
//
|
|
usCmdMaskReg = (CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_DATAA | CAN_IF1CMSK_DATAB |
|
|
CAN_IF1CMSK_CONTROL);
|
|
|
|
//
|
|
// Initialize the values to a known state before filling them in based on
|
|
// the type of message object that is being configured.
|
|
//
|
|
usArbReg0 = 0;
|
|
usArbReg1 = 0;
|
|
usMsgCtrl = 0;
|
|
usMaskReg0 = 0;
|
|
usMaskReg1 = 0;
|
|
|
|
switch(eMsgType)
|
|
{
|
|
//
|
|
// Transmit message object.
|
|
//
|
|
case MSG_OBJ_TYPE_TX:
|
|
{
|
|
//
|
|
// Set the TXRQST bit and the reset the rest of the register.
|
|
//
|
|
usMsgCtrl |= CAN_IF1MCTL_TXRQST;
|
|
usArbReg1 = CAN_IF1ARB2_DIR;
|
|
bTransferData = 1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Transmit remote request message object
|
|
//
|
|
case MSG_OBJ_TYPE_TX_REMOTE:
|
|
{
|
|
//
|
|
// Set the TXRQST bit and the reset the rest of the register.
|
|
//
|
|
usMsgCtrl |= CAN_IF1MCTL_TXRQST;
|
|
usArbReg1 = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Receive message object.
|
|
//
|
|
case MSG_OBJ_TYPE_RX:
|
|
{
|
|
//
|
|
// This clears the DIR bit along with everything else. The TXRQST
|
|
// bit was cleared by defaulting usMsgCtrl to 0.
|
|
//
|
|
usArbReg1 = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Receive remote request message object.
|
|
//
|
|
case MSG_OBJ_TYPE_RX_REMOTE:
|
|
{
|
|
//
|
|
// The DIR bit is set to one for remote receivers. The TXRQST bit
|
|
// was cleared by defaulting usMsgCtrl to 0.
|
|
//
|
|
usArbReg1 = CAN_IF1ARB2_DIR;
|
|
|
|
//
|
|
// Set this object so that it only indicates that a remote frame
|
|
// was received and allow for software to handle it by sending back
|
|
// a data frame.
|
|
//
|
|
usMsgCtrl = CAN_IF1MCTL_UMASK;
|
|
|
|
//
|
|
// Use the full Identifier by default.
|
|
//
|
|
usMaskReg0 = 0xffff;
|
|
usMaskReg1 = 0x1fff;
|
|
|
|
//
|
|
// Make sure to send the mask to the message object.
|
|
//
|
|
usCmdMaskReg |= CAN_IF1CMSK_MASK;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Remote frame receive remote, with auto-transmit message object.
|
|
//
|
|
case MSG_OBJ_TYPE_RXTX_REMOTE:
|
|
{
|
|
//
|
|
// Oddly the DIR bit is set to one for remote receivers.
|
|
//
|
|
usArbReg1 = CAN_IF1ARB2_DIR;
|
|
|
|
//
|
|
// Set this object to auto answer if a matching identifier is seen.
|
|
//
|
|
usMsgCtrl = CAN_IF1MCTL_RMTEN | CAN_IF1MCTL_UMASK;
|
|
|
|
//
|
|
// The data to be returned needs to be filled in.
|
|
//
|
|
bTransferData = 1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// This case should never happen due to the ASSERT statement at the
|
|
// beginning of this function.
|
|
//
|
|
default:
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Configure the Mask Registers.
|
|
//
|
|
if(pMsgObject->ulFlags & MSG_OBJ_USE_ID_FILTER)
|
|
{
|
|
if(bUseExtendedID)
|
|
{
|
|
//
|
|
// Set the 29 bits of Identifier mask that were requested.
|
|
//
|
|
usMaskReg0 = pMsgObject->ulMsgIDMask & CAN_IF1MSK1_IDMSK_M;
|
|
usMaskReg1 = ((pMsgObject->ulMsgIDMask >> 16) &
|
|
CAN_IF1MSK2_IDMSK_M);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Lower 16 bit are unused so set them to zero.
|
|
//
|
|
usMaskReg0 = 0;
|
|
|
|
//
|
|
// Put the 11 bit Mask Identifier into the upper bits of the field
|
|
// in the register.
|
|
//
|
|
usMaskReg1 = ((pMsgObject->ulMsgIDMask << 2) &
|
|
CAN_IF1MSK2_IDMSK_M);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the caller wants to filter on the extended ID bit then set it.
|
|
//
|
|
if((pMsgObject->ulFlags & MSG_OBJ_USE_EXT_FILTER) ==
|
|
MSG_OBJ_USE_EXT_FILTER)
|
|
{
|
|
usMaskReg1 |= CAN_IF1MSK2_MXTD;
|
|
}
|
|
|
|
//
|
|
// The caller wants to filter on the message direction field.
|
|
//
|
|
if((pMsgObject->ulFlags & MSG_OBJ_USE_DIR_FILTER) ==
|
|
MSG_OBJ_USE_DIR_FILTER)
|
|
{
|
|
usMaskReg1 |= CAN_IF1MSK2_MDIR;
|
|
}
|
|
|
|
if(pMsgObject->ulFlags & (MSG_OBJ_USE_ID_FILTER | MSG_OBJ_USE_DIR_FILTER |
|
|
MSG_OBJ_USE_EXT_FILTER))
|
|
{
|
|
//
|
|
// Set the UMASK bit to enable using the mask register.
|
|
//
|
|
usMsgCtrl |= CAN_IF1MCTL_UMASK;
|
|
|
|
//
|
|
// Set the MASK bit so that this gets transferred to the Message Object.
|
|
//
|
|
usCmdMaskReg |= CAN_IF1CMSK_MASK;
|
|
}
|
|
|
|
//
|
|
// Set the Arb bit so that this gets transferred to the Message object.
|
|
//
|
|
usCmdMaskReg |= CAN_IF1CMSK_ARB;
|
|
|
|
//
|
|
// Configure the Arbitration registers.
|
|
//
|
|
if(bUseExtendedID)
|
|
{
|
|
//
|
|
// Set the 29 bit version of the Identifier for this message object.
|
|
//
|
|
usArbReg0 |= pMsgObject->ulMsgID & CAN_IF1ARB1_ID_M;
|
|
usArbReg1 |= (pMsgObject->ulMsgID >> 16) & CAN_IF1ARB2_ID_M;
|
|
|
|
//
|
|
// Mark the message as valid and set the extended ID bit.
|
|
//
|
|
usArbReg1 |= CAN_IF1ARB2_MSGVAL | CAN_IF1ARB2_XTD;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set the 11 bit version of the Identifier for this message object.
|
|
// The lower 18 bits are set to zero.
|
|
//
|
|
usArbReg1 |= (pMsgObject->ulMsgID << 2) & CAN_IF1ARB2_ID_M;
|
|
|
|
//
|
|
// Mark the message as valid.
|
|
//
|
|
usArbReg1 |= CAN_IF1ARB2_MSGVAL;
|
|
}
|
|
|
|
//
|
|
// Set the data length since this is set for all transfers. This is also a
|
|
// single transfer and not a FIFO transfer so set EOB bit.
|
|
//
|
|
usMsgCtrl |= (pMsgObject->ulMsgLen & CAN_IF1MCTL_DLC_M);
|
|
|
|
//
|
|
// Mark this as the last entry if this is not the last entry in a FIFO.
|
|
//
|
|
if((pMsgObject->ulFlags & MSG_OBJ_FIFO) == 0)
|
|
{
|
|
usMsgCtrl |= CAN_IF1MCTL_EOB;
|
|
}
|
|
|
|
//
|
|
// Enable transmit interrupts if they should be enabled.
|
|
//
|
|
if(pMsgObject->ulFlags & MSG_OBJ_TX_INT_ENABLE)
|
|
{
|
|
usMsgCtrl |= CAN_IF1MCTL_TXIE;
|
|
}
|
|
|
|
//
|
|
// Enable receive interrupts if they should be enabled.
|
|
//
|
|
if(pMsgObject->ulFlags & MSG_OBJ_RX_INT_ENABLE)
|
|
{
|
|
usMsgCtrl |= CAN_IF1MCTL_RXIE;
|
|
}
|
|
|
|
//
|
|
// Write the data out to the CAN Data registers if needed.
|
|
//
|
|
if(bTransferData)
|
|
{
|
|
CANDataRegWrite(pMsgObject->pucMsgData,
|
|
(unsigned long *)(ulBase + CAN_O_IF1DA1),
|
|
pMsgObject->ulMsgLen);
|
|
}
|
|
|
|
//
|
|
// Write out the registers to program the message object.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CMSK, usCmdMaskReg);
|
|
CANRegWrite(ulBase + CAN_O_IF1MSK1, usMaskReg0);
|
|
CANRegWrite(ulBase + CAN_O_IF1MSK2, usMaskReg1);
|
|
CANRegWrite(ulBase + CAN_O_IF1ARB1, usArbReg0);
|
|
CANRegWrite(ulBase + CAN_O_IF1ARB2, usArbReg1);
|
|
CANRegWrite(ulBase + CAN_O_IF1MCTL, usMsgCtrl);
|
|
|
|
//
|
|
// Transfer the message object to the message object specifiec by ulObjID.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);
|
|
|
|
return;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Reads a CAN message from one of the message object buffers.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param ulObjID is the object number to read (1-32).
|
|
//! \param pMsgObject points to a structure containing message object fields.
|
|
//! \param bClrPendingInt indicates whether an associated interrupt should be
|
|
//! cleared.
|
|
//!
|
|
//! This function is used to read the contents of one of the 32 message objects
|
|
//! in the CAN controller, and return it to the caller. The data returned is
|
|
//! stored in the fields of the caller-supplied structure pointed to by
|
|
//! \e pMsgObject. The data consists of all of the parts of a CAN message,
|
|
//! plus some control and status information.
|
|
//!
|
|
//! Normally this is used to read a message object that has received and stored
|
|
//! a CAN message with a certain identifier. However, this could also be used
|
|
//! to read the contents of a message object in order to load the fields of the
|
|
//! structure in case only part of the structure needs to be changed from a
|
|
//! previous setting.
|
|
//!
|
|
//! When using CANMessageGet, all of the same fields of the structure are
|
|
//! populated in the same way as when the CANMessageSet() function is used,
|
|
//! with the following exceptions:
|
|
//!
|
|
//! \e pMsgObject->ulFlags:
|
|
//!
|
|
//! - \b MSG_OBJ_NEW_DATA indicates if this is new data since the last time it
|
|
//! was read
|
|
//! - \b MSG_OBJ_DATA_LOST indicates that at least one message was received on
|
|
//! this message object, and not read by the host before being overwritten.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANMessageGet(unsigned long ulBase, unsigned long ulObjID,
|
|
tCANMsgObject *pMsgObject, tBoolean bClrPendingInt)
|
|
{
|
|
unsigned short usCmdMaskReg;
|
|
unsigned short usMaskReg0, usMaskReg1;
|
|
unsigned short usArbReg0, usArbReg1;
|
|
unsigned short usMsgCtrl;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT((ulObjID <= 32) && (ulObjID != 0));
|
|
|
|
//
|
|
// This is always a read to the Message object as this call is setting a
|
|
// message object.
|
|
//
|
|
usCmdMaskReg = (CAN_IF1CMSK_DATAA | CAN_IF1CMSK_DATAB |
|
|
CAN_IF1CMSK_CONTROL | CAN_IF1CMSK_MASK | CAN_IF1CMSK_ARB);
|
|
|
|
//
|
|
// Clear a pending interrupt and new data in a message object.
|
|
//
|
|
if(bClrPendingInt)
|
|
{
|
|
usCmdMaskReg |= CAN_IF1CMSK_CLRINTPND;
|
|
}
|
|
|
|
//
|
|
// Set up the request for data from the message object.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF2CMSK, usCmdMaskReg);
|
|
|
|
//
|
|
// Transfer the message object to the message object specified by ulObjID.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF2CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);
|
|
|
|
//
|
|
// Wait for busy bit to clear
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF2CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Read out the IF Registers.
|
|
//
|
|
usMaskReg0 = CANRegRead(ulBase + CAN_O_IF2MSK1);
|
|
usMaskReg1 = CANRegRead(ulBase + CAN_O_IF2MSK2);
|
|
usArbReg0 = CANRegRead(ulBase + CAN_O_IF2ARB1);
|
|
usArbReg1 = CANRegRead(ulBase + CAN_O_IF2ARB2);
|
|
usMsgCtrl = CANRegRead(ulBase + CAN_O_IF2MCTL);
|
|
|
|
pMsgObject->ulFlags = MSG_OBJ_NO_FLAGS;
|
|
|
|
//
|
|
// Determine if this is a remote frame by checking the TXRQST and DIR bits.
|
|
//
|
|
if((!(usMsgCtrl & CAN_IF1MCTL_TXRQST) && (usArbReg1 & CAN_IF1ARB2_DIR)) ||
|
|
((usMsgCtrl & CAN_IF1MCTL_TXRQST) && (!(usArbReg1 & CAN_IF1ARB2_DIR))))
|
|
{
|
|
pMsgObject->ulFlags |= MSG_OBJ_REMOTE_FRAME;
|
|
}
|
|
|
|
//
|
|
// Get the identifier out of the register, the format depends on size of
|
|
// the mask.
|
|
//
|
|
if(usArbReg1 & CAN_IF1ARB2_XTD)
|
|
{
|
|
//
|
|
// Set the 29 bit version of the Identifier for this message object.
|
|
//
|
|
pMsgObject->ulMsgID = ((usArbReg1 & CAN_IF1ARB2_ID_M) << 16) |
|
|
usArbReg0;
|
|
|
|
pMsgObject->ulFlags |= MSG_OBJ_EXTENDED_ID;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The Identifier is an 11 bit value.
|
|
//
|
|
pMsgObject->ulMsgID = (usArbReg1 & CAN_IF1ARB2_ID_M) >> 2;
|
|
}
|
|
|
|
//
|
|
// Indicate that we lost some data.
|
|
//
|
|
if(usMsgCtrl & CAN_IF1MCTL_MSGLST)
|
|
{
|
|
pMsgObject->ulFlags |= MSG_OBJ_DATA_LOST;
|
|
}
|
|
|
|
//
|
|
// Set the flag to indicate if ID masking was used.
|
|
//
|
|
if(usMsgCtrl & CAN_IF1MCTL_UMASK)
|
|
{
|
|
if(usArbReg1 & CAN_IF1ARB2_XTD)
|
|
{
|
|
//
|
|
// The Identifier Mask is assumed to also be a 29 bit value.
|
|
//
|
|
pMsgObject->ulMsgIDMask =
|
|
((usMaskReg1 & CAN_IF1MSK2_IDMSK_M) << 16) | usMaskReg0;
|
|
|
|
//
|
|
// If this is a fully specified Mask and a remote frame then don't
|
|
// set the MSG_OBJ_USE_ID_FILTER because the ID was not really
|
|
// filtered.
|
|
//
|
|
if((pMsgObject->ulMsgIDMask != 0x1fffffff) ||
|
|
((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0))
|
|
{
|
|
pMsgObject->ulFlags |= MSG_OBJ_USE_ID_FILTER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The Identifier Mask is assumed to also be an 11 bit value.
|
|
//
|
|
pMsgObject->ulMsgIDMask = ((usMaskReg1 & CAN_IF1MSK2_IDMSK_M) >>
|
|
2);
|
|
|
|
//
|
|
// If this is a fully specified Mask and a remote frame then don't
|
|
// set the MSG_OBJ_USE_ID_FILTER because the ID was not really
|
|
// filtered.
|
|
//
|
|
if((pMsgObject->ulMsgIDMask != 0x7ff) ||
|
|
((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0))
|
|
{
|
|
pMsgObject->ulFlags |= MSG_OBJ_USE_ID_FILTER;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Indicate if the extended bit was used in filtering.
|
|
//
|
|
if(usMaskReg1 & CAN_IF1MSK2_MXTD)
|
|
{
|
|
pMsgObject->ulFlags |= MSG_OBJ_USE_EXT_FILTER;
|
|
}
|
|
|
|
//
|
|
// Indicate if direction filtering was enabled.
|
|
//
|
|
if(usMaskReg1 & CAN_IF1MSK2_MDIR)
|
|
{
|
|
pMsgObject->ulFlags |= MSG_OBJ_USE_DIR_FILTER;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the interrupt flags.
|
|
//
|
|
if(usMsgCtrl & CAN_IF1MCTL_TXIE)
|
|
{
|
|
pMsgObject->ulFlags |= MSG_OBJ_TX_INT_ENABLE;
|
|
}
|
|
if(usMsgCtrl & CAN_IF1MCTL_RXIE)
|
|
{
|
|
pMsgObject->ulFlags |= MSG_OBJ_RX_INT_ENABLE;
|
|
}
|
|
|
|
//
|
|
// See if there is new data available.
|
|
//
|
|
if(usMsgCtrl & CAN_IF1MCTL_NEWDAT)
|
|
{
|
|
//
|
|
// Get the amount of data needed to be read.
|
|
//
|
|
pMsgObject->ulMsgLen = (usMsgCtrl & CAN_IF1MCTL_DLC_M);
|
|
|
|
//
|
|
// Don't read any data for a remote frame, there is nothing valid in
|
|
// that buffer anyway.
|
|
//
|
|
if((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0)
|
|
{
|
|
//
|
|
// Read out the data from the CAN registers.
|
|
//
|
|
CANDataRegRead(pMsgObject->pucMsgData,
|
|
(unsigned long *)(ulBase + CAN_O_IF2DA1),
|
|
pMsgObject->ulMsgLen);
|
|
}
|
|
|
|
//
|
|
// Now clear out the new data flag.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF2CMSK, CAN_IF1CMSK_NEWDAT);
|
|
|
|
//
|
|
// Transfer the message object to the message object specified by
|
|
// ulObjID.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF2CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);
|
|
|
|
//
|
|
// Wait for busy bit to clear
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF2CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Indicate that there is new data in this message.
|
|
//
|
|
pMsgObject->ulFlags |= MSG_OBJ_NEW_DATA;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Along with the MSG_OBJ_NEW_DATA not being set the amount of data
|
|
// needs to be set to zero if none was available.
|
|
//
|
|
pMsgObject->ulMsgLen = 0;
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Clears a message object so that it is no longer used.
|
|
//!
|
|
//! \param ulBase is the base address of the CAN controller.
|
|
//! \param ulObjID is the message object number to disable (1-32).
|
|
//!
|
|
//! This function frees the specified message object from use. Once a message
|
|
//! object has been ``cleared,'' it will no longer automatically send or
|
|
//! receive messages, or generate interrupts.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
CANMessageClear(unsigned long ulBase, unsigned long ulObjID)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(CANBaseValid(ulBase));
|
|
ASSERT((ulObjID >= 1) && (ulObjID <= 32));
|
|
|
|
//
|
|
// Wait for busy bit to clear
|
|
//
|
|
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Clear the message value bit in the arbitration register. This indicates
|
|
// the message is not valid.
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CMSK, CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB);
|
|
CANRegWrite(ulBase + CAN_O_IF1ARB1, 0);
|
|
CANRegWrite(ulBase + CAN_O_IF1ARB2, 0);
|
|
|
|
//
|
|
// Initiate programming the message object
|
|
//
|
|
CANRegWrite(ulBase + CAN_O_IF1CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Close the Doxygen group.
|
|
//! @}
|
|
//
|
|
//*****************************************************************************
|