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/TMS320F28379D: CAN_EXTERNAL_TRANSMIT

Part Number: TMS320F28379D

Tool/software: Code Composer Studio

Hi ,
I am using CAN_EXTERNAL_TRANSMIT code from c2000 .

So , the issue is that when the DELAY_US is defined , the Rx ISR executes,but when we remove the delay, the ISR doesn't execute.

Is there any relation between these ?.

How the delay is affecting Rx ISR?.

  • This example does not actually poll a flag bit in the CAN module to ascertain completion of transmission/reception, but relies on a s/w delay loop to ensure completion. This is the reason code doesn't work as intended when you remove the delay. Examples like can_ex4_simple_transmit.c & can_ex5_simple_receive poll the status flags. Refer to SPRACE5 for details.

  • Hi Hareesh,
    Thanks for the reply.

    So , here is what I did : -

    1. Separated the Tx and Rx code , and running on two TMS320F28379D , both at CANB (which has integrated CAN transceiver).

    but I am facing an issue, though I can see the CANH and CANL toggling in the oscilloscope , the Tx code is stucking at "while(((HWREGH(CANB_BASE + CAN_O_ES) & CAN_ES_TXOK)) !=  CAN_ES_TXOK){}"

    which I believe, indicates that Tx has not transmitted succesfully.

    I am attaching the code for the reference.

    2.The data buffers are also updated , when running CAN Tx on one board and CAN Rx on another, but  the Tx code is stucking at "while(((HWREGH(CANB_BASE + CAN_O_ES) & CAN_ES_TXOK)) !=  CAN_ES_TXOK){}".

    Kindly help further.

    //###########################################################################
    //
    // FILE:   can_external_transmit.c
    //
    // TITLE:  Example to demonstrate CAN external transmission
    //
    //! \addtogroup cpu01_example_list
    //! <h1>CAN-A to CAN-B External Transmit (can_external_transmit)</h1>
    //!
    //! This example initializes CAN module A and CAN module B for external
    //! communication. CAN-A module is setup to transmit incrementing data for "n"
    //! number of times to the CAN-B module, where "n" is the value of TXCOUNT.
    //! CAN-B module is setup to trigger an interrupt service routine (ISR) when
    //! data is received. An error flag will be set if the transmitted data doesn't
    //! match the received data.
    //!
    //! \note Both CAN modules on the device need to be
    //!       connected to each other via CAN transceivers.
    //!
    //! \b Hardware \b Required \n
    //!  - A C2000 board with two CAN transceivers
    //!
    //! \b External \b Connections \n
    //!  - ControlCARD CANA is on GPIO31 (CANTXA) and GPIO30 (CANRXA)
    //!  - ControlCARD CANB is on GPIO8 (CANTXB) and GPIO10 (CANRXB)
    //!
    //! \b Watch \b Variables \n
    //!  - TXCOUNT - Adjust to set the number of messages to be transmitted
    //!  - txMsgCount - A counter for the number of messages sent
    //!  - rxMsgCount - A counter for the number of messages received
    //!  - txMsgData - An array with the data being sent
    //!  - rxMsgData - An array with the data that was received
    //!  - errorFlag - A flag that indicates an error has occurred
    //!
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v3.07.00.00 $
    // $Release Date: Sun Sep 29 07:34:54 CDT 2019 $
    // $Copyright:
    // Copyright (C) 2013-2019 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"     // Device Headerfile and Examples Include File
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_can.h"
    #include "driverlib/can.h"
    /*VVDN*/
    #include "driverlib/rom_map.h"
    //#include "F2837xD_Gpio_defines.h"
    #include "gpio.h"
    #include "pin_map.h"
    //
    //
    // Defines
    //
    
    #define MSG_DATA_LENGTH    4
    
    #define RX_MSG_OBJ_ID    1
    
    //
    // Globals
    //
    volatile unsigned long i;
    
    volatile uint32_t rxMsgCount = 0;
    volatile uint32_t errorFlag = 0;
    
    unsigned char rxMsgData[4];
    
    tCANMsgObject sRXCANMessage;
    
    //
    // Function Prototypes
    //
    __interrupt void canbISR(void);
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        //
        InitSysCtrl();
    
        //
        // Initialize GPIO and configure GPIO pins for CANTX/CANRX
        // on module A and B
        //
        InitGpio();
    
        //
        // Setup GPIO pin mux for CAN-A TX/RX and CAN-B TX/RX
        //
    #if 0
        GPIO_SetupPinMux(17, GPIO_MUX_CPU1, 2); //GPIO30 -  CANRXA
        GPIO_SetupPinOptions(17, GPIO_INPUT, GPIO_ASYNC);
        GPIO_SetupPinMux(12, GPIO_MUX_CPU1, 2); //GPIO31 - CANTXA
        GPIO_SetupPinOptions(12, GPIO_OUTPUT, GPIO_PUSHPULL);
    #endif
    
        GPIO_SetupPinMux(7, GPIO_MUX_CPU1, 6); //GPIO30 -  CANRXA
            GPIO_SetupPinOptions(7, GPIO_INPUT, GPIO_ASYNC);
            GPIO_SetupPinMux(6, GPIO_MUX_CPU1, 6); //GPIO31 - CANTXA
            GPIO_SetupPinOptions(6, GPIO_OUTPUT, GPIO_PUSHPULL);
            /*VVDN - to enable can_stb and can_en pins of can transceiver respectively */
                        GPIO_setMasterCore(77, GPIO_CORE_CPU1);
                        GPIO_setPinConfig(GPIO_77_GPIO77);
                        GPIO_setPadConfig(77, GPIO_PIN_TYPE_PULLUP);
                        GPIO_setQualificationMode(77, GPIO_QUAL_ASYNC); /*J1 connector = pin 3 */
                        GPIO_setDirectionMode(77, GPIO_DIR_MODE_OUT);
                        GPIO_WritePin(77,1);
    
                        Uint16 value = GPIO_ReadPin(77);
    
                        GPIO_setMasterCore(79, GPIO_CORE_CPU1);
                        GPIO_setPinConfig(GPIO_79_GPIO79);
                        GPIO_setPadConfig(79, GPIO_PIN_TYPE_PULLUP); /*J1 connector  pin 4 */
                        GPIO_setQualificationMode(79, GPIO_QUAL_ASYNC);
                        GPIO_setDirectionMode(79, GPIO_DIR_MODE_OUT);
                        GPIO_WritePin(79,1);
                       value = GPIO_ReadPin(79);
        //
        // Initialize the CAN controllers
        //
        CANInit(CANB_BASE);
    
    
        //
        // Setup CAN to be clocked off the PLL output clock
        //
        CANClkSourceSelect(CANB_BASE, 0);   // 500kHz CAN-Clock
           // 500kHz CAN-Clock
    
        //
        // Set up the CAN bus bit rate to 500kHz for each module
        // This function sets up the CAN bus timing for a nominal configuration.
        // You can achieve more control over the CAN bus timing by using the
        // function CANBitTimingSet() instead of this one, if needed.
        // Additionally, consult the device data sheet for more information about
        // the CAN module clocking.
        //
        CANBitRateSet(CANB_BASE, 200000000, 500000);
    
        //
        // Enable interrupts on the CAN B peripheral.
        //
        CANIntEnable(CANB_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        //
        // 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.
        //
        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.
        //
        InitPieVectTable();
    
        //
        // 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.
        //
        EALLOW;
        PieVectTable.CANB0_INT = canbISR;
        EDIS;
    
        //
        // Enable the CAN-B interrupt on the processor (PIE).
        //
        PieCtrlRegs.PIEIER9.bit.INTx7 = 1;
        IER |= M_INT9;
        EINT;
    
        //
        // Enable the CAN-B interrupt signal
        //
        CANGlobalIntEnable(CANB_BASE, CAN_GLB_INT_CANINT0);
    
    
    
        //
        // Initialize the receive message object used for receiving CAN messages.
        // Message Object Parameters:
        //      Message Identifier: 0x5555
        //      Message ID Mask: 0x0
        //      Message Object Flags: Receive Interrupt
        //      Message Data Length: 4 Bytes
        //      Message Receive data: rxMsgData
        //
        sRXCANMessage.ui32MsgID = 0x5555;
        sRXCANMessage.ui32MsgIDMask = 0;
        sRXCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE;
        sRXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
        sRXCANMessage.pucMsgData = rxMsgData;
        CANMessageSet(CANB_BASE, RX_MSG_OBJ_ID, &sRXCANMessage,
                      MSG_OBJ_TYPE_RX);
    
        // Start CAN module A and B operations
        //
        CANEnable(CANB_BASE);
        while(1){
            DELAY_US(4200*250);
       }
    
    
        //
        // Stop application
        //
        asm("   ESTOP0");
    }
    
    //
    // CAN B ISR - The interrupt service routine called when a CAN interrupt is
    //             triggered on CAN module B.
    //
    __interrupt void
    canbISR(void)
    {
        uint32_t status;
    
        //
        // Read the CAN-B interrupt status to find the cause of the interrupt
        //
        status = CANIntStatus(CANB_BASE, CAN_INT_STS_CAUSE);
    
        //
        // 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 = CANStatusGet(CANB_BASE, CAN_STS_CONTROL);
    
            //
            // Check to see if an error occurred.
            //
            if(((status  & ~(CAN_ES_RXOK)) != 7) &&
               ((status  & ~(CAN_ES_RXOK)) != 0))
            {
                //
                // Set a flag to indicate some errors may have occurred.
                //
                errorFlag = 1;
            }
        }
        //
        // Check if the cause is the CAN-B receive message object 1
        //
        else if(status == RX_MSG_OBJ_ID)
        {
            //
            // Get the received message
            //
            CANMessageGet(CANB_BASE, RX_MSG_OBJ_ID, &sRXCANMessage, true);
    
            //
            // Getting to this point means that the RX interrupt occurred on
            // message object 1, and the message RX is complete.  Clear the
            // message object interrupt.
            //
            CANIntClear(CANB_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++;
    
            //
            // Since the message was received, clear any error flags.
            //
            errorFlag = 0;
        }
        //
        // 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
        //
        CANGlobalIntClear(CANB_BASE, CAN_GLB_INT_CANINT0);
    
        //
        // Acknowledge this interrupt located in group 9
        //
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
    }
    
    //
    // End of File
    //
    
    
    //###########################################################################
    //
    // FILE:   can_external_transmit.c
    //
    // TITLE:  Example to demonstrate CAN external transmission
    //
    //! \addtogroup cpu01_example_list
    //! <h1>CAN-A to CAN-B External Transmit (can_external_transmit)</h1>
    //!
    //! This example initializes CAN module A and CAN module B for external
    //! communication. CAN-A module is setup to transmit incrementing data for "n"
    //! number of times to the CAN-B module, where "n" is the value of TXCOUNT.
    //! CAN-B module is setup to trigger an interrupt service routine (ISR) when
    //! data is received. An error flag will be set if the transmitted data doesn't
    //! match the received data.
    //!
    //! \note Both CAN modules on the device need to be
    //!       connected to each other via CAN transceivers.
    //!
    //! \b Hardware \b Required \n
    //!  - A C2000 board with two CAN transceivers
    //!
    //! \b External \b Connections \n
    //!  - ControlCARD CANA is on GPIO31 (CANTXA) and GPIO30 (CANRXA)
    //!  - ControlCARD CANB is on GPIO8 (CANTXB) and GPIO10 (CANRXB)
    //!
    //! \b Watch \b Variables \n
    //!  - TXCOUNT - Adjust to set the number of messages to be transmitted
    //!  - txMsgCount - A counter for the number of messages sent
    //!  - rxMsgCount - A counter for the number of messages received
    //!  - txMsgData - An array with the data being sent
    //!  - rxMsgData - An array with the data that was received
    //!  - errorFlag - A flag that indicates an error has occurred
    //!
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v3.07.00.00 $
    // $Release Date: Sun Sep 29 07:34:54 CDT 2019 $
    // $Copyright:
    // Copyright (C) 2013-2019 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"     // Device Headerfile and Examples Include File
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_can.h"
    #include "driverlib/can.h"
    /*VVDN*/
    #include "driverlib/rom_map.h"
    //#include "F2837xD_Gpio_defines.h"
    #include "gpio.h"
    #include "pin_map.h"
    //
    //
    // Defines
    //
    
    #define MSG_DATA_LENGTH    4
    #define TX_MSG_OBJ_ID    1
    
    
    //
    // Globals
    //
    volatile unsigned long i;
    volatile uint32_t txMsgCount = 0;
    
    volatile uint32_t errorFlag = 0;
    unsigned char txMsgData[4];
    
    tCANMsgObject sTXCANMessage;
    
    
    //
    // Function Prototypes
    //
    
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        //
        InitSysCtrl();
    
        //
        // Initialize GPIO and configure GPIO pins for CANTX/CANRX
        // on module A and B
        //
        InitGpio();
    
        //
        // Setup GPIO pin mux for CAN-A TX/RX and CAN-B TX/RX
        //
        GPIO_SetupPinMux(7, GPIO_MUX_CPU1, 6); //GPIO30 -  CANRXA
        GPIO_SetupPinOptions(7, GPIO_INPUT, GPIO_ASYNC);
        GPIO_SetupPinMux(6, GPIO_MUX_CPU1, 6); //GPIO31 - CANTXA
        GPIO_SetupPinOptions(6, GPIO_OUTPUT, GPIO_PUSHPULL);
        /*VVDN - to enable can_stb and can_en pins of can transceiver respectively */
                    GPIO_setMasterCore(77, GPIO_CORE_CPU1);
                    GPIO_setPinConfig(GPIO_77_GPIO77);
                    GPIO_setPadConfig(77, GPIO_PIN_TYPE_PULLUP);
                    GPIO_setQualificationMode(77, GPIO_QUAL_ASYNC); /*J1 connector = pin 3 */
                    GPIO_setDirectionMode(77, GPIO_DIR_MODE_OUT);
                    GPIO_WritePin(77,1);
    
                    Uint16 value = GPIO_ReadPin(77);
    
                    GPIO_setMasterCore(79, GPIO_CORE_CPU1);
                    GPIO_setPinConfig(GPIO_79_GPIO79);
                    GPIO_setPadConfig(79, GPIO_PIN_TYPE_PULLUP); /*J1 connector  pin 4 */
                    GPIO_setQualificationMode(79, GPIO_QUAL_ASYNC);
                    GPIO_setDirectionMode(79, GPIO_DIR_MODE_OUT);
                    GPIO_WritePin(79,1);
                   value = GPIO_ReadPin(79);
    
        //
        // Initialize the CAN controllers
        //
        CANInit(CANB_BASE);
    
        //
        // Setup CAN to be clocked off the PLL output clock
        //
         // 500kHz CAN-Clock
        CANClkSourceSelect(CANB_BASE, 0);   // 500kHz CAN-Clock
    
        //
        // Set up the CAN bus bit rate to 500kHz for each module
        // This function sets up the CAN bus timing for a nominal configuration.
        // You can achieve more control over the CAN bus timing by using the
        // function CANBitTimingSet() instead of this one, if needed.
        // Additionally, consult the device data sheet for more information about
        // the CAN module clocking.
        //
    
        CANBitRateSet(CANB_BASE, 200000000, 500000);
    
        //
        // Enable interrupts on the CAN B peripheral.
        //
    
    
        //
        // 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.
        //
        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.
        //
        InitPieVectTable();
    
    
    
    
        //
        // Initialize the transmit message object used for sending CAN messages.
        // Message Object Parameters:
        //      Message Identifier: 0x5555
        //      Message ID Mask: 0x0
        //      Message Object Flags: None
        //      Message Data Length: 4 Bytes
        //      Message Transmit data: txMsgData
        //
        sTXCANMessage.ui32MsgID = 0x5555;
        sTXCANMessage.ui32MsgIDMask = 0;
        sTXCANMessage.ui32Flags = 0;
        sTXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
        sTXCANMessage.pucMsgData = txMsgData;
    
    
        //
        // Initialize the transmit message object data buffer to be sent
        //
        txMsgData[0] = 0x12;
        txMsgData[1] = 0x34;
        txMsgData[2] = 0x56;
        txMsgData[3] = 0x78;
    
        //
        // Start CAN module A and B operations
        //
    
        CANEnable(CANB_BASE);
        while(1){
                //
                // Transmit Message
                //
                CANMessageSet(CANB_BASE, TX_MSG_OBJ_ID, &sTXCANMessage,
                              MSG_OBJ_TYPE_TX);
                // Increment the value in the transmitted message data.
                        //
                        txMsgData[0] += 0x01;
                        txMsgData[1] += 0x01;
                        txMsgData[2] += 0x01;
                        txMsgData[3] += 0x01;
    
                while(((HWREGH(CANB_BASE + CAN_O_ES) & CAN_ES_TXOK)) !=  CAN_ES_TXOK){}
        }
        asm("   ESTOP0");
    
    }
    
    
    
    //
    // End of File
    //
    
    

  • Either there is a H/W issue (bus connection) or the receiver is not configured correctly. Have you read through the debug tips in my app.note (section 3)? Almost always, you will be able to find your solution there. 

    Debugging your code is not something we can support on the forum. My app.note SPRACE5 has tested examples that you can run on your H/W.