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.

TMS320F28379D: CAN_loopback_bitfield.c cant able to send data when EXL and TEST bit is disable

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Tool/software:

Hi 

whenever i try to Disable these two registers 

CanaRegs.CAN_CTL.bit.Test = 1;
CanaRegs.CAN_TEST.bit.EXL = 1;

data does not come into a CANTX pin.

please suggest me what's going wrong in this code

//###########################################################################
//
// FILE:   can_loopback_bitfields.c
//
// TITLE:  Example to demonstrate basic CAN setup and use.
//
//! \addtogroup cpu01_example_list
//! <h1>CAN External Loopback Using Bitfields (can_loopback_bitfields)</h1>
//!
//! IMPORTANT: CAN Bitfield headers require compiler v16.6.0.STS and newer!
//!
//! This example, using bitfield headers, shows the basic setup of CAN in
//! order to transmit and receive messages on the CAN bus.  The CAN
//! peripheral is configured to transmit messages with a specific CAN ID.
//! A message is then transmitted once per second, using a simple delay
//! loop for timing.  The message that is sent is a 4 byte message that
//! contains an incrementing pattern.
//!
//! This example sets up the CAN controller in External Loopback test mode.
//! Data transmitted is visible on the CAN0TX pin and can be received with
//! an appropriate mailbox configuration.
//!
//
//###########################################################################
//
// $Release Date:  $
// $Copyright:
// Copyright (C) 2013-2023 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.
// $
//###########################################################################

//
// Included Files
//
#include "F28x_Project.h"

//
// Defines
//
#define CAN_MSG_ID              0x111 // This example only supports standard ID
#define CAN_TX_MSG_OBJ          1
#define CAN_RX_MSG_OBJ          2
#define CAN_MAX_BIT_DIVISOR     (13)   // The maximum CAN bit timing divisor
#define CAN_MIN_BIT_DIVISOR     (5)    // The minimum CAN bit timing divisor
#define CAN_MAX_PRE_DIVISOR     (1024) // The maximum CAN pre-divisor
#define CAN_MIN_PRE_DIVISOR     (1)    // The minimum CAN pre-divisor
#define CAN_BTR_BRP_M           (0x3F)
#define CAN_BTR_BRPE_M          (0xF0000)
#define CAN_MSG_ID_SHIFT        18U


//
// Globals
//
unsigned char ucTXMsgData[4] = {0x1, 0x2, 0x3, 0x4}; // TX Data
unsigned char ucRXMsgData[4] = {0, 0, 0, 0};         // RX Data
uint32_t messageSize = sizeof(ucTXMsgData);          // Message Size (DLC)
volatile unsigned long msgCount = 0; // A counter that keeps track of the
                                     // number of times the transmit was
                                     // successful.
volatile unsigned long errFlag = 0;  // A flag to indicate that some
                                     // transmission error occurred.

static const uint16_t canBitValues[] =
{
    0x1100, // TSEG2 2, TSEG1 2, SJW 1, Divide 5
    0x1200, // TSEG2 2, TSEG1 3, SJW 1, Divide 6
    0x2240, // TSEG2 3, TSEG1 3, SJW 2, Divide 7
    0x2340, // TSEG2 3, TSEG1 4, SJW 2, Divide 8
    0x3340, // TSEG2 4, TSEG1 4, SJW 2, Divide 9
    0x3440, // TSEG2 4, TSEG1 5, SJW 2, Divide 10
    0x3540, // TSEG2 4, TSEG1 6, SJW 2, Divide 11
    0x3640, // TSEG2 4, TSEG1 7, SJW 2, Divide 12
    0x3740  // TSEG2 4, TSEG1 8, SJW 2, Divide 13
};

typedef enum
{
        //! Transmit message object.
        MSG_OBJ_TYPE_TRANSMIT,

        //! Receive message object.
        MSG_OBJ_TYPE_RECEIVE
}
msgObjType;

//
// Function Prototypes
//
uint32_t setCANBitRate(uint32_t sourceClock, uint32_t bitRate);
void  setupMessageObject(uint32_t objID, uint32_t msgID, msgObjType msgType);
void sendCANMessage(uint32_t objID);
bool getCANMessage(uint32_t objID);
void CAN_A_B_GPIO();

//
// Main
//
int
main(void)
{
    //
    // Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
    //
    InitSysCtrl();

    //
    // Initialize GPIO:
    // This example function is found in the F2837xD_Gpio.c file and
    // illustrates how to set the GPIO to its default state.
    //
//    InitGpio();
//    GPIO_SetupPinMux(70, GPIO_MUX_CPU1, 5);  //GPIO39 - CANRXA
//    GPIO_SetupPinMux(71, GPIO_MUX_CPU1, 5);  //GPIO38 - CANTXA
//    GPIO_SetupPinOptions(70, GPIO_INPUT, GPIO_ASYNC);
//    GPIO_SetupPinOptions(71, GPIO_OUTPUT, GPIO_PUSHPULL);

    CAN_A_B_GPIO();

    //
    // Initialize the CAN-A controller
    //
    InitCAN();

    //
    // Setup CAN to be clocked off the SYSCLKOUT
    //
    ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0;

    //
    // Set up the bit rate for the CAN bus.  This function sets up the CAN
    // bus timing for a nominal configuration.
    // In this example, the CAN bus is set to 500 kbps.
    //
    // Consult the TRM for more information about
    // CAN peripheral clocking.
    //
    uint32_t status = setCANBitRate(200000000, 5000000);

    //
    // If values requested are too small or too large, catch error
    //
    if(status == 0)
    {
        errFlag++;
        ESTOP0;         // Stop here and handle error
    }

    //
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    //

    DINT;

    //
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xD_PieCtrl.c file.
    //
    InitPieCtrl();

    //
    // Disable CPU interrupts and clear all CPU interrupt flags:
    //
    IER = 0x0000;
    IFR = 0x0000;

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2837xD_DefaultIsr.c.
    // This function is found in F2837xD_PieVect.c.
    //
    InitPieVectTable();

    //
    // Enable the CAN for operation.
    //
    CanaRegs.CAN_CTL.bit.Init = 0;

    //
    // Enable test mode and select external loopback
    //
     CanaRegs.CAN_CTL.bit.Test = 1;
     CanaRegs.CAN_TEST.bit.EXL = 1;

    //
    // Initialize the message object that will be used for sending CAN
    // messages.
    //
    setupMessageObject(CAN_TX_MSG_OBJ, CAN_MSG_ID, MSG_OBJ_TYPE_TRANSMIT);

    //
    // Initialize the message object that will be used for receiving CAN
    // messages.
    //
    setupMessageObject(CAN_RX_MSG_OBJ, CAN_MSG_ID, MSG_OBJ_TYPE_RECEIVE);

    //
    // Enter loop to send messages.  A new message will be sent once per
    // second.  The 4 bytes of message content will be treated as an unsigned
    // long and incremented by one each time.
    //
    for(;;)
    {
        //
        // Send the CAN message using object number 1 (not the same thing as
        // CAN ID, which is also 1 in this example).  This function will cause
        // the message to be transmitted right away.
        //
        sendCANMessage(CAN_TX_MSG_OBJ);

        //
        // Now wait 1 second before continuing
        //
        DELAY_US(1000*1000);

        //
        // Get the receive message
        //
        getCANMessage(CAN_RX_MSG_OBJ);

        //
        // Ensure the received data matches the transmitted data
        //
        if((ucTXMsgData[0] != ucRXMsgData[0]) ||
           (ucTXMsgData[1] != ucRXMsgData[1]) ||
           (ucTXMsgData[2] != ucRXMsgData[2]) ||
           (ucTXMsgData[3] != ucRXMsgData[3]))
        {
            errFlag++;
            //asm(" ESTOP0");
        }
        else
        {
            //
            // Increment successful message count
            //
            msgCount++;
        }
            

        //
        // Increment the value in the transmitted message data.
        //
        ucTXMsgData[0] += 0x1;
        ucTXMsgData[1] += 0x1;
        ucTXMsgData[2] += 0x1;
        ucTXMsgData[3] += 0x1;
        
        //
        // Reset data if exceeds a byte
        //

        if(ucTXMsgData[0] > 0xFF)
        {
            ucTXMsgData[0] = 0;  
        }
        if(ucTXMsgData[1] > 0xFF)
        {
            ucTXMsgData[1] = 0; 
        }     
        if(ucTXMsgData[2] > 0xFF)
        {
            ucTXMsgData[2] = 0; 
        }     
        if(ucTXMsgData[3] > 0xFF)
        {
            ucTXMsgData[3] = 0; 
        } 
    }
}

//
// setCANBitRate - Set the CAN bit rate based on device clock (Hz)
//                 and desired bit rate (Hz)
//
uint32_t setCANBitRate(uint32_t sourceClock, uint32_t bitRate)
{
    uint32_t desiredRatio;
    uint32_t canBits;
    uint32_t preDivide;
    uint32_t regValue;
    uint16_t canControlValue;

    //
    // Calculate the desired clock rate.
    //
    desiredRatio = sourceClock / bitRate;

    //
    // Make sure that the Desired Ratio is not too large.  This enforces the
    // requirement that the bit rate is larger than requested.
    //
    if((sourceClock / desiredRatio) > bitRate)
    {
        desiredRatio += 1;
    }

    //
    // Check all possible values to find a matching value.
    //
    while(desiredRatio <= CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR)
    {
        //
        // Loop through all possible CAN bit divisors.
        //
        for(canBits = CAN_MAX_BIT_DIVISOR;
            canBits >= CAN_MIN_BIT_DIVISOR;
            canBits--)
        {
            //
            // For a given CAN bit divisor save the pre divisor.
            //
            preDivide = desiredRatio / canBits;

            //
            // If the calculated divisors match the desired clock ratio then
            // return these bit rate and set the CAN bit timing.
            //
            if((preDivide * canBits) == desiredRatio)
            {
                //
                // Start building the bit timing value by adding the bit timing
                // in time quanta.
                //
                regValue = canBitValues[canBits - CAN_MIN_BIT_DIVISOR];

                //
                // To set the bit timing register, the controller must be
                // placed
                // in init mode (if not already), and also configuration change
                // bit enabled.  The state of the register should be saved
                // so it can be restored.
                //
                canControlValue = CanaRegs.CAN_CTL.all;
                CanaRegs.CAN_CTL.bit.Init = 1;
                CanaRegs.CAN_CTL.bit.CCE = 1;

                //
                // Now add in the pre-scalar on the bit rate.
                //
                regValue |= ((preDivide - 1) & CAN_BTR_BRP_M) |
                            (((preDivide - 1) << 10) & CAN_BTR_BRPE_M);

                //
                // Set the clock bits in the and the bits of the
                // pre-scalar.
                //
                CanaRegs.CAN_BTR.all = regValue;

                //
                // Restore the saved CAN Control register.
                //
                CanaRegs.CAN_CTL.all = canControlValue;

                //
                // Return the computed bit rate.
                //
                return(sourceClock / ( preDivide * canBits));
            }
        }

        //
        // Move the divisor up one and look again.  Only in rare cases are
        // more than 2 loops required to find the value.
        //
        desiredRatio++;
    }
    return 0;
}

//
// setupMessageObject - Setup message object as Transmit or Receive
//
void setupMessageObject(uint32_t objID, uint32_t msgID, msgObjType msgType)
{
    //
    // Use Shadow variable for IF1CMD. IF1CMD should be written to in
    // single 32-bit write.
    //
    union CAN_IF1CMD_REG CAN_IF1CMD_SHADOW;
    
    //
    // Wait for busy bit to clear.
    //
    while(CanaRegs.CAN_IF1CMD.bit.Busy)
    {
    }

    //
    // Clear and Write out the registers to program the message object.
    //
    CAN_IF1CMD_SHADOW.all = 0;    
    CanaRegs.CAN_IF1MSK.all = 0;
    CanaRegs.CAN_IF1ARB.all = 0;
    CanaRegs.CAN_IF1MCTL.all = 0;

    //
    // Set the Control, Mask, and Arb bit so that they get transferred to the
    // Message object.
    //
    CAN_IF1CMD_SHADOW.bit.Control = 1;
    CAN_IF1CMD_SHADOW.bit.Arb = 1;
    CAN_IF1CMD_SHADOW.bit.Mask = 1;
    CAN_IF1CMD_SHADOW.bit.DIR = 1;

    //
    // Set direction to transmit
    //
    if(msgType == MSG_OBJ_TYPE_TRANSMIT)
    {
        CanaRegs.CAN_IF1ARB.bit.Dir = 1;
    }

    //
    // Set Message ID (this example assumes 11 bit ID mask)
    //
    CanaRegs.CAN_IF1ARB.bit.ID = (msgID << CAN_MSG_ID_SHIFT);
    CanaRegs.CAN_IF1ARB.bit.MsgVal = 1;

    //
    // Set the data length since this is set for all transfers.  This is
    // also a single transfer and not a FIFO transfer so set EOB bit.
    //
    CanaRegs.CAN_IF1MCTL.bit.DLC = messageSize;
    CanaRegs.CAN_IF1MCTL.bit.EoB = 1;

    //
    // Transfer data to message object RAM
    //
    CAN_IF1CMD_SHADOW.bit.MSG_NUM = objID;
    CanaRegs.CAN_IF1CMD.all = CAN_IF1CMD_SHADOW.all;
}

//
// sendCANMessage - Transmit data from the specified message object
//
void sendCANMessage(uint32_t objID)
{
    //
    // Use Shadow variable for IF1CMD. IF1CMD should be written to in
    // single 32-bit write.
    //
    union CAN_IF1CMD_REG CAN_IF1CMD_SHADOW;
    
    //
    // Wait for busy bit to clear.
    //
    while(CanaRegs.CAN_IF1CMD.bit.Busy)
    {
    }

    //
    // Write data to transfer into DATA-A and DATA-B interface registers
    //
    uint16_t index;
    for(index = 0; index < messageSize; index++)
    {
        switch(index)
        {
            case 0:
                CanaRegs.CAN_IF1DATA.bit.Data_0 = ucTXMsgData[index];
                break;
            case 1:
                CanaRegs.CAN_IF1DATA.bit.Data_1 = ucTXMsgData[index];
                break;
            case 2:
                CanaRegs.CAN_IF1DATA.bit.Data_2 = ucTXMsgData[index];
                break;
            case 3:
                CanaRegs.CAN_IF1DATA.bit.Data_3 = ucTXMsgData[index];
                break;
            case 4:
                CanaRegs.CAN_IF1DATB.bit.Data_4 = ucTXMsgData[index];
                break;
            case 5:
                CanaRegs.CAN_IF1DATB.bit.Data_5 = ucTXMsgData[index];
                break;
            case 6:
                CanaRegs.CAN_IF1DATB.bit.Data_6 = ucTXMsgData[index];
                break;
            case 7:
                CanaRegs.CAN_IF1DATB.bit.Data_7 = ucTXMsgData[index];
                break;
        }
    }

    //
    // Set Direction to write and set DATA-A/DATA-B to be transfered to
    // message object
    //
    CAN_IF1CMD_SHADOW.all = 0;
    CAN_IF1CMD_SHADOW.bit.DIR = 1;
    CAN_IF1CMD_SHADOW.bit.DATA_A = 1;
    CAN_IF1CMD_SHADOW.bit.DATA_B = 1;

    //
    // Set Tx Request Bit
    //
    CAN_IF1CMD_SHADOW.bit.TXRQST = 1;

    //
    // Transfer the message object to the message object specified by
    // objID.
    //
    CAN_IF1CMD_SHADOW.bit.MSG_NUM = objID;
    CanaRegs.CAN_IF1CMD.all = CAN_IF1CMD_SHADOW.all;
}

//
// getCANMessage - Check the message object for new data.
//                 If new data, data written into array and return true.
//                 If no new data, return false.
//
bool getCANMessage(uint32_t objID)
{
    bool status;
    
    //
    // Use Shadow variable for IF2CMD. IF2CMD should be written to in
    // single 32-bit write.
    //
    union CAN_IF2CMD_REG CAN_IF2CMD_SHADOW;

    //
    // Set the Message Data A, Data B, and control values to be read
    // on request for data from the message object.
    //
    CAN_IF2CMD_SHADOW.all = 0;
    CAN_IF2CMD_SHADOW.bit.Control = 1;
    CAN_IF2CMD_SHADOW.bit.DATA_A = 1;
    CAN_IF2CMD_SHADOW.bit.DATA_B = 1;

    //
    // Transfer the message object to the message object IF register.
    //
    CAN_IF2CMD_SHADOW.bit.MSG_NUM = objID;
    CanaRegs.CAN_IF2CMD.all = CAN_IF2CMD_SHADOW.all;

    //
    // Wait for busy bit to clear.
    //
    while(CanaRegs.CAN_IF2CMD.bit.Busy)
    {
    }

    //
    // See if there is new data available.
    //
    if(CanaRegs.CAN_IF2MCTL.bit.NewDat == 1)
    {
        //
        // Read out the data from the CAN registers.
        //
        uint16_t index;
        for(index = 0; index < messageSize; index++)
        {
            switch(index)
            {
                case 0:
                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_0;
                break;
                case 1:
                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_1;
                break;
                case 2:
                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_2;
                break;
                case 3:
                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_3;
                break;
                case 4:
                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_4;
                break;
                case 5:
                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_5;
                break;
                case 6:
                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_6;
                break;
                case 7:
                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_7;
                break;
            }
        }

        //
        // Populate Shadow Variable
        //
        CAN_IF2CMD_SHADOW.all = CanaRegs.CAN_IF2CMD.all;

        //
        // Clear New Data Flag
        //
        CAN_IF2CMD_SHADOW.bit.TxRqst = 1;

        //
        // Transfer the message object to the message object IF register.
        //
        CAN_IF2CMD_SHADOW.bit.MSG_NUM = objID;
        CanaRegs.CAN_IF2CMD.all = CAN_IF2CMD_SHADOW.all;

        status = true;
    }
    else
    {
        status = false;
    }

    return(status);
}


void CAN_A_B_GPIO(){

    EALLOW;

    /*****************CAN_A  (CANRXA (I)) *****************/

    GpioCtrlRegs.GPCGMUX1.bit.GPIO70 = 0x01;
    GpioCtrlRegs.GPCMUX1.bit.GPIO70  = 0x01;
   // GpioCtrlRegs.GPCDIR.bit.GPIO70   = 0x00; //Configure as Output, 0 for Input and 1 for Output
  //  GpioCtrlRegs.GPCINV.bit.GPIO70   = 0x00; //0 for non inverted Output, 1 for inverted Output
    GpioCtrlRegs.GPCPUD.bit.GPIO70   = 0x00; //0 for Enable Pull up, 1 for Disable Pull up
    GpioCtrlRegs.GPCQSEL1.bit.GPIO70 = 0x03;

    /*****************CAN_A  (CANTXA (O)) *****************/

    GpioCtrlRegs.GPCGMUX1.bit.GPIO71 = 0x01;
    GpioCtrlRegs.GPCMUX1.bit.GPIO71  = 0x01;
   // GpioCtrlRegs.GPCDIR.bit.GPIO71   = 0x01; //Configure as Output, 0 for Input and 1 for Output
  //  GpioCtrlRegs.GPCINV.bit.GPIO71   = 0x00; //0 for non inverted Output, 1 for inverted Output
    GpioCtrlRegs.GPCPUD.bit.GPIO71   = 0x00; //0 for Enable Pull up, 1 for Disable Pull up
    GpioCtrlRegs.GPCQSEL1.bit.GPIO71 = 0x03;

    /*****************CAN_B   (CANTXB (O)) *****************/

    GpioCtrlRegs.GPCGMUX1.bit.GPIO72 = 0x01;
    GpioCtrlRegs.GPCMUX1.bit.GPIO72  = 0x01;
 //   GpioCtrlRegs.GPCDIR.bit.GPIO72   = 0x01; //Configure as Output, 0 for Input and 1 for Output
   // GpioCtrlRegs.GPCINV.bit.GPIO72   = 0x00; //0 for non inverted Output, 1 for inverted Output
    GpioCtrlRegs.GPCPUD.bit.GPIO72   = 0x00; //0 for Enable Pull up, 1 for Disable Pull up
    GpioCtrlRegs.GPCQSEL1.bit.GPIO72 = 0x03;


    /*****************CAN_B  (CANRXB (I)) *****************/

    GpioCtrlRegs.GPCGMUX1.bit.GPIO73 = 0x01;
    GpioCtrlRegs.GPCMUX1.bit.GPIO73  = 0x01;
  //  GpioCtrlRegs.GPCDIR.bit.GPIO73   = 0x00; //Configure as Output, 0 for Input and 1 for Output
  //  GpioCtrlRegs.GPCINV.bit.GPIO73   = 0x00; //0 for non inverted Output, 1 for inverted Output
    GpioCtrlRegs.GPCPUD.bit.GPIO73   = 0x00; //0 for Enable Pull up, 1 for Disable Pull up
    GpioCtrlRegs.GPCQSEL1.bit.GPIO73 = 0x03;

    EDIS;
}


//
// End of file
//