AM64x MCU+ SDK  08.02.00
MCAN

The Controller Area Network (CAN) is a serial communication protocol which efficiently supports distributed real-time control. The MCAN module supports both classic CAN and CAN FD (CAN with Flexible Data-Rate) specifications. CAN FD feature allows high throughput and increased payload per data frame. The driver provides API's to configure the MCAN module. Below are the high level features supported by the MCAN driver.

Features Supported

  • MCAN module conforms with CAN Protocol 2.0 A, B and ISO 11898-1:2015
  • Configure CAN FD mode to support Full CAN FD (up to 64 data bytes)
  • Transmit and Receive classic CAN and and CAN FD message formats
  • Configure Up to 32 dedicated Transmit Buffers
  • Configure Transmit FIFO, up to 32 elements(Buffer + FIFO combined up to 32)
  • Configure Transmit Event FIFO, up to 32 elements
  • Configure Up to 64 dedicated Receive Buffers
  • Configure Two configurable Receive FIFOs, up to 64 elements each
  • Configure Up to 128 Standard Id filter elements
  • Configure Up to 64 Extended Id filter elements
  • Configure Bit timing parameters
  • Configure Global filter to receive non-matching messages
  • Configure Maskable interrupts and two interrupt lines
  • Api's to read protocol status register(useful in case of communication failures)

SysConfig Features

Note
It is strongly recommend to use SysConfig where it is available instead of using direct SW API calls. This will help simplify the SW application and also catch common mistakes early in the development cycle.

SysConfig can be used to configure below parameters apart from common configuration like Clock, MPU, RAT and others.

  • MCAN instances and pin configurations.

Features NOT Supported

  • DMA mode of operation

Usage

Message Ram Initialization

The MCAN module has implemented Message RAM. The main purpose of the Message RAM is to store:

  • Receive Messages
  • Transmit Messages
  • Tx Event Elements
  • Message ID Filter Elements

User just needs to configure the number of elements required based on their usecase.

Acceptance filtering

The MCAN module is capable to configure two sets of acceptance filters - one set for standard and one set for extended identifiers. These filters can be assigned to an Rx Buffer or to one of the two Rx FIFOs. The main features of the filter elements are:

  • Each filter element can be configured as:
    • Range Filter (from - to)
    • Filter for specific IDs (for one or two dedicated IDs)
    • Classic Bit Mask Filter
  • Each filter element can be enabled/disabled individually
  • Each filter element can be configured for acceptance or rejection filtering
  • Filters are checked sequentially and execution (acceptance filtering procedure) stops at the first matching filter element or when the end of the filter list is reached

Depending on the configuration of the filter element if filter matches, one of the following actions is performed:

  • Received frame is stored in FIFO 0 or FIFO 1
  • Received frame is stored in Rx Buffer

To receive all the messages without acceptance filtering, you need to configure anfe and anfs fields of Global filter register. Please refer section "Acceptance Filtering" in technical reference manual for more details.

Filter Types

Basically there are 3 types of filter which MCAN module supports.

Range Filter

Each filter element can be configured to operate as Range Filter (Standard Filter Type SFT = 00/Extended Filter Type EFT = 00). The filter matches for all received message frames with IDs in the range from SFID1 to SFID2 (SFID2 >= SFID1) and respectively in the range from EFID1 to EFID2 (EFID2 >= EFID1).

There are two options for range filtering of extended frames:

  • Extended Filter Type EFT = 00: The Extended ID AND Mask is used for Range Filtering. The Message ID of received frames is ANDed with the Extended ID AND Mask before the range filter is applied.
  • Extended Filter Type EFT = 11: The Extended ID AND Mask (MCAN_XIDAM) is not used for Range Filtering.

Filter for specific IDs

Each filter element can be configured to filter one or two dedicated Message IDs (Standard Filter Type SFT =01/ Extended Filter Type EFT =01). To filter only one specific Message ID, the filter element has to be configured with SFID1 = SFID2 respectively EFID1 = EFID2.

Classic Bit Mask Filter

Classic bit mask filtering can filter groups of Message IDs (Standard Filter Type SFT =10/Extended Filter Type EFT =10). This is done by masking single bits of a received Message ID. In this case SFID1/EFID1 element is used as Message ID filter, while SFID2/EFID2 element is used as filter mask. A 0 bit at the filter mask (SFID2/EFID2) will mask out the corresponding bit position of the configured Message ID filter (SFID1/EFID1) and the value of the received Message ID at that bit position is not relevant for acceptance filtering. Only those bits of the received Message ID where the corresponding mask bits are 1 are relevant for acceptance filtering. There are two interesting cases:

  • All mask bits are 1: a match occurs only when the received Message ID and the configured Message ID filter are identical.
  • All mask bits are 0: all Message IDs match.
Note
For example: if sfid1(message id) is 0xC0 and sfid2(mask) is 0xF then all the messages ranged from 0xC0 to 0xCF will be received. In case you want to receive all messages, sfid2(mask) need to be set to 0x0.

Filter Element Configuration

Up to 128 filter elements can be configured for 11-bit standard IDs and 64 filter elements can be configured for 29-bit extended IDs. Each filter element have 4 following parameters to be configured.

  • sfid1/efid1 : Defines the ID of the message to be stored
  • sfid2/efid2 : Defines the second ID.This field has a different meaning depending on sfec/efec. In case buffer is configured then sfid2/efid2 filters to Rx buffer number[0-63]
  • sfec/efec : Place to store message(Buffer/FIFO0/FIFO1)
  • sft/eft : Filter Types

Tx Buffer/FIFO Configuration

The MCAN module supports up to 32 Tx Buffers. These Tx Buffers can be configured as dedicated Tx Buffers, Tx FIFO and as combination of dedicated Tx Buffers/Tx FIFO. In the message RAM, FIFO is allocated only after the number of buffers allocated. i.e.

txFifoStartAddr = txBufStartAddr + txBufCnt;

Dedicated Tx Buffers are intended for message transmission under complete control of the Host CPU. There are two options:

  • Each dedicated Tx Buffer is configured with a specific Message ID.
  • Two or more dedicated Tx Buffers are configured with the same Message ID. In this case the Tx Buffer with the lowest buffer number is transmitted first.
Note
Please refer APIs for MCAN for more details and Example Usage for code snippets.

Important Usage Guidelines

Bit Rate Calculation

Formula for bit-rate is:

Sampling Point(%) = (1 + TSEG1) / (1 + TSEG1 + TSEG2)
TSEG1, TSEG2: Time Segments expressed in terms of number of Tq(Time Quantum)
Tq: the period of the CAN module functional clock.

CAN bus termination

CAN bus termination is needed to minimize the reflection, to reduce the noise. The transmission lines must be terminated to make sure noise does not cause communication failure.

There are two types of CAN termination:

  • Standard termination: The traditional 120 Ohm resistor(RL) is used on each end of the bus.
  • Split Termination Two 60 Ohm(RL/2) resistors along with capacitor(CL) is used to suppress the noise at both ends of the bus. Typical value of CL for 1.1 Mbps is 4.7 nF.

Please note RL and CL values are dependent on a signaling rate.

Transceiver Delay Compensation Value(TDCV)

CAN is a broadcast protocol, every node on the bus sees the message on the bus even if it is Tx node. Tx node uses this data on Rx line for integrity and error checks locally. Overview of a bit flow through different stages in communication is:

CAN module core -> CAN module Tx line -> SoC Tx Pin/PAD -> Transceiver Out -> CAN Bus -> Transceiver In -> SoC Rx Pin/PAD -> CAN module Rx line -> CAN module core

In the above path flow, introduces latency between data going out from Tx line to data coming in on Rx line. Major part of this latency comes from Transceiver. Hence it is called Transceiver Delay Compensation Value. This needs to programmed as controller has to adjust it's Secondary Sampling Point(SSP) for sampling Rx line at the correct time.

  • MCAN provides functionality to measure delay between transition on Tx line and same transition for Rx line. User need not to measure transceiver loop-back delay or refer transceiver documentation for the same. User just needs to program SSP position which could be same as Sampling Point(SP).

Things to consider/check before sending a message over CAN bus

Make sure following is done/checked before attempting communication on bus:

  • ISO-11898 compatible transceivers have to be connected to a CAN bus.
  • CAN bus should have proper termination.
  • CAN_L lines from nodes shall be connected together and same goes for CAN_H and GND lines as well.
  • Make sure all connections are firm and all pins properly connected.
  • All node on the bus are configured for same bit rate.
  • In case of CAN FD, make sure Transceiver Delay Compensation value is correctly programmed.
  • CAN module is powered up and configured properly.
  • SoC pins/PADs for CAN are configured properly.

Debug CAN communication failure

When any CAN message transmission/reception fails, controller updates LEC (Last Error Code) and DLEC (Data Phase Last Error Code) fields in status register('MCAN_PSR')

LEC: this field is updated when error happened in arbitration phase in case of CAN FD message or during full message for classic CAN message.

DLEC: this field is updated when error happened in data phase in case of CAN FD message.

LEC/DLEC fields have following errors:

  • Stuff Error
    • Node type: Rx
    • Description: More than 5 equal bits in a sequence have occurred in a part of a received message where this is not allowed.
    • Check if all the nodes on the bus have same bit-rate.
  • Form Error
    • Node type: Rx
    • Description: A fixed format part of a received frame has the wrong format.
    • This could happen if receiver node have drift in CAN functional clock momentarily or bus have interference.
  • Ack Error
    • Node Type: Tx
    • Description: The message transmitted by the MCAN module was not acknowledged by another node.
    • CAN bus should have more than one nodes(apart for transmitting node) up and running(not in sleep or power down state).
  • Bit1 Error and Bit0 Error
    • Node Type: Tx
    • Description:
      • Bit1 Error: During the transmission of a message (with the exception of the arbitration field), the device wanted to send a recessive level (bit of logical value 1), but the monitored bus value was dominant.
      • Bit0 Error: During the transmission of a message (acknowledge bit, active error flag, or overload flag), the device wanted to send a dominant level (data or identifier bit logical value 0), but the monitored bus value was recessive.
    • Tx and Rx lines are sampled at Sampling Point (SP) and Secondary Sampling Point (SSP) respectively have different values. Position of SSP is configurable.
    • This can happen in following cases:
      • Check if tx and rx pins are configured properly. These pins should be pulled high by default i.e. when bus is idle(no communication is going on).
      • Check if CAN transceiver is enabled.
      • For LEC:
        • If configured SP is too large for given node.
        • Segment after SP(TSEG2) should be large enough to compensate for Transceiver Delay.
      • For DLEC:
        • Configured Transceiver Delay Compensation value is less/more than required.
  • CRC Error
    • Node type: Rx
    • Description: The CRC check sum of a received message was incorrect. The CRC of an incoming message does not match with the CRC calculated from the received data.
    • This could happen if receiver node have drift in CAN functional clock momentarily or bus have interference.

Example Usage

Include the below file to access the APIs

#include <drivers/mcan.h>

MCAN Interrupt Registration

int32_t status = SystemP_SUCCESS;
HwiP_Params hwiPrms;
/* Register interrupt */
HwiP_Params_init(&hwiPrms);
hwiPrms.intNum = APP_MCAN_INTR_NUM;
hwiPrms.callback = &App_mcanIntrISR;
status = HwiP_construct(&gMcanHwiObject, &hwiPrms);

MCAN Message RAM Configuration

MCAN_initMsgRamConfigParams(msgRAMConfigParams);
/* Configure the user required msg ram params */
msgRAMConfigParams->lss = APP_MCAN_STD_ID_FILTER_CNT;
msgRAMConfigParams->lse = APP_MCAN_EXT_ID_FILTER_CNT;
msgRAMConfigParams->txBufCnt = APP_MCAN_TX_BUFF_CNT;
msgRAMConfigParams->txFIFOCnt = APP_MCAN_TX_FIFO_CNT;
/* Buffer/FIFO mode is selected */
msgRAMConfigParams->txBufMode = MCAN_TX_MEM_TYPE_BUF;
msgRAMConfigParams->txEventFIFOCnt = APP_MCAN_TX_EVENT_FIFO_CNT;
msgRAMConfigParams->rxFIFO0Cnt = APP_MCAN_FIFO_0_CNT;
msgRAMConfigParams->rxFIFO1Cnt = APP_MCAN_FIFO_1_CNT;
/* FIFO blocking mode is selected */
msgRAMConfigParams->rxFIFO0OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
msgRAMConfigParams->rxFIFO1OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
status = MCAN_calcMsgRamParamsStartAddr(msgRAMConfigParams);
DebugP_assert(status == CSL_PASS);

MCAN Rx Standard Filter Element Configuration

/* sfid1 defines the ID of the standard message to be stored. */
stdFiltElem->sfid1 = APP_MCAN_STD_ID;
/* As buffer mode is selected, sfid2 should be bufNum[0 - 63] */
stdFiltElem->sfid2 = bufNum;
/* Store message in buffer */
stdFiltElem->sfec = MCAN_STD_FILT_ELEM_BUFFER;
/* Below configuration is ignored if message is stored in buffer */
stdFiltElem->sft = MCAN_STD_FILT_TYPE_RANGE;

MCAN Tx Message Configuration

/* Initialize message to transmit */
/* Standard message identifier 11 bit, stored into ID[28-18] */
txMsg->id = ((APP_MCAN_STD_ID & MCAN_STD_ID_MASK) << MCAN_STD_ID_SHIFT);
txMsg->dlc = MCAN_DATA_SIZE_64BYTES; /* Payload size is 64 bytes */
txMsg->fdf = TRUE; /* CAN FD Frame Format */
txMsg->xtd = FALSE; /* Extended id not configured */
for (i = 0U; i < MCAN_MAX_PAYLOAD_BYTES; i++)
{
txMsg->data[i] = i;
}

MCAN Message Transmit/Receive

/* Configure Tx Msg to transmit */
App_mcanConfigTxMsg(&txMsg);
/* Select buffer number, 32 buffers available */
bufNum = 0U;
/* Enable Transmission interrupt for the selected buf num,
* If FIFO is used, then need to send FIFO start index until FIFO count */
status = MCAN_txBufTransIntrEnable(gMcanBaseAddr, bufNum, (uint32_t)TRUE);
DebugP_assert(status == CSL_PASS);
/* Write message to Msg RAM */
MCAN_writeMsgRam(gMcanBaseAddr, MCAN_MEM_TYPE_BUF, bufNum, &txMsg);
/* Add request for transmission, This function will trigger transmission */
status = MCAN_txBufAddReq(gMcanBaseAddr, bufNum);
DebugP_assert(status == CSL_PASS);
/* Wait for Tx completion */
MCAN_getProtocolStatus(gMcanBaseAddr, &protStatus);
/* Checking for Tx Errors */
if (((MCAN_ERR_CODE_NO_ERROR != protStatus.lastErrCode) ||
(MCAN_ERR_CODE_NO_CHANGE != protStatus.lastErrCode)) &&
((MCAN_ERR_CODE_NO_ERROR != protStatus.dlec) ||
(MCAN_ERR_CODE_NO_CHANGE != protStatus.dlec)) &&
(0U != protStatus.pxe))
{
DebugP_assert(FALSE);
}
/* Wait for Rx completion */
/* Checking for Rx Errors */
MCAN_getErrCounters(gMcanBaseAddr, &errCounter);
DebugP_assert((0U == errCounter.recErrCnt) &&
(0U == errCounter.canErrLogCnt));
/* Get the new data staus, indicates buffer num which received message */
MCAN_getNewDataStatus(gMcanBaseAddr, &newDataStatus);
MCAN_clearNewDataStatus(gMcanBaseAddr, &newDataStatus);
/* Select buffer and fifo number, Buffer is used in this app */
bufNum = 0U;
fifoNum = MCAN_RX_FIFO_NUM_0;
bitPos = (1U << bufNum);
if (bitPos == (newDataStatus.statusLow & bitPos))
{
MCAN_readMsgRam(gMcanBaseAddr, MCAN_MEM_TYPE_BUF, bufNum, fifoNum, &rxMsg);
}
else
{
DebugP_assert(FALSE);
}
/* Compare Tx/Rx data */
if (((txMsg.id >> APP_MCAN_STD_ID_SHIFT) & APP_MCAN_STD_ID_MASK) ==
((rxMsg.id >> APP_MCAN_STD_ID_SHIFT) & APP_MCAN_STD_ID_MASK))
{
for (i = 0U; i < MCAN_MAX_PAYLOAD_BYTES; i++)
{
if (txMsg.data[i] != rxMsg.data[i])
{
DebugP_logError("Data mismatch !!!\r\n");
DebugP_assert(FALSE);
}
}
}
else
{
DebugP_logError("Message ID mismatch !!!\r\n");
DebugP_assert(FALSE);
}

MCAN Interrupt Service Routine

intrStatus = MCAN_getIntrStatus(gMcanBaseAddr);
MCAN_clearIntrStatus(gMcanBaseAddr, intrStatus);
{
SemaphoreP_post(&gMcanTxDoneSem);
}
/* If FIFO0/FIFO1 is used, then MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG macro
* needs to be replaced by MCAN_INTR_SRC_RX_FIFO0_NEW_MSG/
* MCAN_INTR_SRC_RX_FIFO1_NEW_MSG respectively */
{
SemaphoreP_post(&gMcanRxDoneSem);
}

MCAN Interrupt De-Registration

HwiP_destruct(&gMcanHwiObject);

API

APIs for MCAN

MCAN_ERR_CODE_NO_CHANGE
#define MCAN_ERR_CODE_NO_CHANGE
Definition: mcan/v0/mcan.h:605
MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG
#define MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG
Definition: mcan/v0/mcan.h:477
MCAN_STD_FILT_TYPE_RANGE
#define MCAN_STD_FILT_TYPE_RANGE
Macros to represent Standard Filter Types.
Definition: mcan/v0/mcan.h:230
MCAN_RX_FIFO_OPERATION_MODE_BLOCKING
#define MCAN_RX_FIFO_OPERATION_MODE_BLOCKING
Macros to represent the MCAN RX FIFO mode of operation.
Definition: mcan/v0/mcan.h:133
HwiP_destruct
void HwiP_destruct(HwiP_Object *obj)
Cleanup, delete, destruct a Hwi object.
HwiP_Params
Parameters passed during HwiP_construct.
Definition: HwiP.h:72
MCAN_INTR_SRC_TRANS_COMPLETE
#define MCAN_INTR_SRC_TRANS_COMPLETE
Definition: mcan/v0/mcan.h:457
MCAN_TX_MEM_TYPE_BUF
#define MCAN_TX_MEM_TYPE_BUF
Macros to represent the MCAN Tx Message RAM type.
Definition: mcan/v0/mcan.h:147
SystemP_WAIT_FOREVER
#define SystemP_WAIT_FOREVER
Value to use when needing a timeout of infinity or wait forver until resource is available.
Definition: SystemP.h:83
MCAN_initMsgRamConfigParams
void MCAN_initMsgRamConfigParams(MCAN_MsgRAMConfigParams *msgRAMConfigParams)
This API will initialize MCAN message config RAM params to default.
HwiP_construct
int32_t HwiP_construct(HwiP_Object *obj, HwiP_Params *params)
Create a Hwi object.
MCAN_ERR_CODE_NO_ERROR
#define MCAN_ERR_CODE_NO_ERROR
Definition: mcan/v0/mcan.h:570
MCAN_calcMsgRamParamsStartAddr
int32_t MCAN_calcMsgRamParamsStartAddr(MCAN_MsgRAMConfigParams *msgRAMConfigParams)
This API will calculate start addresses of message RAM params.
MCAN_MEM_TYPE_BUF
#define MCAN_MEM_TYPE_BUF
Definition: mcan/v0/mcan.h:343
MCAN_getErrCounters
void MCAN_getErrCounters(uint32_t baseAddr, MCAN_ErrCntStatus *errCounter)
This API will return error counter status for MCAN module.
MCAN_DATA_SIZE_64BYTES
#define MCAN_DATA_SIZE_64BYTES
Definition: mcan/v0/mcan.h:191
HwiP_Params_init
void HwiP_Params_init(HwiP_Params *params)
Set default values to HwiP_Params.
MCAN_clearNewDataStatus
void MCAN_clearNewDataStatus(uint32_t baseAddr, const MCAN_RxNewDataStatus *newDataStatus)
This API clear New Data Message Status.
MCAN_clearIntrStatus
void MCAN_clearIntrStatus(uint32_t baseAddr, uint32_t intrMask)
This API is used to clear the interrupt status.
MCAN_writeMsgRam
void MCAN_writeMsgRam(uint32_t baseAddr, uint32_t memType, uint32_t bufNum, const MCAN_TxBufElement *elem)
This API is used to write Tx message to message RAM.
DebugP_logError
#define DebugP_logError(format,...)
Function to log a string to the enabled console, for error zone.
Definition: DebugP.h:223
SystemP_SUCCESS
#define SystemP_SUCCESS
Return status when the API execution was successful.
Definition: SystemP.h:56
MCAN_getNewDataStatus
void MCAN_getNewDataStatus(uint32_t baseAddr, MCAN_RxNewDataStatus *newDataStatus)
This API will return New Data Message Status.
MCAN_readMsgRam
void MCAN_readMsgRam(uint32_t baseAddr, uint32_t memType, uint32_t bufNum, uint32_t fifoNum, MCAN_RxBufElement *elem)
This API is used to read received message form message RAM.
MCAN_getProtocolStatus
void MCAN_getProtocolStatus(uint32_t baseAddr, MCAN_ProtocolStatus *protStatus)
This API will return protocol status for MCAN module.
MCAN_MAX_PAYLOAD_BYTES
#define MCAN_MAX_PAYLOAD_BYTES
Maximum payload supported by CAN-FD protocol in bytes.
Definition: mcan/v0/mcan.h:106
HwiP_Params::callback
HwiP_FxnCallback callback
Definition: HwiP.h:75
SemaphoreP_post
void SemaphoreP_post(SemaphoreP_Object *obj)
Post a semaphore object or unlock a mutex.
MCAN_getIntrStatus
uint32_t MCAN_getIntrStatus(uint32_t baseAddr)
This API will return interrupt status.
DebugP_assert
#define DebugP_assert(expression)
Function to call for assert check.
Definition: DebugP.h:159
HwiP_Params::intNum
uint32_t intNum
Definition: HwiP.h:74
mcan.h
MCAN_STD_FILT_ELEM_BUFFER
#define MCAN_STD_FILT_ELEM_BUFFER
Definition: mcan/v0/mcan.h:217
MCAN_RX_FIFO_NUM_0
#define MCAN_RX_FIFO_NUM_0
Definition: mcan/v0/mcan.h:359
MCAN_txBufAddReq
int32_t MCAN_txBufAddReq(uint32_t baseAddr, uint32_t bufNum)
This API will set Tx Buffer Add Request.
MCAN_txBufTransIntrEnable
int32_t MCAN_txBufTransIntrEnable(uint32_t baseAddr, uint32_t bufNum, uint32_t enable)
This API is used to enable/disable Tx Buffer Transmission Interrupt.
SemaphoreP_pend
int32_t SemaphoreP_pend(SemaphoreP_Object *obj, uint32_t timeToWaitInTicks)
Pend on a semaphore object or lock a mutex.
MCAN_initTxBufElement
void MCAN_initTxBufElement(MCAN_TxBufElement *txMsg)
This API will initialize TX message object with default values.