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.

eCan on F28069M

Hi,

I got the F28069M ECanBack2Back project running. It's a self  test.

I have 2 boards, and I wanted to try and run them against each other, where board 2 would read the messages transmitted by board 1, etc. To me, at least, that seemed feasible, and it would show more than the self test.

I reset the line that configured the CAN for the self test,( ECanaShadow.CANMC.bit.STM = 0 instead of = 1);    but I got no output. 

Has anyone ever tried this and achieved success? If so I would appreciate any advice relevant to this experiment.

Thanks,

Nolan

  • TI controlStick28069 doesn't have the eCAN pin output.
    Gastón
  • You cannot directly connect CANTX of node-A to CANRX of node-B and vice versa and expect successful CAN communication. In this case, CAN is unlike other serial interfaces like SCI or SPI or McBSP. For example, SCI can be made to work with a RS232 transceiver or through a direct connection. However, CAN bus always needs a CAN transceiver. (Note: One could connect multiple CANTX pins to the input of an AND gate and connect the output of the AND gate to the CANRX pins of all nodes and satisfy the ACK requirement. However, this is an atypical way of using the CAN bus and impractical when bus lengths of more than a few inches are involved). Why a transceiver is needed? In addition to converting the single-ended CAN signal for differential transmission, the transceiver also loops back the CANTX and CANRX pins of a node. This is because a CAN node needs to be able to monitor its own transmission. Why? This has to do with the ACK requirement mandated by the CAN protocol. When a node transmits a frame on the CAN bus, it expects an ACKnowledgement from at least one other node on the network. The receiving node that provides the ACK does not need to be the intended recipient of the frame, although it could very well be. When the transmitting node does not receive an ACK, it results in ACKnowledge error and it keeps re-transmitting the frame forever. In this situation, the TA bit for the transmitting mailbox does not get set at all and code will be looping there forever. No interrupts will be generated either. For the ACK phase, the transmitter puts out a 1 and expects to read back a 0.
  • Hi Hareesh,

    Thanks for the informative answer. So are you saying, basically, you cannot loop back one F28069M with another? 

    Having attempted that with no results, I believe you. I found that, as you say,  "the TA bit for the transmitting mailbox does not get set at all and code will be looping there forever. "

    But  is there not some way you can have one of these boards communicate (via eCan) with another?

    The reason for my question is the simple fact that I could find only 1 demo on eCAN, and it was just a self test. It would be nice if there were examples of the eCAN actually reading/writing in/out some data. If you know of any such, or can refer to some relevant code or documentation, I would welcome the information.

    Thanks,

    Nolan 

  • Hi Gaston,

    My question referred to the F28069M, which is the Launchpad, not the ControlStick, which is just F28069.

    I agree there is no eCAN on the F28069 ControlStick, but there is on the F28069M Launchpad.

    Thanks,

    Nolan
  • well then is like Hareesh said. You MUST use a transceiver to communicate between nodes.
    Gastón
  • Nolan,

      No. Direct connection between two CAN nodes will NOT work, for reasons mentioned earlier. If you do not want to bring in transceivers, you could try the idea in the attachment.  Once you implement the hardware connection, you could easily modify the example code that you are using for receive operation. All you need to do is to run the same code on the receiver, but disable transmission. From my earlier post: The receiving node that provides the ACK does not need to be the intended recipient of the frame, although it could very well be. In other words, you just need another node configured for the same bit-rate. Once you do this , the receiver would automatically ACKnowledge the frames WITHOUT any code intervention.

  • Hareesh,

    Attachment? I did not receive any attachment on this.

    Could you please explain this drawing in words? I am a software guy, not a EE.

    The only pins I can see on the board are the CAN HI and CAN LO pins. Are there separate TX and RX pins?

    Thank you,
    Nolan
  • Nolan,
    Realized you are using the Launchpad which already has the CAN transceiver. All you need to do is to connect the CANH pins of the two boards together and likewise the CANL pins and you will be all set.
  • HI Hareesh,

    Thank you.

    I did that- wrapped them around, Ho to Hi, Lo to LO. I also turned off the self test feature in the ecan_back2back project by the following line.

    ECanaShadow.CANMC.bit.STM = 0; // De-configure CAN for self-test mode

    No joy there. It could not get by the statement:

    while(ECanaRegs.CANTA.all != 0x0000FFFF ) {} // Wait for all TAn bits to be set.

    Do I have to set up one board as the transmitter, and the other as the receiver? That's what I want to do anyway, but TI has no demos of anything like that.

    Regards,
    Nolan
  • Since you got the code running in self-test mode, I am not tempted to suspect the code. You have correctly disabled the self-test mode on the transmitting node. If you run the same code on the receiving node, that is all it should take (of course, you need to comment out the line that initiates the transmit. Any node is capable of transmitting or receiving. There is no special configuration for a "transmitter" or "receiver". You simply need to connect the nodes together and ensure the termination resistor is present on either end of the bus (the 120-ohm resistor should be part of the launch pad). Please scope the CANTX pin on the transmitting node. See if the ACK bit is driven low by the receiver. If you scope the signal from start-to-finish, you will be able to debug this in a matter of minutes.

  • Nolan,
    All CAN nodes are capable of both transmitting and receiving. No special configuration needed to make a node a “transmitter” or a “receiver”. Better to use the terms “transmitting node” and “receiving node” as opposed to “transmitter” and “receiver”. You have already succeeded in getting the program to work in self-test mode. So, the code cannot be drastically wrong. You could run the same code on the receiving node (but remember to comment out the line that initiates the transmit and the line that puts the node in self-test mode). Running the same code on either nodes would ensure that the bit rate is identical (assuming you are using two identical Launchpads). Use an oscilloscope to probe the CANRX pin of the transmitting node and see if the ACK bit is being driven low. I suspect it is not. If so, start moving from the CANTX pin , and then on to the CANRX pin of the receiving node and ensure the waveforms are identical at both pins. The only difference should be in the ACK phase where the transmitting node outputs a 1 and the receiving node puts out a 0. All the best.
  • Hareesh,

    Thank you. I am talking about modifying ecan_back2back so that one node transmits and the other just receives. By "commenting out the line that initiates the transmit" I assume you mean the following line? (Unless there are other lines I also need to comment out?)

    //ECanaRegs.CANTRS.all = 0x0000FFFF; // Set TRS for all transmit mailboxes

    I do that, and of course I turn off self test on both nodes by:

    EALLOW;
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.STM = 0; // De-configure CAN for self-test mode
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    EDIS;

    The setup is wrapped around as specified. So the code is basically identical for the transmitting and receiving node, except the receiving node has the transmit turned off.

    But the problem remains, it never gets by the following line in the receiving node:

    while(ECanaRegs.CANTA.all != 0x0000FFFF ) {} // Wait for all TAn bits to be set.

    This appears to be a historical problem. Numerous people have described it, but no-one has ever, to my knowledge, reported it being solved. One person did say it worked for "older" code versions but I need it to work for the current builds.

    Yes I am sure one could see this issue on a scope, but I need to fix it in software.

    Any thoughts?

    For completeness I just attaching the code for the receiver node at the end of this note, in case my brief description is insufficient.

    Regards,
    Nolan

    //###########################################################################
    // Description:
    //! \addtogroup f2806x_example_list
    //! <h1>eCAN back to back (ecan_back2back)</h1>
    //!
    //! This example tests eCAN by transmitting data back-to-back at high speed
    //! without stopping. The received data is verified. Any error is flagged.
    //! MBX0 transmits to MBX16, MBX1 transmits to MBX17 and so on....
    //! This program illustrates the use of self-test mode
    //!
    //! \b Watch \b Variables \n
    //! - PassCount
    //! - ErrorCount
    //! - MessageReceivedCount
    //
    //
    //###########################################################################
    // $TI Release: F2806x C/C++ Header Files and Peripheral Examples V141 $
    // $Release Date: January 19, 2015 $
    // $Copyright: Copyright (C) 2011-2015 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################

    #include "DSP28x_Project.h" // Device Headerfile and Examples Include File

    // Prototype statements for functions found within this file.
    void mailbox_check(int32 T1, int32 T2, int32 T3);
    void mailbox_read(int16 i);

    // Global variable for this example
    Uint32 ErrorCount;
    Uint32 PassCount;
    Uint32 MessageReceivedCount;
    Uint32 ictr;
    Uint16 cycleCount = 0;
    Uint32 TestMbox1 = 0;
    Uint32 TestMbox2 = 0;
    Uint32 TestMbox3 = 0;

    void heartbeat()
    { //the cpu0 interrupt provided to demo life as well as anything else one wants to add for that rate
    //the interrupt (with internal clock) has "approximately" a 1 msec period
    //static Uint16 cycleCount = 0;
    int j;
    if(CpuTimer0Regs.TCR.bit.TIF == 1)
    {
    CpuTimer0Regs.TCR.bit.TIF = 1; // clear flag

    if(cycleCount= 1000) // approximately 1 sec
    {
    GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; //Toggle GPIO34 (LD2) to show life
    GpioDataRegs.GPBTOGGLE.bit.GPIO39 = 1; //Toggle GPIO39 (LD2) to show life
    cycleCount=0;
    }
    else cycleCount ++;
    }
    }

    void main(void)
    {


    Uint16 j;

    // eCAN control registers require read/write access using 32-bits. Thus we
    // will create a set of shadow registers for this example. These shadow
    // registers will be used to make sure the access is 32-bits and not 16.
    struct ECAN_REGS ECanaShadow;

    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2806x_SysCtrl.c file.
    InitSysCtrl();

    // Step 2. Initalize GPIO:
    // This example function is found in the F2806x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    // InitGpio(); // Skipped for this example

    // For this example, configure CAN pins using GPIO regs here
    // This function is found in F2806x_ECan.c
    InitECanGpio();

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

    // Initialize 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 F2806x_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 F2806x_DefaultIsr.c.
    // This function is found in F2806x_PieVect.c.
    InitPieVectTable();

    // Step 4. Initialize all the Device Peripherals:
    // This function is found in F2806x_InitPeripherals.c
    // InitPeripherals(); // Not required for this example

    // Step 5. User specific code, enable interrupts:

    MessageReceivedCount = 0;
    ErrorCount = 0;
    PassCount = 0;

    InitECana(); // Initialize eCAN-A module

    // Mailboxs can be written to 16-bits or 32-bits at a time
    // Write to the MSGID field of TRANSMIT mailboxes MBOX0 - 15
    ECanaMboxes.MBOX0.MSGID.all = 0x9555AAA0;
    ECanaMboxes.MBOX1.MSGID.all = 0x9555AAA1;
    ECanaMboxes.MBOX2.MSGID.all = 0x9555AAA2;
    ECanaMboxes.MBOX3.MSGID.all = 0x9555AAA3;
    ECanaMboxes.MBOX4.MSGID.all = 0x9555AAA4;
    ECanaMboxes.MBOX5.MSGID.all = 0x9555AAA5;
    ECanaMboxes.MBOX6.MSGID.all = 0x9555AAA6;
    ECanaMboxes.MBOX7.MSGID.all = 0x9555AAA7;
    ECanaMboxes.MBOX8.MSGID.all = 0x9555AAA8;
    ECanaMboxes.MBOX9.MSGID.all = 0x9555AAA9;
    ECanaMboxes.MBOX10.MSGID.all = 0x9555AAAA;
    ECanaMboxes.MBOX11.MSGID.all = 0x9555AAAB;
    ECanaMboxes.MBOX12.MSGID.all = 0x9555AAAC;
    ECanaMboxes.MBOX13.MSGID.all = 0x9555AAAD;
    ECanaMboxes.MBOX14.MSGID.all = 0x9555AAAE;
    ECanaMboxes.MBOX15.MSGID.all = 0x9555AAAF;

    // Write to the MSGID field of RECEIVE mailboxes MBOX16 - 31
    ECanaMboxes.MBOX16.MSGID.all = 0x9555AAA0;
    ECanaMboxes.MBOX17.MSGID.all = 0x9555AAA1;
    ECanaMboxes.MBOX18.MSGID.all = 0x9555AAA2;
    ECanaMboxes.MBOX19.MSGID.all = 0x9555AAA3;
    ECanaMboxes.MBOX20.MSGID.all = 0x9555AAA4;
    ECanaMboxes.MBOX21.MSGID.all = 0x9555AAA5;
    ECanaMboxes.MBOX22.MSGID.all = 0x9555AAA6;
    ECanaMboxes.MBOX23.MSGID.all = 0x9555AAA7;
    ECanaMboxes.MBOX24.MSGID.all = 0x9555AAA8;
    ECanaMboxes.MBOX25.MSGID.all = 0x9555AAA9;
    ECanaMboxes.MBOX26.MSGID.all = 0x9555AAAA;
    ECanaMboxes.MBOX27.MSGID.all = 0x9555AAAB;
    ECanaMboxes.MBOX28.MSGID.all = 0x9555AAAC;
    ECanaMboxes.MBOX29.MSGID.all = 0x9555AAAD;
    ECanaMboxes.MBOX30.MSGID.all = 0x9555AAAE;
    ECanaMboxes.MBOX31.MSGID.all = 0x9555AAAF;

    // Configure Mailboxes 0-15 as Tx, 16-31 as Rx
    // Since this write is to the entire register (instead of a bit
    // field) a shadow register is not required.
    ECanaRegs.CANMD.all = 0xFFFF0000;

    // Enable all Mailboxes */
    // Since this write is to the entire register (instead of a bit
    // field) a shadow register is not required.
    ECanaRegs.CANME.all = 0xFFFFFFFF;

    // Specify that 8 bits will be sent/received
    ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX2.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX3.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX4.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX5.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX6.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX7.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX8.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX9.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX10.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX11.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX12.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX13.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX14.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX15.MSGCTRL.bit.DLC = 8;

    // Write to the mailbox RAM field of MBOX0 - 15
    ECanaMboxes.MBOX0.MDL.all = 0x9555AAA0;
    ECanaMboxes.MBOX0.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX1.MDL.all = 0x9555AAA1;
    ECanaMboxes.MBOX1.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX2.MDL.all = 0x9555AAA2;
    ECanaMboxes.MBOX2.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX3.MDL.all = 0x9555AAA3;
    ECanaMboxes.MBOX3.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX4.MDL.all = 0x9555AAA4;
    ECanaMboxes.MBOX4.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX5.MDL.all = 0x9555AAA5;
    ECanaMboxes.MBOX5.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX6.MDL.all = 0x9555AAA6;
    ECanaMboxes.MBOX6.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX7.MDL.all = 0x9555AAA7;
    ECanaMboxes.MBOX7.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX8.MDL.all = 0x9555AAA8;
    ECanaMboxes.MBOX8.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX9.MDL.all = 0x9555AAA9;
    ECanaMboxes.MBOX9.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX10.MDL.all = 0x9555AAAA;
    ECanaMboxes.MBOX10.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX11.MDL.all = 0x9555AAAB;
    ECanaMboxes.MBOX11.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX12.MDL.all = 0x9555AAAC;
    ECanaMboxes.MBOX12.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX13.MDL.all = 0x9555AAAD;
    ECanaMboxes.MBOX13.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX14.MDL.all = 0x9555AAAE;
    ECanaMboxes.MBOX14.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX15.MDL.all = 0x9555AAAF;
    ECanaMboxes.MBOX15.MDH.all = 0x89ABCDEF;

    // Since this write is to the entire register (instead of a bit
    // field) a shadow register is not required.
    EALLOW;
    ECanaRegs.CANMIM.all = 0xFFFFFFFF;

    // Configure the eCAN for self test mode
    // Enable the enhanced features of the eCAN.

    EALLOW;
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    //ECanaShadow.CANMC.bit.STM = 1; // Configure CAN for self-test mode //nolan
    ECanaShadow.CANMC.bit.STM = 0; // De-configure CAN for self-test mode

    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    EDIS;

    // Begin transmitting
    for(;;)
    {
    //ECanaRegs.CANTRS.all = 0x0000FFFF; // Set TRS for all transmit mailboxes
    while(ECanaRegs.CANTA.all != 0x0000FFFF ) {} // Wait for all TAn bits to be set.. // IT STOPS HERE..............
    ECanaRegs.CANTA.all = 0x0000FFFF; // Clear all TAn
    MessageReceivedCount++;

    //Read from Receive mailboxes and begin checking for data
    for(j=16; j<32; j++) // Read & check 16 mailboxes
    {
    mailbox_read(j); // This func reads the indicated mailbox data
    mailbox_check(TestMbox1,TestMbox2,TestMbox3); // Checks the received data
    }

    heartbeat();
    }
    }

    // This function reads out the contents of the indicated
    // by the Mailbox number (MBXnbr).
    void mailbox_read(int16 MBXnbr)
    {
    volatile struct MBOX *Mailbox;
    Mailbox = &ECanaMboxes.MBOX0 + MBXnbr;
    TestMbox1 = Mailbox->MDL.all; // = 0x9555AAAn (n is the MBX number) 9555AAA1
    TestMbox2 = Mailbox->MDH.all; // = 0x89ABCDEF (a constant)
    TestMbox3 = Mailbox->MSGID.all;// = 0x9555AAAn (n is the MBX number)

    } // MSGID of a rcv MBX is transmitted as the MDL data.

    void mailbox_check(int32 T1, int32 T2, int32 T3)
    {
    if((T1 != T3) || ( T2 != 0x89ABCDEF))
    {
    ErrorCount++;
    }
    else
    {
    PassCount++;
    }
    }

    //===========================================================================
    // No more.
    //===========================================================================
  • Nolan,

     Let us take the debug offline until we find the resolution. I have sent you an email. Please respond to it.

  • Hareesh,

    Good idea. The discussion was getting pretty detailed.

    I did not receive any email though.

    Regards,

    Nolan

  • Hareesh,

    Thank you. I got everything working fine now. Bascially I found out to try use the ecan back2back program for 2 nodes, versus checkout on one node, you had to use 2 boards on 2 separate computers. Having 2 boards hanging off one computer confused the debugger t seems.

    Regards,
    Nolan
  • Hi Nolan,

    I think I met similar problem with you. It works well when 1 F28069 work in back2back mode, but failed when 2 F28069 communicate with each other.
    I modified ECanaShadow.CANMC.bit.STM = 0, and the code can't jump out of the while loop
    while(ECanaRegs.CANTA.all != 0x0000FFFF ) {} // Wait for all TAn bits to be set.

    Could you pls kindly let me know what I need to pay attention to, or any other code I need to modify?