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.

TMS320F28388D: CAN_setupMessageObject Configuration

Part Number: TMS320F28388D
Other Parts Discussed in Thread: C2000WARE

Hello everyone,

I have to use a CAN communication between 2 devices, one of these is not a texas microcontroller. I found an example on how to use it but I have a question about setting the receive message objects. 

The fact is that I can receive messages with not only one messageID but with multiple messageID, approximately 20. Do I have to use the CAN_setupMessageObject() function for each message ID that I can receive.

I don't really understand the role of this function. If I receive a message with a messageID that I did not log with this function, will I be able to read it ?

Thanks for your explanations !

Nathan

  • Nathan,

                  You could either dedicate a mailbox (message object) to receive each one of the 20 MSGIDs or you could use filtering and choose to receive all 20 MSGIDs in the same mailbox. Please download my Application report http://www.ti.com/lit/sprace5. It has an example that demonstrates filtering. I also strongly urge you to look at the Debug tips provided.

    Application report http://www.ti.com/lit/spracq3 depicts lot of easy to understand waveforms and also provide a tool to introduce error at a chosen bit location. 

    The TRM chapter explains the CAN protocol implementation in the MCU. i.e. it explains the function of registers/bits. However, it does not explain the protocol itself. For protocol information, refer to these excellent videos:

    https://training.ti.com/ti-precision-labs-canlinsbc-can-and-can-fd-protocol?context=1139747-1138099-1139707-1138111

    https://training.ti.com/ti-precision-labs-canlinsbc-can-and-can-fd-overview?context=1139747-1138099-1139707-1138109

    https://training.ti.com/ti-precision-labs-canlinsbc-can-physical-layer?context=1139747-1138099-1139707-1138110    

  • Thank you for your answer !

    My problem is not with the waveforms or the frames themselves, but with the programm and the functions to use, and how to use them.

    If I want to dedicate a mailbox for each messageID I can receive, I have to use 20 times the function Can_SetupMessageObject(), each time with a different messageID ? Is that true ?

    Another problem that I have is that I have to read the RTR bit when I receive a message. I see that there is 2 functions to read messages : CAN_readMessage() and CAN_readMessageWithID() but none give me the RTR bit. How can I read this bit ?

    Thanks in advance,

    Nathan

  • My problem is not with the waveforms or the frames themselves, but with the programm and the functions to use, and how to use them.

    I am aware. I just pointed to those helpful resources to enhance your understanding of the protocol.

    If I want to dedicate a mailbox for each messageID I can receive, I have to use 20 times the function Can_SetupMessageObject(), each time with a different messageID ? Is that true ?

    Yes. 

    Another problem that I have is that I have to read the RTR bit when I receive a message. I see that there is 2 functions to read messages : CAN_readMessage() and CAN_readMessageWithID() but none give me the RTR bit. How can I read this bit ?

    Why do you have to "read" the RTR bit? If a remote frame is received, transmission of the corresponding data frame is automatic. 

    Once again, Please download my Application report http://www.ti.com/lit/sprace5. There is an example that shows how to use remote frames.

  • It's correct, I don't need to read the RTR bit.

    I did the configuration of the answer when a remote frame is received but it does not work. Here are the few lines :

    In the configuration:

    CAN_setupMessageObject(CANA_BASE, 8, RX_REQUEST_STATE+NODE_ID, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RXTX_REMOTE, 0, CAN_MSG_OBJ_NO_FLAGS, MSG_DATA_LENGTH);

    In the endless loop :

    //
    // Copy data into the mailbox1 RAM of CAN-A. This is the data that will be
    // automatically transmitted in response to a remote frame.
    //
    // Wait for busy bit to clear
    //
    while((HWREGH(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) ==CAN_IF1CMD_BUSY)
    {
    }

    //
    // Write to IF1DATA & IF1DATB registers
    //
    HWREG_BP(CANB_BASE + CAN_O_IF1DATA) = 0x67452301UL;
    HWREG_BP(CANB_BASE + CAN_O_IF1DATB) = 0xEFCDAB89UL;

    //
    // Transfer to MBX RAM
    //
    HWREG_BP(CANA_BASE + CAN_O_IF1CMD) = 0x00830001UL;

    //
    // Wait for busy bit to clear
    //
    while((HWREGH(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
    {
    }


    When I test it I can see the answer. The message identifier is 0x701 (it's correct, it correspond with RX_REQUEST_STATE+NODE_ID) but the data is zero for each bytes. 

    An idea why ?

  • Please try the tested example for remote frames in SPRACE5 and compare it with your code.

  • Yes this is exactly what I did. As you can see in my code I tested with the same values but the sent data is 0x00 for each byte

  • Please use the C2000ware example as the base and modify it as needed for your application in progressive steps. You should be able to catch exactly where it fails. 

  • I'm based on this example (can_ex8_remote_tx.c) but I have to change some things to make it work. For example I can't use CANB module but only CANA. I don't thinks there is big changes but it doesn't work. My code is very simple and the same as the example. Here are the 2 codes (CM and CPU1):

    //###########################################################################
    //
    // FILE:   enet_lwip.c
    //
    // TITLE:  lwIP based Ethernet Example.
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright: $
    //###########################################################################
    
    #include <string.h>
    
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_types.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_emac.h"
    
    #include "driverlib_cm/gpio.h"
    #include "driverlib_cm/interrupt.h"
    
    #include "driverlib_cm/sysctl.h"
    #include "driverlib_cm/systick.h"
    
    #include "cm.h"
    
    #include "mCan.h"
    
    #include "SharedMemory.h"
    #include "objectDictionnary.h"
    #include "aMailBox.h"
    #include "aInput.h"
    #include "aCompute.h"
    #include "aOutput.h"
    
    #include <ipc.h>
    
    
    // These are defined by the linker (see device linker command file)
    extern uint16_t RamfuncsLoadStart;
    extern uint16_t RamfuncsLoadSize;
    extern uint16_t RamfuncsRunStart;
    extern uint16_t RamfuncsLoadEnd;
    extern uint16_t RamfuncsRunEnd;
    extern uint16_t RamfuncsRunSize;
    
    extern uint16_t constLoadStart;
    extern uint16_t constLoadEnd;
    extern uint16_t constLoadSize;
    extern uint16_t constRunStart;
    extern uint16_t constRunEnd;
    extern uint16_t constRunSize;
    
    
    void CM_init(void)
    {
        //
        // Disable the watchdog
        //
        SysCtl_disableWatchdog();
    
    #ifdef _FLASH
        //
        // Copy time critical code and flash setup code to RAM. This includes the
        // following functions: InitFlash();
        //
        // The RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart symbols
        // are created by the linker. Refer to the device .cmd file.
        // Html pages are also being copied from flash to ram.
        //
        memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
        memcpy(&constRunStart, &constLoadStart, (size_t)&constLoadSize);
        //
        // Call Flash Initialization to setup flash waitstates. This function must
        // reside in RAM.
        //
        Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
    #endif
    
        //
        // Turn on peripherals
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_UART0);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SSI0);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_I2C0);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_USB);
    
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ENET);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ECAT);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CAN_A);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CAN_B);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_MCAN_A);
    
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER0);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER1);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER2);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_UDMA);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_AESIP);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_GCRC);
    
        //
        // Sets the NVIC vector table offset address.
        //
    #ifdef _FLASH
        Interrupt_setVectorTableOffset((uint32_t)vectorTableFlash);
    #else
        Interrupt_setVectorTableOffset((uint32_t)vectorTableRAM);
    #endif
    
    }
    
    uint16_t rxMsgData[8];
    
    //*****************************************************************************
    int main(void)
    {
        //
        // Initializing the CM. Loading the required functions to SRAM.
        //
        CM_init();
    
        //
        // 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, CM_CLK_FREQ, 125000, 16);
    
        CAN_disableRetry(CANA_BASE);
    
        CAN_enableTestMode(CANA_BASE, CAN_TEST_EXL);
    
        CAN_setupMessageObject(CANA_BASE, 1, 0x701, CAN_MSG_FRAME_STD,
                               CAN_MSG_OBJ_TYPE_TX_REMOTE, 0, CAN_MSG_OBJ_NO_FLAGS,
                               0);
    
        CAN_setupMessageObject(CANA_BASE, 8, 0x701, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RXTX_REMOTE, 0, CAN_MSG_OBJ_NO_FLAGS, 8);
    
        rxMsgData[0] = 0;
        rxMsgData[1] = 0;
        rxMsgData[2] = 0;
        rxMsgData[3] = 0;
        rxMsgData[4] = 0;
        rxMsgData[5] = 0;
        rxMsgData[6] = 0;
        rxMsgData[7] = 0;
    
        CAN_startModule(CANA_BASE);
    
        //
        // Copy data into the mailbox1 RAM of CAN-A. This is the data that will be
        // automatically transmitted in response to  a remote frame.
        //
        // Wait for busy bit to clear
        //
        while((HWREGH(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) ==
              CAN_IF1CMD_BUSY)
        {
        }
    
        //
        // Write to IF1DATA & IF1DATB registers
        //
        HWREG_BP(CANA_BASE + CAN_O_IF1DATA)  =  0x67452301UL;
        HWREG_BP(CANA_BASE + CAN_O_IF1DATB)  =  0xEFCDAB89UL;
    
        //
        // Transfer to MBX RAM
        //
        HWREG_BP(CANA_BASE + CAN_O_IF1CMD)  =  0x00830001UL;
    
        //
        // Wait for busy bit to clear
        //
        while((HWREGH(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) ==
               CAN_IF1CMD_BUSY)
        {
        }
    
        //
        // Loop forever. All the work is done in interrupt handlers.
        //
        while(1)
        {
            CAN_sendMessage(CANA_BASE, 1, 0, rxMsgData);
    
            DEVICE_DELAY_US(2000000);
        }
    }
    
    
    
    
     
    //
    
    /**
     * main.c
     */
    #include "device.h"
    #include "driverlib.h"
    
    #define IPC_FLAGDEVICE_INITDONE 1
    
    void CanA_Config();
    // void Tim2_Config(void);
    
    
    void main(void)
    {
        Device_init();
        Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
    
        Device_initGPIO();
    
        CanA_Config();
    
        Interrupt_initModule();
        Interrupt_initVectorTable();
    
        MemCfg_setGSRAMMasterSel(MEMCFG_SECT_GS0, MEMCFG_GSRAMMASTER_CPU1);
        MemCfg_setGSRAMMasterSel(MEMCFG_SECT_GS1, MEMCFG_GSRAMMASTER_CPU2);
    
        DEVICE_DELAY_US(50000);
    
        EINT;
        ERTM;
    }
    
    void CanA_Config()
    {
        //
        // Configuring the GPIOs for CAN A.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
    
        //
        // Allocate Shared Peripheral CAN A to the CM Side.
        //
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_CAN_A,0x1U);
    }
    

    As you will see there is no big difference with the example. The most important difference is the configuration of Tx message. The message used to send is set as CAN_MSG_OBJ_TYPE_RX and not CAN_MSG_OBJ_TYPE_TX_REMOTE. Why ?

  • I regret I still don't understand what your issue is. Please provide a block diagram of your system. What are the two nodes? Who is transmitting the Remote frame and who is responding? What is the MSGID of the remote frame?

    If you run SPRACE5 examples "as is" does it work in your setup?

  • In that moment I don't have two nodes but only one, my microcontroller, and I use it in external loopback mode. This is the reason why I setup 2 MessageObjects, one to send the remote frame and the other to receive it. Here are the 2 setup:

    CAN_setupMessageObject(CANA_BASE, 1, 0x701, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX_REMOTE, 0, CAN_MSG_OBJ_NO_FLAGS, 0);

    CAN_setupMessageObject(CANA_BASE, 8, 0x701, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RXTX_REMOTE, 0, CAN_MSG_OBJ_NO_FLAGS, 8);

    After that I set data to answer in IF1DATA and I send the TX remote frame every 2 seconds.

    And here is what I have on CAN-H (there is an CAN transceiver on my board) : 

    We can see that the TX remote frame is sent (first problem, DLC is 8 and must be 0) with MSGID = 0x701, and there is the answer but with all data at 0 and not 0x0123456789ABCDEF.

    I can't run SPRACE5 examples "as is" because I don't have the same microcontroller

  • It could be that the module behavior is different in self-test mode. I have seen this in another device of ours where the acceptance mask filtering behavior was different in self-test mode, compared to normal mode of operation. Please try the experiment with a 2nd physical CAN node in normal operating mode (i.e. not loopback mode)

  • I tried, no change.

    Did you see something else in my code that could be a problem ?

    Thanks,

    Nathan

  • Debugging your code is not something we can support on e2e. Could you please describe your system? You have two CAN nodes that are connected to each other via transceivers? You ran the SPRACE5 examples and they didn't work?

  • I thought you could because someone already did that in one of my other threads.

    My system is easy. I only have one microcontroller on a custom board with a transceiver and I want to communicate with a custom Linux board with CAN Bus. It has a transceiver too.

    I cannot run SPRACE5 examples "as is" because I don't have the same microcontroller. But I simply copy/paste the lines for setup and use the remote frames in my main code.

  • Is the TI microcontroller transmitting the remote frame or responding to one?

  • We can see that the TX remote frame is sent (first problem, DLC is 8 and must be 0) with MSGID = 0x701, and there is the answer but with all data at 0 and not 0x0123456789ABCDEF.

  • I am afraid you didn’t answer my question.

    1. Is the TI microcontroller transmitting the remote frame?
    2. If so, are you using can_ex8_Remote_Tx.c "as is"?
    3. If not, what change did you make to that code? Did you only change the MSGID and DLC value?

     

    Remote frame is transmitted by the function below:

     

           //

           // Initiate transmission of remote frame. "rxMsgData" is "dummy"

           // No data will go out on a Remote Frame

           //

           CAN_sendMessage(CANA_BASE, TX_MSG_OBJ_ID, MSG_DATA_LENGTH, rxMsgData);

     

    DLC value is indicated by MSG_DATA_LENGTH. What is the #define value in your code?

     

    and there is the answer but with all data at 0 and not 0x0123456789ABCDEF

    I regret I cannot help you with the response from the other MCU.

    1. Yes, the picture above is the signal on CAN-H. There is 2 frames. The first one is the TX remote frame and the second one is the answer
    2. No
    3. I'm not using the example "as is" because it does not build (not the same microcontroller) but I just copy/paste in my main code. There is nothing else around. Only the copied/pasted example is running. The changes are that I only use CANA to send remote frame and also to receive it and send the answer (I'm in test mode, the device normally used to send the remote frame is at a customer so I have to test at home with test mode)

    The setup of the object sending the remote frame is as following:

    CAN_setupMessageObject(CANA_BASE, 1, 0x701, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX_REMOTE, 0, CAN_MSG_OBJ_NO_FLAGS,0);

    Some changes compared to the example

    • MSG_ID is 0x701 and not 0x111
    • msgType is CAN_MSG_OBJ_TYPE_TX_REMOTE and not CAN_MSG_OBJ_TYPE_RX, because I don't understand why a TX frame is set as RX frame (but also tested with the 2 configurations)
    • MSG_DATA_LENGTH is 0 and not 8, because there is no data in a remote frame (but also tested with the 2 configurations)

    And then, the setup of the object sending the answer is as following : 

    CAN_setupMessageObject(CANA_BASE, 8, 0x701, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RXTX_REMOTE, 0, CAN_MSG_OBJ_NO_FLAGS, 8);

    Some changes compared to the example

    • CAN peripheral is A and not B (because B is not rooted on my custom board)
    • TX_MSG_OBJ_ID is 8 and not 1
    • MSG_ID is 0x701 and not 0x111

    Note that the answer with all data to 0 is sent by my microcontroller in external_loopback test mode, and not by an external node (same case in the example)

  • In an earlier post, I had requested you to try this experiment with two different CAN nodes (NOT in self-test mode). I took your response of "I tried, no change" to mean that you did try the experiment with 2 different nodes. However, once again you are referring to test-mode in your last post. Please try the example with  setup containing two different nodes and let me know of any issues.

  • Yes, sorry for the misunderstood. I will explain clearly my situation for this problem.

    I'm working with a customer who is working on his side with the second node. We see us regularly to test the implementation we did each on our side. The last workshop day was last week and we tried the remote frame. He sent me the remote frame request and I tried to answer but without success, all the data was 0 as mentionned above. I tried to find a solution on this day and at this time I copy/paste the example, but it changed nothing. At the end of this day, the result was the same as in the picture above, I can receive the request, I can send the answer but data is 0 for each byte.

    I can't work everyday with the customer due to the coronavirus situation, this is why I'm actually working alone with external loopback test mode. The next time we work together will be when I am able to respond to the remote frame request.

    Here is why I actually can't try with another node and why I'm using test mode, but the request you did earlier (to try with another node without test mode) has been tried.

  • Hi,

    In your code you have setup Msg Obj 8 as RX TX Remote but while configuring the Remote Data using IF1CMD you used MSG NUM 1 instead of 8.

    HWREG_BP(CANA_BASE + CAN_O_IF1CMD)  =  0x00830008UL; instead of HWREG_BP(CANA_BASE + CAN_O_IF1CMD)  =  0x00830001UL;

    Regards,

    Yashwant 

  • Hello Yashwant,

    Thanks for your answer, I did this change and this is better. Now the request frame is good (DLC is 0 and not 8), but the answer frame always has the data to 0:

  • I was able to test and receive the exact data (0xDE) that was initialized in the remote frame in another receive object after remote tx request.  Please spend sometime and go through the attached project and try to understand how the 3 message objects were initialized and masks were used.can_tx_rx_remote_loopback.zip

    Regards,

    Yashwant