This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/TMS320F280049: CAN loopback with DMA

Part Number: TMS320F280049

Tool/software: Code Composer Studio

Hi

I am trying to send data to CAN module by using DMA. To implement this i'm using  "can_ex4_loopback_dma.c" file, but i'm unable to transmit or receive data. 


Timer 2 is used as trigger (every 150us) for DMA to transfer data from txMsgData to IF1 data registers, when DMA completes the transfer it interrupts an ISR (dmaCh5ISR) where data from IF1 registers is transferred to Message RAM. I have checked IF1 data registers which updates to appropriate values.

But i don't find any CAN interrupt happening (both Tx and RX). 
I guess data transfer from IF1 to message RAM is not happening as expected, because of this i am unable to transmit or recieve data.
I have attached code for the reference.
Please let me know changes to be done.

//
// Included Files
//
#include "driverlib.h"
#include "device.h"
//
// Defines
//
#define MSG_DATA_LENGTH    8
#define TX_MSG_OBJ_ID    1
#define RX_MSG_OBJ_ID    2
#define DMA_BURST       4
#define DMA_TRANSFER    1
#define CAN_IF2    2
#define CAN_IF1    1
//
// Globals
//
volatile uint32_t txMsgCount = 0;
volatile uint32_t rxMsgCount = 0;
uint16_t txMsgData[4] = {0x121, 0x341, 0x561, 0x781};
uint16_t rxMsgData[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
volatile uint16_t done = 0;
// Place buffers in GSRAM
#pragma DATA_SECTION(txMsgData, "ramgs0");
#pragma DATA_SECTION(rxMsgData, "ramgs1");
//
// Function Prototypes
//
void initDMA(void);
__interrupt void dmaCh5ISR(void);
__interrupt void canISR(void);
//
// Main
//
void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    Device_init();
    // UV use TIMER 2 to trigger DMA transfer for every 150us
    uint32_t systemFreq_Mhz = 100;
    uint32_t timerPeriod_150us = (systemFreq_Mhz *
                                    (float32_t)150.0) - 1;
    // initialize timer 2
    CPUTimer_setPreScaler(CPUTIMER2_BASE, 0);
    CPUTimer_setEmulationMode(CPUTIMER2_BASE,
                              CPUTIMER_EMULATIONMODE_RUNFREE);
   // CPUTimer_setPeriod(obj->timerHandle[2], 0xFFFFFFFF);
    CPUTimer_setPeriod(CPUTIMER2_BASE, timerPeriod_150us);
    CPUTimer_enableInterrupt(CPUTIMER2_BASE);
     // Starts CPU-Timer 2.
     CPUTimer_startTimer(CPUTIMER2_BASE);
     // Enable interrupt
     Interrupt_enable(INT_TIMER2);
    //
    //
    // Initialize GPIO and configure GPIO pins for CANTX/CANRX
    //
    Device_initGPIO();
    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
    //
    // Initialize the CAN controller
    //
    CAN_initModule(CANA_BASE);
    //
    // Set up the CAN bus bit rate to 500kHz
    // Refer to the Driver Library User Guide for information on how to set
    // tighter timing control. Additionally, consult the device data sheet
    // for more information about the CAN module clocking.
    //
    CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 500000, 20);
    //
    // Enable interrupts on the CAN peripheral.
    //
    CAN_enableInterrupt(CANA_BASE, CAN_INT_IE0 | CAN_INT_ERROR |
                        CAN_INT_STATUS);
    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();
    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;
    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    // This registers the interrupt handler in PIE vector table.
    //
    Interrupt_register(INT_CANA0, &canISR);
    Interrupt_register(INT_DMA_CH5, &dmaCh5ISR);
    //
    // Setup the DMA for CAN use
    //
    initDMA();
    //
    // Enable the CAN DMA request lines for IF1, IF2, and IF3
    //
    CAN_enableDMARequests(CANA_BASE);
    //
    // Enable the CAN and DMA interrupt signal
    //
    Interrupt_enable(INT_DMA_CH5);    
    Interrupt_enable(INT_CANA0);
    CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT0);
    //
    // Enable CAN test mode with external loopback
    //
    //CAN_enableTestMode(CANA_BASE, CAN_TEST_EXL);
    CAN_enableTestMode(CANA_BASE, CAN_TEST_LBACK);
    //
    // Initialize the transmit message object used for sending CAN messages.
    // Message Object Parameters:
    //      Message Object ID Number: 1
    //      Message Identifier: 0x1
    //      Message Frame: Standard
    //      Message Type: Transmit
    //      Message ID Mask: 0x0
    //      Message Object Flags: Transmit Interrupt
    //      Message Data Length: 4 Bytes
    //
    CAN_setupMessageObject(CANA_BASE, TX_MSG_OBJ_ID, 0x1, CAN_MSG_FRAME_STD,
                           CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_TX_INT_ENABLE,
                           MSG_DATA_LENGTH);
    //
    // Initialize the receive message object used for receiving CAN messages.
    // Message Object Parameters:
    //      Message Object ID Number: 2
    //      Message Identifier: 0x1
    //      Message Frame: Standard
    //      Message Type: Receive
    //      Message ID Mask: 0x0
    //      Message Object Flags: Receive Interrupt
    //      Message Data Length: 4 Bytes
    //
    CAN_setupMessageObject(CANA_BASE, RX_MSG_OBJ_ID, 0x1, CAN_MSG_FRAME_STD,
                           CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE,
                           MSG_DATA_LENGTH);
    //
    // Start CAN module operations
    //
    CAN_startModule(CANA_BASE);
    //
    // Start the DMA channel
    //
    DMA_startChannel(DMA_CH5_BASE);
     //
    // Wait until the CAN message is received and the DMA transfer is complete
    //
    while(!done);
    //
    // When the DMA transfer is complete, the program will stop here
    //
   // ESTOP0;
}
//
// initDMA - Initialize the DMA controller and configure DMA channel 5 to
//           transfer the received CAN data into the specified RX buffer
//
void initDMA()
{
    //
    // Initialize DMA
    //
    DMA_initController();
        DMA_configAddresses(DMA_CH5_BASE,(uint16_t *)(CANA_BASE + CAN_O_IF1DATA),txMsgData);
        DMA_configBurst(DMA_CH5_BASE, DMA_BURST, 1, 2);
        DMA_configTransfer(DMA_CH5_BASE, DMA_TRANSFER, 0, 0);
        DMA_configMode(DMA_CH5_BASE, DMA_TRIGGER_TINT2, DMA_CFG_ONESHOT_DISABLE |
                       DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
    //
    // Configure DMA Ch5 interrupts
    //
    DMA_setInterruptMode(DMA_CH5_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(DMA_CH5_BASE);
    DMA_enableTrigger(DMA_CH5_BASE);
}
//
// CAN ISR - The interrupt service routine called when a CAN interrupt is
//           triggered.  It checks for the cause of the interrupt, and
//           maintains a count of all messages that have been transmitted.
//
__interrupt void
canISR(void)
{
    uint32_t status;
    //
    // Read the CAN interrupt status to find the cause of the interrupt
    //
    status = CAN_getInterruptCause(CANA_BASE);
    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
        //
        // Read the controller status.  This will return a field of status
        // error bits that can indicate various errors.  Error processing
        // is not done in this example for simplicity.  Refer to the
        // API documentation for details about the error status bits.
        // The act of reading this status will clear the interrupt.
        //
        status = CAN_getStatus(CANA_BASE);
        //
        // Check to see if an error occurred.
        //
        if(((status  & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 7) &&
           ((status  & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 0))
        {
            // Something went wrong. rData doesn't contain expected data.
           // ESTOP0;
        }
    }
    //
    // Check if the cause is the transmit message object 1
    //
    else if(status == TX_MSG_OBJ_ID)
    {
        //
        // Getting to this point means that the TX interrupt occurred on
        // message object 1, and the message TX is complete.  Clear the
        // message object interrupt.
        //
        CAN_clearInterruptStatus(CANA_BASE, TX_MSG_OBJ_ID);
        //
        // Increment a counter to keep track of how many messages have been
        // sent.  In a real application this could be used to set flags to
        // indicate when a message is sent.
        //
        txMsgCount++;
    }
    //
    // Check if the cause is the receive message object 2
    //
    else if(status == RX_MSG_OBJ_ID)
    {
        //
      
        CAN_readMessage(CANA_BASE,RX_MSG_OBJ_ID,rxMsgData);
        //
        // Getting to this point means that the RX interrupt occurred on
        // message object 2, and the message RX is complete.  Clear the
        // message object interrupt.
        //
        CAN_clearInterruptStatus(CANA_BASE, RX_MSG_OBJ_ID);
        //
        // Increment a counter to keep track of how many messages have been
        // received. In a real application this could be used to set flags to
        // indicate when a message is received.
        //
        rxMsgCount++;
    }
    //
    // If something unexpected caused the interrupt, this would handle it.
    //
    else
    {
        //
        // Spurious interrupt handling can go here.
        //
    }
    //
    // Clear the global interrupt flag for the CAN interrupt line
    //
    CAN_clearGlobalInterruptStatus(CANA_BASE, CAN_GLOBAL_INT_CANINT0);
    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
//
// DMA Channel 5 ISR - The interrupt service routine called when the DMA
//                     channel completes the transfer of data into the buffer.
//
__interrupt void dmaCh5ISR(void)
{
    //uint16_t i, txWordData, txIndex = 0;
    // Transfer the data from IF1 to message RAM
    CAN_transferMessage(CANA_BASE, CAN_IF1, TX_MSG_OBJ_ID, true, false);
    //
    // Stop the DMA channel operations and acknowledge interrupt
    //
  //  DMA_stopChannel(DMA_CH5_BASE);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}
//
// End of File
//