empty_project_28377D/device/driverlib/can.c

1121 lines
30 KiB
C
Raw Normal View History

//###########################################################################
//
// FILE: can.c
//
// TITLE: C28x CAN driver.
//
//###########################################################################
// $Copyright:
// Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//###########################################################################
#include "can.h"
//*****************************************************************************
//
// CAN_initModule
//
//*****************************************************************************
void
CAN_initModule(uint32_t base)
{
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
//
// 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.
//
HWREGH(base + CAN_O_CTL) |= ((uint16_t)CAN_CTL_INIT |
(uint16_t)CAN_INIT_PARITY_DISABLE);
//
// Initialize the message RAM before using it.
//
CAN_initRAM(base);
//
// Force module to reset state
//
HWREGH(base + CAN_O_CTL) |= CAN_CTL_SWR;
//
// Delay for 14 cycles
//
SysCtl_delay(1U);
//
// Enable write access to the configuration registers
//
HWREGH(base + CAN_O_CTL) |= CAN_CTL_CCE;
}
//*****************************************************************************
//
// CAN_setBitRate
//
//*****************************************************************************
void
CAN_setBitRate(uint32_t base, uint32_t clockFreq, uint32_t bitRate,
uint16_t bitTime)
{
uint16_t brp;
uint16_t tPhase;
uint16_t phaseSeg2;
uint16_t tSync = 1U;
uint16_t tProp = 2U;
uint16_t tSeg1;
uint16_t tSeg2;
uint16_t sjw;
uint16_t prescaler;
uint16_t prescalerExtension;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((bitTime > 7U) && (bitTime < 26U));
ASSERT(bitRate <= 1000000U);
//
// Calculate bit timing values
//
brp = (uint16_t)(clockFreq / (bitRate * bitTime));
tPhase = bitTime - (tSync + tProp);
if((tPhase / 2U) <= 8U)
{
phaseSeg2 = tPhase / 2U;
}
else
{
phaseSeg2 = 8U;
}
tSeg1 = ((tPhase - phaseSeg2) + tProp) - 1U;
tSeg2 = phaseSeg2 - 1U;
if(phaseSeg2 > 4U)
{
sjw = 3U;
}
else
{
sjw = tSeg2;
}
prescalerExtension = ((brp - 1U) / 64U);
prescaler = ((brp - 1U) % 64U);
//
// Set the calculated timing parameters
//
CAN_setBitTiming(base, prescaler, prescalerExtension, tSeg1, tSeg2, sjw);
}
//*****************************************************************************
//
// CAN_setBitTiming
//
//*****************************************************************************
void
CAN_setBitTiming(uint32_t base, uint16_t prescaler,
uint16_t prescalerExtension, uint16_t tSeg1, uint16_t tSeg2,
uint16_t sjw)
{
uint16_t savedInit;
uint32_t bitReg;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT(prescaler < 64U);
ASSERT((tSeg1 > 0U) && (tSeg1 < 16U));
ASSERT(tSeg2 < 8U);
ASSERT(sjw < 4U);
ASSERT(prescalerExtension < 16U);
//
// 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.
//
savedInit = HWREGH(base + CAN_O_CTL);
HWREGH(base + CAN_O_CTL) = savedInit | CAN_CTL_INIT | CAN_CTL_CCE;
//
// Set the bit fields of the bit timing register
//
bitReg = (uint32_t)((uint32_t)prescaler & CAN_BTR_BRP_M);
bitReg |= (uint32_t)(((uint32_t)sjw << CAN_BTR_SJW_S) & CAN_BTR_SJW_M);
bitReg |= (uint32_t)(((uint32_t)tSeg1 << CAN_BTR_TSEG1_S) &
CAN_BTR_TSEG1_M);
bitReg |= (uint32_t)(((uint32_t)tSeg2 << CAN_BTR_TSEG2_S) &
CAN_BTR_TSEG2_M);
bitReg |= (uint32_t)(((uint32_t)prescalerExtension << CAN_BTR_BRPE_S) &
CAN_BTR_BRPE_M);
HWREG_BP(base + CAN_O_BTR) = bitReg;
//
// Clear the config change bit, and restore the init bit.
//
savedInit &= ~((uint16_t)CAN_CTL_CCE);
HWREGH(base + CAN_O_CTL) = savedInit;
}
//*****************************************************************************
//
// CAN_clearInterruptStatus
//
//*****************************************************************************
void
CAN_clearInterruptStatus(uint32_t base, uint32_t intClr)
{
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((intClr == CAN_INT_INT0ID_STATUS) ||
((intClr >= 1U) && (intClr <= 32U)));
if(intClr == (uint32_t)CAN_INT_INT0ID_STATUS)
{
//
// Simply read and discard the status to clear the interrupt.
//
HWREGH(base + CAN_O_ES);
}
else
{
//
// Wait to be sure that this interface is not busy.
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) ==
CAN_IF1CMD_BUSY)
{
}
//
// Only change the interrupt pending state by setting only the
// CAN_IF1CMD_CLRINTPND bit.
//
// Send the clear pending interrupt command to the CAN controller.
//
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CLRINTPND |
(intClr & CAN_IF1CMD_MSG_NUM_M));
//
// Wait to be sure that this interface is not busy.
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) ==
CAN_IF1CMD_BUSY)
{
}
}
}
//*****************************************************************************
//
// CAN_setupMessageObject
//
//*****************************************************************************
void
CAN_setupMessageObject(uint32_t base, uint32_t objID, uint32_t msgID,
CAN_MsgFrameType frame, CAN_MsgObjType msgType,
uint32_t msgIDMask, uint32_t flags, uint16_t msgLen)
{
uint32_t cmdMaskReg = 0U;
uint32_t maskReg = 0U;
uint32_t arbReg = 0U;
uint32_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID > 0U));
ASSERT(msgLen <= 8U);
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
switch(msgType)
{
//
// Transmit message object.
//
case CAN_MSG_OBJ_TYPE_TX:
{
//
// Set message direction to transmit.
//
arbReg = CAN_IF1ARB_DIR;
break;
}
//
// Remote frame receive remote, with auto-transmit message object.
//
case CAN_MSG_OBJ_TYPE_RXTX_REMOTE:
{
//
// Set message direction to Tx for remote receivers.
//
arbReg = CAN_IF1ARB_DIR;
//
// Set this object to auto answer if a matching identifier is seen.
//
msgCtrl = (uint32_t)((uint32_t)CAN_IF1MCTL_RMTEN |
(uint32_t)CAN_IF1MCTL_UMASK);
break;
}
//
// Transmit remote request message object (CAN_MSG_OBJ_TYPE_TX_REMOTE)
// or Receive message object (CAN_MSG_OBJ_TYPE_RX).
//
default:
{
//
// Set message direction to read.
//
arbReg = 0U;
break;
}
}
//
// Set values based on Extended Frame or Standard Frame
//
if(frame == CAN_MSG_FRAME_EXT)
{
//
// Configure the Mask Registers for 29 bit Identifier mask.
//
if((flags & CAN_MSG_OBJ_USE_ID_FILTER) == CAN_MSG_OBJ_USE_ID_FILTER)
{
maskReg = msgIDMask & CAN_IF1MSK_MSK_M;
}
//
// Set the 29 bit version of the Identifier for this message
// object. Mark the message as valid and set the extended ID bit.
//
arbReg |= (msgID & CAN_IF1ARB_ID_M) | CAN_IF1ARB_MSGVAL |
CAN_IF1ARB_XTD;
}
else
{
//
// Configure the Mask Registers for 11 bit Identifier mask.
//
if((flags & CAN_MSG_OBJ_USE_ID_FILTER) == CAN_MSG_OBJ_USE_ID_FILTER)
{
maskReg = ((msgIDMask << CAN_IF1ARB_STD_ID_S) &
CAN_IF1ARB_STD_ID_M);
}
//
// Set the 11 bit version of the Identifier for this message
// object. The lower 18 bits are set to zero. Mark the message as
// valid.
//
arbReg |= ((msgID << CAN_IF1ARB_STD_ID_S) & CAN_IF1ARB_STD_ID_M) |
CAN_IF1ARB_MSGVAL;
}
//
// If the caller wants to filter on the extended ID bit then set it.
//
maskReg |= (flags & CAN_MSG_OBJ_USE_EXT_FILTER);
//
// The caller wants to filter on the message direction field.
//
maskReg |= (flags & CAN_MSG_OBJ_USE_DIR_FILTER);
//
// If any filtering is requested, set the UMASK bit to use mask register
//
if(((flags & CAN_MSG_OBJ_USE_ID_FILTER) |
(flags & CAN_MSG_OBJ_USE_DIR_FILTER) |
(flags & CAN_MSG_OBJ_USE_EXT_FILTER)) != 0U)
{
msgCtrl |= CAN_IF1MCTL_UMASK;
}
//
// Set the data length for the transfers. This is applicable only for
// Tx mailboxes. For Rx mailboxes, dlc is updated on receving a frame.
//
if((msgType == CAN_MSG_OBJ_TYPE_TX) ||
(msgType == CAN_MSG_OBJ_TYPE_RXTX_REMOTE))
{
msgCtrl |= ((uint32_t)msgLen & CAN_IF1MCTL_DLC_M);
}
//
// If this is a single transfer or the last mailbox of a FIFO, set EOB bit.
// If this is not the last entry in a FIFO, leave the EOB bit as 0.
//
if((flags & CAN_MSG_OBJ_FIFO) == 0U)
{
msgCtrl |= CAN_IF1MCTL_EOB;
}
//
// Enable transmit interrupts if they should be enabled.
//
msgCtrl |= (flags & CAN_MSG_OBJ_TX_INT_ENABLE);
//
// Enable receive interrupts if they should be enabled.
//
msgCtrl |= (flags & CAN_MSG_OBJ_RX_INT_ENABLE);
//
// Set the Control, Arb, and Mask bit so that they get transferred to the
// Message object.
//
cmdMaskReg |= CAN_IF1CMD_ARB;
cmdMaskReg |= CAN_IF1CMD_CONTROL;
cmdMaskReg |= CAN_IF1CMD_MASK;
cmdMaskReg |= CAN_IF1CMD_DIR;
//
// Write out the registers to program the message object.
//
HWREG_BP(base + CAN_O_IF1MSK) = maskReg;
HWREG_BP(base + CAN_O_IF1ARB) = arbReg;
HWREG_BP(base + CAN_O_IF1MCTL) = msgCtrl;
//
// Transfer data to message object RAM
//
HWREG_BP(base + CAN_O_IF1CMD) =
cmdMaskReg | (objID & CAN_IF1CMD_MSG_NUM_M);
}
//*****************************************************************************
//
// CAN_sendMessage
//
//*****************************************************************************
void
CAN_sendMessage(uint32_t base, uint32_t objID, uint16_t msgLen,
const uint16_t *msgData)
{
uint32_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID > 0U));
ASSERT(msgLen <= 8U);
//
// Set IF command to read message object control value
//
// Set up the request for data from the message object.
// Transfer the message object to the IF register.
//
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CONTROL |
(objID & CAN_IF1CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Read IF message control
//
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
//
// Check provided DLC size with actual Message DLC size
//
ASSERT((msgCtrl & CAN_IF1MCTL_DLC_M) == msgLen);
//
// Write the data out to the CAN Data registers.
//
CAN_writeDataReg(msgData, (base + CAN_O_IF1DATA),
(msgCtrl & CAN_IF1MCTL_DLC_M));
//
// Set Data to be transferred from IF
//
if(msgLen > 0U)
{
msgCtrl = CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A;
}
else
{
msgCtrl = 0U;
}
//
// Set Direction to write
//
// Set Tx Request Bit
//
// Transfer the message object to the message object specified by
// objID.
//
HWREG_BP(base + CAN_O_IF1CMD) = (msgCtrl | (uint32_t)CAN_IF1CMD_DIR |
(uint32_t)CAN_IF1CMD_TXRQST |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
//*****************************************************************************
//
// CAN_sendMessage_16bit
//
//*****************************************************************************
void
CAN_sendMessage_16bit(uint32_t base, uint32_t objID, uint16_t msgLen,
const uint16_t *msgData)
{
uint32_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID > 0U));
ASSERT(msgLen <= 8U);
//
// Set IF command to read message object control value
//
// Set up the request for data from the message object.
// Transfer the message object to the IF register.
//
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CONTROL |
(objID & CAN_IF1CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Read IF message control
//
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
//
// Check provided DLC size with actual Message DLC size
//
ASSERT((msgCtrl & CAN_IF1MCTL_DLC_M) == msgLen);
//
// Write the data out to the CAN Data registers.
//
CAN_writeDataReg_16bit(msgData, (base + CAN_O_IF1DATA),
(msgCtrl & CAN_IF1MCTL_DLC_M));
//
// Set Data to be transferred from IF
//
if(msgLen > 0U)
{
msgCtrl = CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A;
}
else
{
msgCtrl = 0U;
}
//
// Set Direction to write
//
// Set Tx Request Bit
//
// Transfer the message object to the message object specified by
// objID.
//
HWREG_BP(base + CAN_O_IF1CMD) = (msgCtrl | (uint32_t)CAN_IF1CMD_DIR |
(uint32_t)CAN_IF1CMD_TXRQST |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
//*****************************************************************************
//
// CAN_sendMessage_32bit
//
//*****************************************************************************
void
CAN_sendMessage_32bit(uint32_t base, uint32_t objID, uint16_t msgLen,
const uint32_t *msgData)
{
uint32_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID > 0U));
ASSERT(msgLen <= 8U);
//
// Set IF command to read message object control value
//
// Set up the request for data from the message object.
// Transfer the message object to the IF register.
//
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CONTROL |
(objID & CAN_IF1CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Read IF message control
//
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
//
// Check provided DLC size with actual Message DLC size
//
ASSERT((msgCtrl & CAN_IF1MCTL_DLC_M) == msgLen);
//
// Write the data out to the CAN Data registers.
//
CAN_writeDataReg_32bit(msgData, (base + CAN_O_IF1DATA),
(msgCtrl & CAN_IF1MCTL_DLC_M));
//
// Set Data to be transferred from IF
//
if(msgLen > 0U)
{
msgCtrl = CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A;
}
else
{
msgCtrl = 0U;
}
//
// Set Direction to write
//
// Set Tx Request Bit
//
// Transfer the message object to the message object specified by
// objID.
//
HWREG_BP(base + CAN_O_IF1CMD) = (msgCtrl | (uint32_t)CAN_IF1CMD_DIR |
(uint32_t)CAN_IF1CMD_TXRQST |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
//*****************************************************************************
//
// CAN_sendMessage_updateDLC
//
//*****************************************************************************
void
CAN_sendMessage_updateDLC(uint32_t base, uint32_t objID, uint16_t msgLen,
const uint16_t *msgData)
{
uint32_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID > 0U));
ASSERT(msgLen <= 8U);
//
// Set IF command to read message object control value
//
// Set up the request for data from the message object.
// Transfer the message object to the IF register.
//
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CONTROL |
(objID & CAN_IF1CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Read IF message control
//
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
//
// Update to the new data length
//
msgCtrl &= ~CAN_IF1MCTL_DLC_M;
msgCtrl |= (msgLen & CAN_IF1MCTL_DLC_M);
//
// Write out to the register to program the message object
//
HWREG_BP(base + CAN_O_IF1MCTL) = msgCtrl;
//
// Transfer data to message object RAM
//
HWREG_BP(base + CAN_O_IF1CMD) =
(CAN_IF1CMD_CONTROL | CAN_IF1CMD_DIR | (objID & CAN_IF1CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Set IF command to read message object control value
//
// Set up the request for data from the message object.
// Transfer the message object to the IF register.
//
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CONTROL |
(objID & CAN_IF1CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Read IF message control
//
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
//
// Check provided DLC size with actual Message DLC size
//
ASSERT((msgCtrl & CAN_IF1MCTL_DLC_M) == msgLen);
//
// Write the data out to the CAN Data registers.
//
CAN_writeDataReg(msgData, (base + CAN_O_IF1DATA),
(msgCtrl & CAN_IF1MCTL_DLC_M));
//
// Set Data to be transferred from IF
//
if(msgLen > 0U)
{
msgCtrl = CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A;
}
else
{
msgCtrl = 0U;
}
//
// Set Direction to write
//
// Set Tx Request Bit
//
// Transfer the message object to the message object specified by
// objID.
//
HWREG_BP(base + CAN_O_IF1CMD) = (msgCtrl | (uint32_t)CAN_IF1CMD_DIR |
(uint32_t)CAN_IF1CMD_TXRQST |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
//*****************************************************************************
//
// CAN_sendRemoteRequestMessage
//
//*****************************************************************************
void
CAN_sendRemoteRequestMessage(uint32_t base, uint32_t objID)
{
uint32_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID > 0U));
//
// Set IF command to read message object control value
//
// Set up the request for data from the message object.
// Transfer the message object to the IF register.
//
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CONTROL |
(objID & CAN_IF1CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Read IF message control
//
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
//
// Check configured DLC size with 0 as this is a remote frame
//
ASSERT((msgCtrl & CAN_IF1MCTL_DLC_M) == 0U);
//
// Set Direction to write
//
// Set Tx Request Bit for this remote frame
//
// Transfer the message object to the message object specified by
// objID.
//
HWREG_BP(base + CAN_O_IF1CMD) = (msgCtrl | (uint32_t)CAN_IF1CMD_DIR |
(uint32_t)CAN_IF1CMD_TXRQST |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
//*****************************************************************************
//
// CAN_readMessage
//
//*****************************************************************************
bool
CAN_readMessage(uint32_t base, uint32_t objID,
uint16_t *msgData)
{
bool status;
uint16_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID != 0U));
//
// Set the Message Data A, Data B, and control values to be read
// on request for data from the message object.
//
// Transfer the message object to the message object IF register.
//
HWREG_BP(base + CAN_O_IF2CMD) =
((uint32_t)CAN_IF2CMD_DATA_A | (uint32_t)CAN_IF2CMD_DATA_B |
(uint32_t)CAN_IF2CMD_CONTROL | (objID & CAN_IF2CMD_MSG_NUM_M) |
(uint32_t)CAN_IF2CMD_ARB);
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY)
{
}
//
// Read out the IF control Register.
//
msgCtrl = HWREGH(base + CAN_O_IF2MCTL);
//
// See if there is new data available.
//
if((msgCtrl & CAN_IF2MCTL_NEWDAT) == CAN_IF2MCTL_NEWDAT)
{
//
// Read out the data from the CAN registers.
//
CAN_readDataReg(msgData, (base + CAN_O_IF2DATA),
((uint32_t)msgCtrl & CAN_IF2MCTL_DLC_M));
status = true;
//
// Now clear out the new data flag
//
HWREG_BP(base + CAN_O_IF2CMD) = ((uint32_t)CAN_IF2CMD_TXRQST |
(objID & CAN_IF2CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) ==
CAN_IF2CMD_BUSY)
{
}
}
else
{
status = false;
}
return(status);
}
//*****************************************************************************
//
// CAN_readMessageWithID
//
//*****************************************************************************
bool CAN_readMessageWithID(uint32_t base,
uint32_t objID,
CAN_MsgFrameType *frameType,
uint32_t *msgID,
uint16_t *msgData)
{
bool status;
//
// Check the pointers.
//
ASSERT(msgID != 0U);
ASSERT(frameType != 0U);
//
//Read the message first this fills the IF2 registers
//with received message for that mailbox
//
status = CAN_readMessage(base, objID, msgData);
//
// See if there is new data available.
//
if(status)
{
if((HWREG_BP(base + CAN_O_IF2ARB) & CAN_IF2ARB_XTD) != 0U)
{
*frameType = CAN_MSG_FRAME_EXT;
*msgID = ((HWREG_BP(base + CAN_O_IF2ARB)) & CAN_IF2ARB_ID_M);
}
else
{
*frameType = CAN_MSG_FRAME_STD;
*msgID = (((HWREG_BP(base + CAN_O_IF2ARB)) &
CAN_IF2ARB_STD_ID_M) >>
CAN_IF2ARB_STD_ID_S);
}
}
return(status);
}
//*****************************************************************************
//
// CAN_transferMessage
//
//*****************************************************************************
void
CAN_transferMessage(uint32_t base, uint16_t interface, uint32_t objID,
bool direction)
{
uint32_t cmdMaskReg;
ASSERT(CAN_isBaseValid(base));
ASSERT((objID >= 1U) && (objID <= 32U));
ASSERT((interface == 1U) || (interface == 2U));
//
// This is always a read to the Message object as this call is setting a
// message object.
//
cmdMaskReg =
((uint32_t)CAN_IF1CMD_DATA_A | (uint32_t)CAN_IF1CMD_DATA_B |
(uint32_t)CAN_IF1CMD_TXRQST | (uint32_t)CAN_IF1CMD_CONTROL |
(uint32_t)CAN_IF1CMD_MASK | (uint32_t)CAN_IF1CMD_ARB) |
(direction ? CAN_IF1CMD_DIR : 0U);
//
// Ensure this IF isn't busy
//
while((HWREGH(base + ((interface == 2U) ? CAN_O_IF2CMD : CAN_O_IF1CMD)) &
CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Set up the request for data from the message object. Transfer the
// message object to the message object specified by objID.
//
HWREG_BP(base + ((interface == 2U) ? CAN_O_IF2CMD : CAN_O_IF1CMD)) =
(cmdMaskReg | (objID & CAN_IF1CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREGH(base + ((interface == 2U) ? CAN_O_IF2CMD : CAN_O_IF1CMD)) &
CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
}
//*****************************************************************************
//
// CAN_clearMessage
//
//*****************************************************************************
void
CAN_clearMessage(uint32_t base, uint32_t objID)
{
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID >= 1U) && (objID <= 32U));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Clear the message valid bit in the arbitration register. This disables
// the mailbox.
//
HWREG_BP(base + CAN_O_IF1ARB) = 0U;
//
// Initiate programming the message object
//
HWREG_BP(base + CAN_O_IF1CMD) =
(((uint32_t)CAN_IF1CMD_DIR | (uint32_t)CAN_IF1CMD_ARB) |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
//*****************************************************************************
//
// CAN_disableMessageObject
//
//*****************************************************************************
void
CAN_disableMessageObject(uint32_t base, uint32_t objID)
{
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID >= 1U) && (objID <= 32U));
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Clear the message valid bit in the arbitration register. This disables
// the mailbox.
//
HWREG_BP(base + CAN_O_IF1ARB) = 0U;
//
// Initiate programming the message object
//
HWREG_BP(base + CAN_O_IF1CMD) =
(((uint32_t)CAN_IF1CMD_DIR | (uint32_t)CAN_IF1CMD_ARB) |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
//*****************************************************************************
//
// CAN_disableAllMessageObjects
//
//*****************************************************************************
void
CAN_disableAllMessageObjects(uint32_t base)
{
uint32_t objID;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
//
// Loop to disable all valid message objects
//
for(objID = 0x01UL; objID <= 0x20UL; objID++)
{
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Clear the message valid bit in the arbitration register. This disables
// the mailbox.
//
HWREG_BP(base + CAN_O_IF1ARB) = 0U;
//
// Initiate programming the message object
//
HWREG_BP(base + CAN_O_IF1CMD) =
(((uint32_t)CAN_IF1CMD_DIR | (uint32_t)CAN_IF1CMD_ARB) |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
}