1.29.3 Control Area Network (CAN)

The Controller Area Network (CAN) performs communication according to ISO 11898-1:2015 and to Bosch CAN-FD specification. Additional transceiver hardware is required for connection to the physical layer.

All functions concerning the handling of messages are implemented by the Rx Handler and the Tx Handler. The Rx Handler manages message acceptance filtering, the transfer of received messages from the CAN core to the Message RAM, as well as providing receive message status information. The Tx Handler is responsible for the transfer of transmit messages from the Message RAM to the CAN core, as well as providing transmit status information. Acceptance filtering is implemented by a combination of up to 128 filter elements, where each element can be configured as a range, as a bit mask, or as a dedicated ID filter.

Using The Library

The CAN library supports the Normal and CAN-FD modes. The CAN Normal or CAN-FD mode can transfer message in a polling or an interrupt mode.

CAN Message RAM Configuration

Allocate CAN Message RAM Configuration in contiguous non-cacheable buffer as uint8_t Can1MessageRAM"CAN1_MESSAGE_RAM_CONFIG_SIZE" attribute((aligned (32))), here additional attribute such as attribute((section(".region_nocache"))) or attribute((space(data), section (".ram_nocache"))) should be added if cache is enabled and non-cacheable section should be created in linker script.

CAN polling mode:

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "definitions.h"                // SYS function prototypes

uint8_t Can1MessageRAM[CAN1_MESSAGE_RAM_CONFIG_SIZE] __attribute__((aligned (32)));

/* Standard identifier id[28:18]*/
#define WRITE_ID(id) (id << 18)
#define READ_ID(id)  (id >> 18)

static uint32_t status = 0;
static uint8_t loop_count = 0;
static uint8_t user_input = 0;

static uint8_t txFiFo[CAN1_TX_FIFO_BUFFER_SIZE];
static uint8_t rxFiFo0[CAN1_RX_FIFO0_SIZE];
static uint8_t rxFiFo1[CAN1_RX_FIFO1_SIZE];
static uint8_t rxBuffer[CAN1_RX_BUFFER_SIZE];

// *****************************************************************************
// *****************************************************************************
// Section: Local functions
// *****************************************************************************
// *****************************************************************************

/* Message Length to Data length code */
static uint8_t CANLengthToDlcGet(uint8_t length)
{
    uint8_t dlc = 0;

    if (length <= 8U)
    {
        dlc = length;
    }
    else if (length <= 12U)
    {
        dlc = 0x9U;
    }
    else if (length <= 16U)
    {
        dlc = 0xAU;
    }
    else if (length <= 20U)
    {
        dlc = 0xBU;
    }
    else if (length <= 24U)
    {
        dlc = 0xCU;
    }
    else if (length <= 32U)
    {
        dlc = 0xDU;
    }
    else if (length <= 48U)
    {
        dlc = 0xEU;
    }
    else
    {
        dlc = 0xFU;
    }
    return dlc;
}

/* Data length code to Message Length */
static uint8_t CANDlcToLengthGet(uint8_t dlc)
{
    uint8_t msgLength[] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U};
    return msgLength[dlc];
}

/* Menu */
static void display_menu(void)
{
	printf("Menu :\r\n"
	       "  -- Select the action:\r\n"
	       "  0: Send FD standard message with ID: 0x45A and 64 byte data 0 to 63. \r\n"
	       "  1: Send FD standard message with ID: 0x469 and 64 byte data 128 to 191. \r\n"
	       "  2: Send FD extended message with ID: 0x100000A5 and 64 byte data 0 to 63. \r\n"
	       "  3: Send FD extended message with ID: 0x10000096 and 64 byte data 128 to 191. \r\n"
	       "  4: Send normal standard message with ID: 0x469 and 8 byte data 0 to 7. \r\n"
	       "  m: Display menu \r\n\r\n");
}

/* Print Rx Message */
static void print_message(uint8_t numberOfMessage, CAN_RX_BUFFER *rxBuf, uint8_t rxBufLen, uint8_t rxFifoBuf)
{
    uint8_t length = 0;
    uint8_t msgLength = 0;
    uint32_t id = 0;

    if (rxFifoBuf == 0)
        printf(" Rx FIFO0 :");
    else if (rxFifoBuf == 1)
        printf(" Rx FIFO1 :");
    else if (rxFifoBuf == 2)
        printf(" Rx Buffer :");

    for (uint8_t count = 0; count < numberOfMessage; count++)
    {
        /* Print message to Console */
        printf(" New Message Received\r\n");
        id = rxBuf->xtd ? rxBuf->id : READ_ID(rxBuf->id);
        msgLength = CANDlcToLengthGet(rxBuf->dlc);
        length = msgLength;
        printf(" Message - ID : 0x%x Length : 0x%x ", (unsigned int)id, (unsigned int)msgLength);
        printf("Message : ");
        while(length)
        {
            printf("0x%x ", rxBuf->data[msgLength - length--]);
        }
        printf("\r\n");
        rxBuf += rxBufLen;
    }
}

// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    CAN_TX_BUFFER *txBuffer = NULL;
    uint8_t        bufferNumber = 0;
    uint8_t        numberOfMessage = 0;

    /* Initialize all modules */
    SYS_Initialize ( NULL );

    printf(" ------------------------------ \r\n");
    printf("            CAN FD Demo          \r\n");
    printf(" ------------------------------ \r\n");
    
    /* Set Message RAM Configuration */
    CAN1_MessageRAMConfigSet(Can1MessageRAM);

    display_menu();
     
    while ( true )
    {
        /* Rx Buffers */
        if (CAN1_InterruptGet(CAN_INTERRUPT_DRX_MASK))
        {    
            CAN1_InterruptClear(CAN_INTERRUPT_DRX_MASK);

            /* Check CAN Status */
            status = CAN1_ErrorGet();

            if (((status & CAN_PSR_LEC_Msk) == CAN_ERROR_NONE) || ((status & CAN_PSR_LEC_Msk) == CAN_ERROR_LEC_NC))
            {
                if (CAN1_RxBufferNumberGet(&bufferNumber))
                {
                    memset(rxBuffer, 0x00, CAN1_RX_BUFFER_ELEMENT_SIZE);
                    if (CAN1_MessageReceive(bufferNumber, (CAN_RX_BUFFER *)rxBuffer) == true)
                    {
                        print_message(1, (CAN_RX_BUFFER *)rxBuffer, CAN1_RX_BUFFER_ELEMENT_SIZE, 2);
                    }
                    else
                    {
                        printf(" Error in received message\r\n");
                    }
                }
            }
            else
            {
                printf(" Error in received message\r\n");
            }
        }

        /* Rx FIFO0 */
        if (CAN1_InterruptGet(CAN_INTERRUPT_RF0N_MASK))
        {    
            CAN1_InterruptClear(CAN_INTERRUPT_RF0N_MASK);

            /* Check CAN Status */
            status = CAN1_ErrorGet();

            if (((status & CAN_PSR_LEC_Msk) == CAN_ERROR_NONE) || ((status & CAN_PSR_LEC_Msk) == CAN_ERROR_LEC_NC))
            {
                numberOfMessage = CAN1_RxFifoFillLevelGet(CAN_RX_FIFO_0);
                if (numberOfMessage != 0)
                {
                    memset(rxFiFo0, 0x00, (numberOfMessage * CAN1_RX_FIFO0_ELEMENT_SIZE));
                    if (CAN1_MessageReceiveFifo(CAN_RX_FIFO_0, numberOfMessage, (CAN_RX_BUFFER *)rxFiFo0) == true)
                    {
                        print_message(numberOfMessage, (CAN_RX_BUFFER *)rxFiFo0, CAN1_RX_FIFO0_ELEMENT_SIZE, 0);
                    }
                    else
                    {
                        printf(" Error in received message\r\n");
                    }
                }
            }
            else
            {
                printf(" Error in received message\r\n");
            }
        }

        /* Rx FIFO1 */
        if (CAN1_InterruptGet(CAN_INTERRUPT_RF1N_MASK))
        {    
            CAN1_InterruptClear(CAN_INTERRUPT_RF1N_MASK);

            /* Check CAN Status */
            status = CAN1_ErrorGet();

            if (((status & CAN_PSR_LEC_Msk) == CAN_ERROR_NONE) || ((status & CAN_PSR_LEC_Msk) == CAN_ERROR_LEC_NC))
            {
                numberOfMessage = CAN1_RxFifoFillLevelGet(CAN_RX_FIFO_1);
                if (numberOfMessage != 0)
                {
                    memset(rxFiFo1, 0x00, (numberOfMessage * CAN1_RX_FIFO1_ELEMENT_SIZE));
                    if (CAN1_MessageReceiveFifo(CAN_RX_FIFO_1, numberOfMessage, (CAN_RX_BUFFER *)rxFiFo1) == true)
                    {
                        print_message(numberOfMessage, (CAN_RX_BUFFER *)rxFiFo1, CAN1_RX_FIFO1_ELEMENT_SIZE, 1);
                    }
                    else
                    {
                        printf(" Error in received message\r\n");
                    }
                }
            }
            else
            {
                printf(" Error in received message\r\n");
            }
        }

        /* User input */
        if (SERCOM4_USART_ReceiverIsReady() == false)
        {
            continue;
        }
        user_input = (uint8_t)SERCOM4_USART_ReadByte();

        switch (user_input)
        {
            case '0':
                memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                txBuffer = (CAN_TX_BUFFER *)txFiFo;
                txBuffer->id = WRITE_ID(0x45A);
                txBuffer->dlc = CANLengthToDlcGet(64);
                txBuffer->fdf = 1;
                txBuffer->brs = 1;
                for (loop_count = 0; loop_count < 64; loop_count++){
                    txBuffer->data[loop_count] = loop_count;
                }                
                printf("  0: Send FD standard message with ID: 0x45A and 64 byte data 0 to 63.\r\n");
                if (CAN1_MessageTransmitFifo(1, txBuffer) == true)
                {    
                    printf(" Success \r\n");
                }
                else
                {
                    printf(" Failed \r\n");
                }             
                break;  
            case '1':
                memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                txBuffer = (CAN_TX_BUFFER *)txFiFo;
                txBuffer->id = WRITE_ID(0x469);
                txBuffer->dlc = CANLengthToDlcGet(64);
                txBuffer->fdf = 1;
                txBuffer->brs = 1;
                for (loop_count = 128; loop_count < 192; loop_count++){
                    txBuffer->data[loop_count - 128] = loop_count;
                }                
                printf("  1: Send FD standard message with ID: 0x469 and 64 byte data 128 to 191.\r\n");
                if (CAN1_MessageTransmitFifo(1, txBuffer) == true)
                {    
                    printf(" Success \r\n");
                }
                else
                {
                    printf(" Failed \r\n");
                }    
                break;
            case '2': 
                memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                txBuffer = (CAN_TX_BUFFER *)txFiFo;
                txBuffer->id = 0x100000A5;
                txBuffer->dlc = CANLengthToDlcGet(64);
                txBuffer->xtd = 1;
                txBuffer->fdf = 1;
                txBuffer->brs = 1;
                for (loop_count = 0; loop_count < 64; loop_count++){
                    txBuffer->data[loop_count] = loop_count;
                }
                printf("  2: Send FD extended message with ID: 0x100000A5 and 64 byte data 0 to 63.\r\n");
                if (CAN1_MessageTransmitFifo(1, txBuffer) == true)
                {    
                    printf(" Success \r\n");
                }
                else
                {
                    printf(" Failed \r\n");
                }             
                break;
            case '3':
                memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                txBuffer = (CAN_TX_BUFFER *)txFiFo;
                txBuffer->id = 0x10000096;
                txBuffer->dlc = CANLengthToDlcGet(64);
                txBuffer->xtd = 1;
                txBuffer->fdf = 1;
                txBuffer->brs = 1;
                for (loop_count = 128; loop_count < 192; loop_count++){
                    txBuffer->data[loop_count - 128] = loop_count;
                }
                printf("  3: Send FD extended message with ID: 0x10000096 and 64 byte data 128 to 191.\r\n");
                if (CAN1_MessageTransmitFifo(1, txBuffer) == true)
                {    
                    printf(" Success \r\n");
                }
                else
                {
                    printf(" Failed \r\n");
                }             
                break;
            
            case '4':
                memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                txBuffer = (CAN_TX_BUFFER *)txFiFo;
                txBuffer->id = WRITE_ID(0x469);
                txBuffer->dlc = 8;
                for (loop_count = 0; loop_count < 8; loop_count++){
                    txBuffer->data[loop_count] = loop_count;
                }                
                printf("  4: Send normal standard message with ID: 0x469 and 8 byte data 0 to 7.\r\n");
                if (CAN1_MessageTransmitFifo(1, txBuffer) == true)
                {    
                    printf(" Success \r\n");
                }
                else
                {
                    printf(" Failed \r\n");
                }             
                break;                 

            case 'm':
            case 'M':
                display_menu();
                break;
                
            default:
                printf(" Invalid Input \r\n");
                break;
        }  
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

CAN interrupt mode:

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "definitions.h"                // SYS function prototypes

uint8_t Can1MessageRAM[CAN1_MESSAGE_RAM_CONFIG_SIZE] __attribute__((aligned (32)));

/* Standard identifier id[28:18]*/
#define WRITE_ID(id) (id << 18)
#define READ_ID(id)  (id >> 18)

/* Application's state machine enum */
typedef enum
{
    APP_STATE_CAN_RECEIVE,
    APP_STATE_CAN_TRANSMIT,
    APP_STATE_CAN_IDLE,
    APP_STATE_CAN_XFER_SUCCESSFUL,
    APP_STATE_CAN_XFER_ERROR,
    APP_STATE_CAN_USER_INPUT
} APP_STATES;

/* Variable to save Tx/Rx transfer status and context */
static uint32_t status = 0;
static uint32_t xferContext = 0;
/* Variable to save Tx/Rx message */
static uint8_t loop_count = 0;
static uint8_t user_input = 0;
/* Variable to save application state */
volatile static APP_STATES state = APP_STATE_CAN_USER_INPUT;

static uint8_t txFiFo[CAN1_TX_FIFO_BUFFER_SIZE];
static uint8_t rxFiFo0[CAN1_RX_FIFO0_SIZE];
static uint8_t rxFiFo1[CAN1_RX_FIFO1_SIZE];
static uint8_t rxBuffer[CAN1_RX_BUFFER_SIZE];

// *****************************************************************************
// *****************************************************************************
// Section: Local functions
// *****************************************************************************
// *****************************************************************************

/* Message Length to Data length code */
static uint8_t CANLengthToDlcGet(uint8_t length)
{
    uint8_t dlc = 0;

    if (length <= 8U)
    {
        dlc = length;
    }
    else if (length <= 12U)
    {
        dlc = 0x9U;
    }
    else if (length <= 16U)
    {
        dlc = 0xAU;
    }
    else if (length <= 20U)
    {
        dlc = 0xBU;
    }
    else if (length <= 24U)
    {
        dlc = 0xCU;
    }
    else if (length <= 32U)
    {
        dlc = 0xDU;
    }
    else if (length <= 48U)
    {
        dlc = 0xEU;
    }
    else
    {
        dlc = 0xFU;
    }
    return dlc;
}

/* Data length code to Message Length */
static uint8_t CANDlcToLengthGet(uint8_t dlc)
{
    uint8_t msgLength[] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U};
    return msgLength[dlc];
}

/* Menu */
static void display_menu(void)
{
	printf("Menu :\r\n"
	       "  -- Select the action:\r\n"
	       "  0: Send FD standard message with ID: 0x45A and 64 byte data 0 to 63. \r\n"
	       "  1: Send FD standard message with ID: 0x469 and 64 byte data 128 to 191. \r\n"
	       "  2: Send FD extended message with ID: 0x100000A5 and 64 byte data 0 to 63. \r\n"
	       "  3: Send FD extended message with ID: 0x10000096 and 64 byte data 128 to 191. \r\n"
	       "  4: Send normal standard message with ID: 0x469 and 8 byte data 0 to 7. \r\n"
	       "  m: Display menu \r\n\r\n");
}

/* Print Rx Message */
static void print_message(uint8_t numberOfMessage, CAN_RX_BUFFER *rxBuf, uint8_t rxBufLen, uint8_t rxFifoBuf)
{
    uint8_t length = 0;
    uint8_t msgLength = 0;
    uint32_t id = 0;

    if (rxFifoBuf == 0)
        printf(" Rx FIFO0 :");
    else if (rxFifoBuf == 1)
        printf(" Rx FIFO1 :");
    else if (rxFifoBuf == 2)
        printf(" Rx Buffer :");

    for (uint8_t count = 0; count < numberOfMessage; count++)
    {
        /* Print message to Console */
        printf(" New Message Received\r\n");
        id = rxBuf->xtd ? rxBuf->id : READ_ID(rxBuf->id);
        msgLength = CANDlcToLengthGet(rxBuf->dlc);
        length = msgLength;
        printf(" Message - Timestamp : 0x%x ID : 0x%x Length : 0x%x ", (unsigned int)rxBuf->rxts, (unsigned int)id, (unsigned int)msgLength);
        printf("Message : ");
        while(length)
        {
            printf("0x%x ", rxBuf->data[msgLength - length--]);
        }
        printf("\r\n");
        rxBuf += rxBufLen;
    }
}

/* This function will be called by CAN PLIB when transfer is completed from Tx FIFO */
void APP_CAN_TxFifoCallback(uintptr_t context)
{
    xferContext = context;

    /* Check CAN Status */
    status = CAN1_ErrorGet();

    if (((status & CAN_PSR_LEC_Msk) == CAN_ERROR_NONE) || ((status & CAN_PSR_LEC_Msk) == CAN_ERROR_LEC_NC))
    {
        switch ((APP_STATES)context)
        {
            case APP_STATE_CAN_TRANSMIT:
            {
                state = APP_STATE_CAN_XFER_SUCCESSFUL;
                break;
            }
            default:
                break;
        }
    }
    else
    {
        state = APP_STATE_CAN_XFER_ERROR;
    }
}

/* This function will be called by CAN PLIB when Message received in Rx Buffer */
void APP_CAN_RxBufferCallback(uint8_t bufferNumber, uintptr_t context)
{
    xferContext = context;

    /* Check CAN Status */
    status = CAN1_ErrorGet();

    if (((status & CAN_PSR_LEC_Msk) == CAN_ERROR_NONE) || ((status & CAN_PSR_LEC_Msk) == CAN_ERROR_LEC_NC))
    {
        switch ((APP_STATES)context)
        {
            case APP_STATE_CAN_RECEIVE:
            {
                memset(rxBuffer, 0x00, CAN1_RX_BUFFER_ELEMENT_SIZE);
                if (CAN1_MessageReceive(bufferNumber, (CAN_RX_BUFFER *)rxBuffer) == true)
                {
                    print_message(1, (CAN_RX_BUFFER *)rxBuffer, CAN1_RX_BUFFER_ELEMENT_SIZE, 2);
                    state = APP_STATE_CAN_XFER_SUCCESSFUL;
                }
                else
                {
                    state = APP_STATE_CAN_XFER_ERROR;
                }
                break;
            }
            default:
                break;
        }
    }
    else
    {
        state = APP_STATE_CAN_XFER_ERROR;
    }
}

/* This function will be called by CAN PLIB when Message received in Rx FIFO0 */
void APP_CAN_RxFifo0Callback(uint8_t numberOfMessage, uintptr_t context)
{
    xferContext = context;

    /* Check CAN Status */
    status = CAN1_ErrorGet();

    if (((status & CAN_PSR_LEC_Msk) == CAN_ERROR_NONE) || ((status & CAN_PSR_LEC_Msk) == CAN_ERROR_LEC_NC))
    {
        switch ((APP_STATES)context)
        {
            case APP_STATE_CAN_RECEIVE:
            {
                memset(rxFiFo0, 0x00, (numberOfMessage * CAN1_RX_FIFO0_ELEMENT_SIZE));
                if (CAN1_MessageReceiveFifo(CAN_RX_FIFO_0, numberOfMessage, (CAN_RX_BUFFER *)rxFiFo0) == true)
                {
                    print_message(numberOfMessage, (CAN_RX_BUFFER *)rxFiFo0, CAN1_RX_FIFO0_ELEMENT_SIZE, 0);
                    state = APP_STATE_CAN_XFER_SUCCESSFUL;
                }
                else
                {
                    state = APP_STATE_CAN_XFER_ERROR;
                }
                break;
            }
            default:
                break;
        }
    }
    else
    {
        state = APP_STATE_CAN_XFER_ERROR;
    }
}

/* This function will be called by CAN PLIB when Message received in Rx FIFO1 */
void APP_CAN_RxFifo1Callback(uint8_t numberOfMessage, uintptr_t context)
{
    xferContext = context;

    /* Check CAN Status */
    status = CAN1_ErrorGet();

    if (((status & CAN_PSR_LEC_Msk) == CAN_ERROR_NONE) || ((status & CAN_PSR_LEC_Msk) == CAN_ERROR_LEC_NC))
    {
        switch ((APP_STATES)context)
        {
            case APP_STATE_CAN_RECEIVE:
            {
                memset(rxFiFo1, 0x00, (numberOfMessage * CAN1_RX_FIFO1_ELEMENT_SIZE));
                if (CAN1_MessageReceiveFifo(CAN_RX_FIFO_1, numberOfMessage, (CAN_RX_BUFFER *)rxFiFo1) == true)
                {
                    print_message(numberOfMessage, (CAN_RX_BUFFER *)rxFiFo1, CAN1_RX_FIFO1_ELEMENT_SIZE, 1);
                    state = APP_STATE_CAN_XFER_SUCCESSFUL;
                }
                else
                {
                    state = APP_STATE_CAN_XFER_ERROR;
                }
                break;
            }
            default:
                break;
        }
    }
    else
    {
        state = APP_STATE_CAN_XFER_ERROR;
    }
}

// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    CAN_TX_BUFFER *txBuffer = NULL;

    /* Initialize all modules */
    SYS_Initialize ( NULL );

    printf(" ------------------------------ \r\n");
    printf("        CAN FD Demo            \r\n");
    printf(" ------------------------------ \r\n");
    
    /* Set Message RAM Configuration */
    CAN1_MessageRAMConfigSet(Can1MessageRAM);

    CAN1_RxFifoCallbackRegister(CAN_RX_FIFO_0, APP_CAN_RxFifo0Callback, APP_STATE_CAN_RECEIVE);
    CAN1_RxFifoCallbackRegister(CAN_RX_FIFO_1, APP_CAN_RxFifo1Callback, APP_STATE_CAN_RECEIVE);
    CAN1_RxBuffersCallbackRegister(APP_CAN_RxBufferCallback, APP_STATE_CAN_RECEIVE);

    display_menu();
    
    while ( true )
    {
        if (state == APP_STATE_CAN_USER_INPUT)
        {
            /* Read user input */
            scanf("%c", (char *) &user_input);
            
            switch (user_input)
            {
				case '0':
                    memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                    txBuffer = (CAN_TX_BUFFER *)txFiFo;
                    txBuffer->id = WRITE_ID(0x45A);
                    txBuffer->dlc = CANLengthToDlcGet(64);
                    txBuffer->fdf = 1;
                    txBuffer->brs = 1;
					for (loop_count = 0; loop_count < 64; loop_count++){
						txBuffer->data[loop_count] = loop_count;
					}                
					printf("  0: Send FD standard message with ID: 0x45A and 64 byte data 0 to 63.\r\n");
                    CAN1_TxFifoCallbackRegister( APP_CAN_TxFifoCallback, (uintptr_t)APP_STATE_CAN_TRANSMIT );
                    state = APP_STATE_CAN_IDLE;
                    if (CAN1_MessageTransmitFifo(1, txBuffer) == false)
                    {
                        printf(" Failed \r\n");
                    }             
                    break;
				case '1':
                    memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                    txBuffer = (CAN_TX_BUFFER *)txFiFo;
                    txBuffer->id = WRITE_ID(0x469);
                    txBuffer->dlc = CANLengthToDlcGet(64);
                    txBuffer->fdf = 1;
                    txBuffer->brs = 1;
					for (loop_count = 128; loop_count < 192; loop_count++){
						txBuffer->data[loop_count - 128] = loop_count;
					}                
 					printf("  1: Send FD standard message with ID: 0x469 and 64 byte data 128 to 191.\r\n");
					CAN1_TxFifoCallbackRegister( APP_CAN_TxFifoCallback, (uintptr_t)APP_STATE_CAN_TRANSMIT );
                    state = APP_STATE_CAN_IDLE;
					if (CAN1_MessageTransmitFifo(1, txBuffer) == false)
                    {
                        printf(" Failed \r\n");
                    }             
                    break;
				case '2':
                    memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                    txBuffer = (CAN_TX_BUFFER *)txFiFo;
                    txBuffer->id = 0x100000A5;
                    txBuffer->dlc = CANLengthToDlcGet(64);
                    txBuffer->xtd = 1;
                    txBuffer->fdf = 1;
                    txBuffer->brs = 1;
					for (loop_count = 0; loop_count < 64; loop_count++){
						txBuffer->data[loop_count] = loop_count;
					}
					printf("  2: Send FD extended message with ID: 0x100000A5 and 64 byte data 0 to 63.\r\n");
                    CAN1_TxFifoCallbackRegister( APP_CAN_TxFifoCallback, (uintptr_t)APP_STATE_CAN_TRANSMIT );
                    state = APP_STATE_CAN_IDLE;
                    if (CAN1_MessageTransmitFifo(1, txBuffer) == false)
                    {
                        printf(" Failed \r\n");
                    }
                    break;
				case '3':
                    memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                    txBuffer = (CAN_TX_BUFFER *)txFiFo;
                    txBuffer->id = 0x10000096;
                    txBuffer->dlc = CANLengthToDlcGet(64);
                    txBuffer->xtd = 1;
                    txBuffer->fdf = 1;
                    txBuffer->brs = 1;
					for (loop_count = 128; loop_count < 192; loop_count++){
						txBuffer->data[loop_count - 128] = loop_count;
					}
					printf("  3: Send FD extended message with ID: 0x10000096 and 64 byte data 128 to 191.\r\n");
                    CAN1_TxFifoCallbackRegister( APP_CAN_TxFifoCallback, (uintptr_t)APP_STATE_CAN_TRANSMIT );
                    state = APP_STATE_CAN_IDLE;
                    if (CAN1_MessageTransmitFifo(1, txBuffer) == false)
                    {
                        printf(" Failed \r\n");
                    }
                    break;
				case '4':
                    memset(txFiFo, 0x00, CAN1_TX_FIFO_BUFFER_ELEMENT_SIZE);
                    txBuffer = (CAN_TX_BUFFER *)txFiFo;
					txBuffer->id = WRITE_ID(0x469);
                    txBuffer->dlc = 8;
					for (loop_count = 0; loop_count < 8; loop_count++){
						txBuffer->data[loop_count] = loop_count;
					}                
 					printf("  4: Send normal standard message with ID: 0x469 and 8 byte data 0 to 7.\r\n");
					CAN1_TxFifoCallbackRegister( APP_CAN_TxFifoCallback, (uintptr_t)APP_STATE_CAN_TRANSMIT );
                    state = APP_STATE_CAN_IDLE;
					if (CAN1_MessageTransmitFifo(1, txBuffer) == false)
                    {
                        printf(" Failed \r\n");
                    }             
                    break;
				case 'm':
				case 'M':
					display_menu();
					break;
					
				default:
					printf(" Invalid Input \r\n");
					break;
            }
        }

        /* Check the application's current state. */
        switch (state)
        {
            case APP_STATE_CAN_IDLE:
            {
                /* Application can do other task here */
                break;
            }
            case APP_STATE_CAN_XFER_SUCCESSFUL:
            {
                if ((APP_STATES)xferContext == APP_STATE_CAN_TRANSMIT)
                {
                    printf(" Success\r\n");
                }                
                state = APP_STATE_CAN_USER_INPUT;
                break;
            }
            case APP_STATE_CAN_XFER_ERROR:
            {
                if ((APP_STATES)xferContext == APP_STATE_CAN_RECEIVE)
                {
                    printf(" Error in received message\r\n");
                }
                else
                {
                    printf(" Failed\r\n");
                }
                state = APP_STATE_CAN_USER_INPUT;
                break;
            }
            default:
            {
                break;
            }
        }
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

Library Interface

Control Area Network peripheral library provides the following interfaces:

Functions

Name Description
CANx_Initialize Initializes given instance of the CAN peripheral
CANx_MessageTransmit Transmits a message into CAN bus from the specific Tx buffer
CANx_MessageTransmitFifo Transmit multiple messages into CAN bus from Tx FIFO
CANx_TxFifoFreeLevelGet Returns Tx FIFO Free Level
CANx_TxBufferIsBusy Check if Transmission request is pending for the specific Tx buffer
CANx_TxEventFifoRead Read Tx Event FIFO for the transmitted messages
CANx_TxEventFifoFillLevelGet Returns Tx Event FIFO Fill Level
CANx_MessageReceive Read a message from the specific Rx Buffer
CANx_RxBufferNumberGet Get Rx Buffer Number
CANx_MessageReceiveFifo Read messages from Rx FIFO0/FIFO1
CANx_RxFifoFillLevelGet Returns Rx FIFO0/FIFO1 Fill Level
CANx_ErrorGet Returns the error during transfer
CANx_ErrorCountGet Returns the transmit and receive error count during transfer
CANx_InterruptGet Returns the Interrupt status
CANx_InterruptClear Clears Interrupt status
CANx_MessageRAMConfigSet Set the Message RAM Configuration
CANx_StandardFilterElementSet Set a standard filter element configuration
CANx_StandardFilterElementGet Get a standard filter element configuration
CANx_ExtendedFilterElementSet Set a Extended filter element configuration
CANx_ExtendedFilterElementGet Get a Extended filter element configuration
CANx_SleepModeEnter Puts the CAN Peripheral in sleep mode (clock stop request)
CANx_SleepModeExit Exits CAN peripheral from sleep mode (clock stop request)
CANx_TxBuffersCallbackRegister Sets the pointer to the function (and it's contextHandle) to be called when the given CAN's Tx transfer events occur
CANx_TxFifoCallbackRegister Sets the pointer to the function (and it's contextHandle) to be called when the given CAN's Tx transfer events occur
CANx_TxEventFifoCallbackRegister Sets the pointer to the function (and it's contextHandle) to be called when the given CAN's Tx transfer events occur
CANx_BitTimingCalculationGet Returns the bit timing information
CANx_BitTimingSet Sets the bit timing
CANx_RxBuffersCallbackRegister Sets the pointer to the function (and it's contextHandle) to be called when the given CAN's Rx transfer events occur
CANx_RxFifoCallbackRegister Sets the pointer to the function (and it's contextHandle) to be called when the given CAN's Rx transfer events occur

Data types and constants

Name Type Description
CAN_RX_FIFO_NUM Enum CAN Rx FIFO Number
CAN_INTERRUPT_MASK Enum CAN Interrupt Mask
CAN_ERROR Typedef CAN Transfer Error data type
CAN_TX_FIFO_CALLBACK Typedef CAN Callback Function Pointer for Tx FIFO
CAN_TXRX_BUFFERS_CALLBACK Typedef CAN Callback Function Pointer for TX/RX Buffers
CAN_TX_EVENT_FIFO_CALLBACK Typedef CAN Callback Function Pointer for Tx Event FIFO
CAN_RX_FIFO_CALLBACK Typedef CAN Callback Function Pointer for Rx FIFO0/FIFO1
CAN_MSG_RAM_CONFIG Struct CAN Message RAM Configuration structure
CAN_RX_BUFFER Struct CAN Rx Buffer and FIFO Element Structure
CAN_TX_BUFFER Struct CAN Tx Buffer Element Structure
CAN_TX_EVENT_FIFO Struct CAN Tx Event FIFO Element Structure
CAN_TX_FIFO_CALLBACK_OBJ Struct CAN transfer event callback structure for Tx FIFO
CAN_TXRX_BUFFERS_CALLBACK_OBJ Struct CAN transfer event callback structure for Tx/Rx Buffers
CAN_TX_EVENT_FIFO_CALLBACK_OBJ Struct CAN transfer event callback structure for Tx Event FIFO
CAN_RX_FIFO_CALLBACK_OBJ Struct CAN transfer event callback structure for Rx FIFO0/FIFO1
CAN_NOMINAL_BIT_TIMING Struct Nominal bit timing parameters
CAN_BIT_TIMING Struct Bit timing parameters