iLLD_TC27xC  1.0
How to use the CAN Interface driver?
Collaboration diagram for How to use the CAN Interface driver?:

The CAN interface driver provides a default configuration for various modes.

In the following sections it will be described, how to integrate the driver into the application framework.

Preparation

Include Files

Include following header file into your C code:

Variables

Declare the CAN handles as global variables in your C code:

// CAN handle
// Two Nodes (for external loopback demo)
// Two Message objects (for external loopback demo)

Module Initialisation

The module initialisation can be done as followed:

// create configuration
IfxMultican_Can_initModuleConfig(&canConfig, &MODULE_CAN);
// initialize module
// IfxMultican_Can can; // defined globally
IfxMultican_Can_initModule(&can, &canConfig);

Node Initialisation

The Can nodes initialisation can be done as followed:

// create CAN node config
IfxMultican_Can_Node_initConfig(&canNodeConfig, &can);
canNodeConfig.baudrate = 1000000; // 1 MBaud
// Source Node
// IfxMultican_Can_Node canSrcNode; // defined globally
{
canNodeConfig.nodeId = IfxMultican_NodeId_0;
// initialise the node
IfxMultican_Can_Node_init(&canSrcNode, &canNodeConfig);
}
// Destination Node
// IfxMultican_Can_Node canDstNode; // defined globally
{
canNodeConfig.nodeId = IfxMultican_NodeId_1;
// initialise the node
IfxMultican_Can_Node_init(&canDstNode, &canNodeConfig);
}

Message Object Initialisation

The Can message objects initialisation can be done as followed:

const unsigned id = 0x100 ;
// IfxMultican_Can_MsgObj canSrcMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canSrcNode);
// assigned message object:
canMsgObjConfig.msgObjId = 0;
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_transmit;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canSrcMsgObj, &canMsgObjConfig);
}
// IfxMultican_Can_MsgObj canDstMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canDstNode);
// assigned message object:
canMsgObjConfig.msgObjId = 1;
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_receive;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canDstMsgObj, &canMsgObjConfig);
}

The MULTICAN is ready for use now!

Single Data Transfers

The CAN driver provides simple to use transfer functions

Data can be sent by the following way:

const unsigned dataLow = 0x12345678;
const unsigned dataLow = 0x9abcdef0;
// Initialise the message strcture
// Transmit Data

Data can be received by the following way:

// Receiving Data
// Initialise the message structure with dummy values, will be replaced by the received values
IfxMultican_Message_init(&msg, 0xdead, 0xdeadbeef, 0xdeadbeef, IfxMultican_DataLengthCode_8); // start with invalid values
// wait until Multican received a new message
while( !IfxMultican_Can_MsgObj_isRxPending(&canDstMsgObj) );
// read message
IfxMultican_Status readStatus = IfxMultican_Can_MsgObj_readMessage(&canDstMsgObj, &msg);
if( readStatus != IfxMultican_Status_noError ) {
clib_ver_printf("ERROR: IfxMultican_Can_MsgObj_readMessage returned 0x%04x\n", readStatus);
result |= 1;
}
// data now available at msg.data[0] and msg.data[1]

FIFO based Transfers

A transmit and receive FIFO can be enabled during the node configuration by specifing the number of allocated message objects with the canMsgObjConfig.msgObjCount item. and specifying the message object number of first slave object with the canMsgObjConfig.firstSlaveObjId item.

Message objects will be allocated to the FIFO in ascending order.

Here a configuration example:

#define RX_FIFO_SIZE 16
#define TX_FIFO_SIZE 8
const unsigned id = 0x100 ;
// IfxMultican_Can_MsgObj canSrcMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canSrcNode);
// FIFO MsgObj allocation:
canMsgObjConfig.msgObjId = 0; // will allocate MsgObj 0
canMsgObjConfig.msgObjCount = TX_FIFO_SIZE;
canMsgObjConfig.firstSlaveObjId = 1; // will allocate MsgObj 1..8 for the FIFO
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_transmit;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canSrcMsgObj, &canMsgObjConfig);
}
// IfxMultican_Can_MsgObj canDstMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canDstNode);
// FIFO MsgObj allocation:
canMsgObjConfig.msgObjId = 9; // because the Tx FIFO allocated MsgObj 0..8
canMsgObjConfig.msgObjCount = RX_FIFO_SIZE;
canMsgObjConfig.firstSlaveObjId = 10; // will allocate MsgObj 10..25
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_receive;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canDstMsgObj, &canMsgObjConfig);
}

Data can now be sent and received with the IfxMultican_Can_MsgObj_sendMessage and IfxMultican_Can_MsgObj_readMessage functions as usual (see above).

CAN FD Data Transfers

The CAN driver provides simple to use FD transfer functions

Node configuration:

// create CAN node config
IfxMultican_Can_Node_initConfig(&canNodeConfig, &can);
canNodeConfig.baudrate = 1000000; // 1 MBaud
// Source Node
// IfxMultican_Can_Node canSrcNode; // defined globally
{
canNodeConfig.nodeId = IfxMultican_NodeId_0;
// choose CAN FD transfer enable or disable //
canNodeConfig.flexibleDataRate = TRUE;
// if CAN FD enabled choose the FD configuration //
canNodeConfig.fdConfig.nominalBaudrate = 500000;
canNodeConfig.fdConfig.nominalSynchJumpWidth = 8000;
canNodeConfig.fdConfig.nominalSamplePoint = 2000;
canNodeConfig.fdConfig.fastBaudrate = 1000000;
canNodeConfig.fdConfig.fastSynchJumpWidth = 8000;
canNodeConfig.fdConfig.fastSamplePoint = 2000;
canNodeConfig.fdConfig.loopDelayOffset = 0;
// initialise the node
IfxMultican_Can_Node_init(&canSrcNode, &canNodeConfig);
}
// Destination Node
// IfxMultican_Can_Node canDstNode; // defined globally
{
canNodeConfig.nodeId = IfxMultican_NodeId_1;
// choose CAN FD transfer enable or disable //
config->flexibleDataRate = TRUE;
// if CAN FD enabled choose the FD configuration //
canNodeConfig.fdConfig.nominalBaudrate = 500000;
canNodeConfig.fdConfig.nominalSynchJumpWidth = 8000;
canNodeConfig.fdConfig.nominalSamplePoint = 2000;
canNodeConfig.fdConfig.fastBaudrate = 1000000;
canNodeConfig.fdConfig.fastSynchJumpWidth = 8000;
canNodeConfig.fdConfig.fastSamplePoint = 2000;
canNodeConfig.fdConfig.loopDelayOffset = 0;
// initialise the node
IfxMultican_Can_Node_init(&canDstNode, &canNodeConfig);
}

The CAN FD message objects initialisation can be done as followed:

const unsigned id = 0x100 ;
// IfxMultican_Can_MsgObj canSrcMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canSrcNode);
// assigned message object:
canMsgObjConfig.msgObjId = 0;
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_transmit;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
canMsgObjConfig.control.topMsgObjId = 252;
canMsgObjConfig.control.bottomMsgObjId = 253;
canMsgObjConfig.control.fastBitRate = TRUE; // fast bit rate enable/disable
// initialize message object
IfxMultican_Can_MsgObj_init(&canSrcMsgObj, &canMsgObjConfig);
}
// IfxMultican_Can_MsgObj canDstMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canDstNode);
// assigned message object:
canMsgObjConfig.msgObjId = 1;
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_receive;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
canMsgObjConfig.control.topMsgObjId = 250;
canMsgObjConfig.control.bottomMsgObjId = 251;
canMsgObjConfig.control.fastBitRate = TRUE; // fast bit rate enable/disable
// initialize message object
IfxMultican_Can_MsgObj_init(&canDstMsgObj, &canMsgObjConfig);
}

In case of standard messages data can be sent and received with the IfxMultican_Can_MsgObj_sendMessage and IfxMultican_Can_MsgObj_readMessage functions as usual (see above).

In case of long frames of length more than 8 bytes the data can be sent by the following way

// load txData buffer with the data that needs to be send
// txData is assumed to be declared globally
int i;
for (i = 0; i < 16; ++i)
{
txData[i] = (0x11110000 + i);
}
// Initialise the message strcture
// Transmit Data
while( IfxMultican_Can_MsgObj_sendlongFrame(&canSrcMsgObj, &msg, &txData) == IfxMultican_Status_notSentBusy );

You can recieve the data by the following way

// Receiving Data
// Initialise the message strcture with dummy values, will be replaced by the received values
IfxMultican_Message_longFrameInit(&msg, 0xdead, IfxMultican_DataLengthCode_64, FALSE); // start with invalid values
// wait until Multican received a new message
while( !IfxMultican_Can_MsgObj_isRxPending(&canDstMsgObj) );
// read the message
//rxData is assumed to be declared globally
IfxMultican_Status readStatus = IfxMultican_Can_MsgObj_readLongFrame(&canDstMsgObj, &msg, &rxData);
if( readStatus != IfxMultican_Status_noError ) {
clib_ver_printf("ERROR: IfxMultican_Can_MsgObj_readMessage returned 0x%04x\n", readStatus);
result |= 1;
}
// clear pending flag

Gateway Transfers

A Gateway source object can be enabled during the message object configuration by specifing with the canMsgObjConfig.gatewayTransfersEnable item.

Here a configuration example:

// source message object
// IfxMultican_Can_MsgObj canSrcMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canSrcNode);
canMsgObjConfig.msgObjId = 0;
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_transmit;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
canMsgObjConfig.gatewayTransfers = FALSE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canSrcMsgObj, &canMsgObjConfig);
}
// gateway source message object //
// data will be received into this object from SrcObj, and then copied into gateway destination object //
IfxMultican_Can_MsgObj canGatewaySrcMsgObj;
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canDstNode);
canMsgObjConfig.msgObjId = 1;
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_receive;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
canMsgObjConfig.gatewayTransfers = TRUE;
canMsgObjConfig.gatewayConfig.copyData = TRUE;
canMsgObjConfig.gatewayConfig.copyId = FALSE;
canMsgObjConfig.gatewayConfig.enableTransmit = TRUE; // if this is not choosen, then no need to initialise canDstMsgObj to read the final data
canMsgObjConfig.gatewayConfig.gatewayDstObjId = 3; // specify the destination object number
// initialize message object
IfxMultican_Can_MsgObj_init(&canGatewaySrcMsgObj, &canMsgObjConfig);
}
// gateway destination object //
// data, id , datlength code will be copied from GatewaySrcObj into this object through gateway transfers //
// and then sent onto the bus for sending the message to destination message object //
IfxMultican_Can_MsgObj canGatewayDstMsgObj;
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canSrcNode);
canMsgObjConfig.msgObjId = 3;
canMsgObjConfig.messageId = 0x200;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_transmit;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
canMsgObjConfig.gatewayTransfers = FALSE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canGatewayDstMsgObj, &canMsgObjConfig);
}
// destination message object, not needed if enableTransmit is not chosen in gateway source object, or you don't want to read the data//
// data will be received from GatewayDstObj into this obj //
// IfxMultican_Can_MsgObj canDstMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canDstNode);
canMsgObjConfig.msgObjId = 10;
canMsgObjConfig.messageId = 0x200;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_receive;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = FALSE;
canMsgObjConfig.gatewayTransfers = FALSE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canDstMsgObj, &canMsgObjConfig);
}

Data can now be sent and received with the IfxMultican_Can_MsgObj_sendMessage and IfxMultican_Can_MsgObj_readMessage functions as usual (see above).

The data flow is as followed,

Data will be sent from the source object (canSrcMsgObj), it will be received by the gateway source object (canGatewaySrcMsgObj). and then gets copied into the gateway destination object (canGatewayDstMsgObj) without CPU intervention,

If GDFS is selected in gateway source object (canGatewaySrcMsgObj)then, the data will be transmitted from gateway destination object(canGatewayDstMsgObj) to the destination object (canDstMsgObj)

Gateway FIFO based Transfers

A gateway source FIFO can be enabled during the node configuration by specifing the number of allocated message objects with the canMsgObjConfig.msgObjCount item. and anbling the gateway transfers with the canMsgObjConfig.gatewayTransfersEnable item. and also by selecting the start object of the FIFO with the canMsgObjConfig.firstSlaveObjId item.

Message objects will be allocated to the gateway FIFO in ascending order. Here a configuration example:

// source message object, you can even make it as a Tx FIFO
// IfxMultican_Can_MsgObj canSrcMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canSrcNode);
canMsgObjConfig.msgObjId = 0;
canMsgObjConfig.messageId = id;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_transmit;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
canMsgObjConfig.gatewayTransfers = FALSE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canSrcMsgObj, &canMsgObjConfig);
}
// gateway source Fifo //
// data will be received into this object from SrcObj, and then copied into gateway Fifo objects //
IfxMultican_Can_MsgObj canGatewaySrcMsgObj;
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canDstNode);
canMsgObjConfig.msgObjId = 1;
canMsgObjConfig.messageId = id;
canMsgObjConfig.msgObjCount = 4; // FIFO
canMsgObjConfig.firstSlaveObjId = 2; // will allocate MsgObj 2..5 for the gateway FIFO
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_receive;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
canMsgObjConfig.gatewayTransfers = TRUE; // gateway FIFO
canMsgObjConfig.gatewayConfig.copyData = TRUE;
canMsgObjConfig.gatewayConfig.copyId = FALSE;
canMsgObjConfig.gatewayConfig.enableTransmit = TRUE; // if this is not choosen, then no need to initialise canDstMsgObj to read the final data
// initialize message object
IfxMultican_Can_MsgObj_init(&canGatewaySrcMsgObj, &canMsgObjConfig);
}
int i = 0;
for (i = 0; i < 4 ; ++i)
{
// gateway destination objects //
// data, id , datlength code will be copied from GatewaySrcObj into this object through gateway transfers //
// and then sent onto the bus for sending the message to destination receive Fifo message objects //
IfxMultican_Can_MsgObj canGatewayDstMsgObj;
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canSrcNode);
canMsgObjConfig.msgObjId = 2 + i;
canMsgObjConfig.messageId = 0x200;
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_transmit;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = TRUE;
canMsgObjConfig.gatewayTransfers = FALSE;
// initialize message object
IfxMultican_Can_MsgObj_init(&canGatewayDstMsgObj, &canMsgObjConfig);
}
}
// destination receive Fifo, not needed if enableTransmit is not chosen in gateway source object, or you don't want to read the data //
// data will be received from GatewayDstObj into this Fifo //
// IfxMultican_Can_MsgObj canDstMsgObj; // defined globally
{
// create message object config
IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &canDstNode);
canMsgObjConfig.msgObjId = 10;
canMsgObjConfig.messageId = 0x200;
canMsgObjConfig.msgObjCount = 4; // receive FIFO
canMsgObjConfig.firstSlaveObjId = 11; // will allocate MsgObj 11..14 for the receive FIFO
canMsgObjConfig.acceptanceMask = 0x7FFFFFFFUL;
canMsgObjConfig.frame = IfxMultican_Frame_receive;
canMsgObjConfig.control.extendedFrame = FALSE;
canMsgObjConfig.control.matchingId = FALSE;
canMsgObjConfig.gatewayTransfers = FALSE;
canMsgObjConfig.firstSlaveObjId = 11;
// initialize message object
IfxMultican_Can_MsgObj_init(&canDstMsgObj, &canMsgObjConfig);
}

Data can now be sent and received with the IfxMultican_Can_MsgObj_sendMessage and IfxMultican_Can_MsgObj_readMessage functions as usual (see above). here is an example

for (i = 0; i < 4; ++i)
{
// Transmit Data from the source message object //
IfxMultican_Message_init(&msg, id, dataLow + i, dataHigh + i, IfxMultican_DataLengthCode_8);
}

The data flow is as followed,

data will be sent from the source object (canSrcMsgObj) or source TX FIFO, it will be received by the gateway source FIFO (canGatewaySrcMsgObj). and then gets copied into the gateway destination objects (canGatewayDstMsgObj) without CPU intervention,

If GDFS is selected in gateway source object (FIFO) (canGatewaySrcMsgObj)then, the data will be transmitted from gateway destination objects (canGatewayDstMsgObj) to the destination objects or receive FIFO (canDstMsgObj)

if you want to read the data you read by the following way

for (i = 0; i < 4; ++i)
{
// Receiving Data, read the data from the destination receive Fifo //
// wait until MCAN received the frame
// wait until Multican received a new message
while( !IfxMultican_Can_MsgObj_isRxPending(&canDstMsgObj) );
IfxMultican_Message_init(&msg1, 0xdead, 0xdeadbeef, 0xdeadbeef, IfxMultican_DataLengthCode_8); // start with invalid values
IfxMultican_Status readStatus = IfxMultican_Can_MsgObj_readMessage(&canDstMsgObj, &msg1);
if( readStatus != IfxMultican_Status_noError ) {
clib_ver_printf("ERROR: IfxMultican_Can_MsgObj_readMessage returned 0x%04x\n", readStatus);
result |= 1;
}
// check the received data
result |= clib_trace(msg1.data[0], dataLow);
result |= clib_trace(msg1.data[1], dataHigh);
}