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.

Receiving Multiple CAN Messages



I have my CAN Mailboxes setup to receive several different CAN Messages.

One in particular (CAN ID 0x600) is transmitted in bursts of 5, so I have configured 5 mailboxes (16 to 20) to store these messages as they come in. These mailboxes are also set to be overwrite protected (ECanaRegs.CANOPC = 0x001F0000).

However, during runtime, this does not work properly. I receive the first 2 messages, and the other 3 are lost.

This is a master-slave system, where the F2812 is the slave. The master sends the 5 messages to the slave, and it responds with an acknowledge for each. I am only getting 2 responses. After a couple seconds waiting for the acknowledge, the master will retry sending the 5 messages with same results.

Has anyone experienced such issues?

  • I would either try to spread the IDs (if you have control over the master), or setup a simple CAN Rx interrupt on a single mailbox. I don't think your 5 mailboxes are being used in what you described.

    Regards,

    Samuel

  • I do have control of the master, however, this is a standard CAN protocol I am following, and the slave must be able to respond the way I've described.

    According to this paragraph of the eCAN user guide, what I am trying to do should be possible:

    If there is an overflow condition for mailbox n (RMP[ n ] is set to 1 and a new receive message would fit for mailbox n), the new message is stored depending on the settings in the CANOPC register. If the corresponding bit OPC[ n ] is set to 1, the old message is protected against being overwritten by the new message; thus, the next mailboxes are checked for a matching ID. If no other mailbox is found, the message is lost without further notification. If the bit OPC[ n ] is cleared to 0, the old message is overwritten by the new one. This is notified by setting the receive message lost bit RML[ n ].

     

     

  • Henry, your explanation is correct.  In fact I have used this sort of buffered CAN receive technique in multiple projects without any problems. So there must be something else in your project, which is not working correct.

    Here is what I do:  Initialize all your receive mailboxes (for example 5,4,3,2 and 1) with the same ID ( and sometimes also the same LAM). Set OPC for mailbox 5,4,3,2 and request an interrupt service from mailbox 1. The chip will then receive 5 messages with the same ID and store them in mailboxes 5,4,3,2 and 1 (first message in 5, last in 1). Then I use mailbox 1 interrupt service to read all 5 messages and to re-enable the 5 mailboxes.

    This technique very helpful, when you have to process CAN-Diagnostic messages (ISO 15765) in automotive. Such a message consists of 64 bytes, e.g. 8 messages.

    To help you more, I would need some more details (data rate, message repetition rate, bus load, etc. Do you see all messages, including the missing ones, in a CAN-Analyzer? 

    Regards

     

     

     

     

  • Thanks Frank,

    I would like to avoid interrupts if at all possible as I have another very time sensitive function running on an interrupt. If i were to use interrupts, I would not be able to set the interrupt for any one mailbox because it is not always 5 messages, sometimes fewer or even just 1. I currently have code that periodically checks for messages by looking at ECanaRegs.CANRMP.all.

    Datarate = 500kbps, busload is minimal ( < 10%), message repetition (n/a, second pack of message not sent until acknowledge is received).

    I am using CANking w/ Kvaser instead of Canalyzer. But yes, I do see the commanded messages, however, only first two have been acknowledged by F2812.

     

    Below is my code for setting up CAN. Mostly based off of samples from TI. Any help would be very much appreciated.

    EALLOW;
        SysCtrlRegs.PCLKCR.bit.ECANENCLK = 1;        //enable the clock for CAN peripheral

        GpioMuxRegs.GPFMUX.bit.CANTXA_GPIOF6 = 1;    //enable the CAN Tx pin
        GpioMuxRegs.GPFMUX.bit.CANRXA_GPIOF7 = 1;    //enable the CAN Rx pin

        ECanaCopy.CANTIOC.all = ECanaRegs.CANTIOC.all;
        ECanaCopy.CANRIOC.all = ECanaRegs.CANRIOC.all;
        ECanaCopy.CANTIOC.bit.TXFUNC = 1;            //enable CAN Tx
        ECanaCopy.CANRIOC.bit.RXFUNC = 1;            //enable CAN Rx
        ECanaRegs.CANTIOC.all = ECanaCopy.CANTIOC.all;
        ECanaRegs.CANRIOC.all = ECanaCopy.CANRIOC.all;

        ECanaCopy.CANMC.all = ECanaRegs.CANMC.all;
        ECanaCopy.CANMC.bit.SCB = 1;        //set enhanced CAN mode
        ECanaRegs.CANMC.all = ECanaCopy.CANMC.all;
        EDIS;

        ECanaRegs.CANME.all = 0;    //mailbox must be disabled before writing to msgctrl or msgid

        //reset mailbox. can only be done when mailbox disabled (CANME = 0)
        for (i=0; i<32; i++)
            ECanaMboxes.BOX[i].MSGCTRL.all = 0x00000000;

        //clear flags
        ECanaRegs.CANTA.all    = 0xFFFFFFFF;
        ECanaRegs.CANRMP.all = 0xFFFFFFFF;
        ECanaRegs.CANGIF0.all = 0xFFFFFFFF;
        ECanaRegs.CANGIF1.all = 0xFFFFFFFF;

        ECanaRegs.CANOPC.all = 0xFFFFFF00;        //all recieve boxes are overwrite protected.

            EALLOW;

            ECanaCopy.CANMC.all     = ECanaRegs.CANMC.all;
            ECanaCopy.CANMC.bit.CCR = 1 ;                    //request to change config registers
            ECanaRegs.CANMC.all     = ECanaCopy.CANMC.all;
            do {ECanaCopy.CANES.all = ECanaRegs.CANES.all;
            } while(ECanaCopy.CANES.bit.CCE != 1);          //wait to be allowed to change configs

    ECanaCopy.CANBTC.bit.BRPREG = 19;    //set to 500 Kbps

            ECanaCopy.CANBTC.bit.TSEG1REG = 10;
            ECanaCopy.CANBTC.bit.TSEG2REG = 2;
            ECanaCopy.CANBTC.bit.SAM = 1;                    //required if BRP is > 4
            ECanaRegs.CANBTC.all = ECanaCopy.CANBTC.all;

            ECanaCopy.CANMC.all     = ECanaRegs.CANMC.all;
            ECanaCopy.CANMC.bit.CCR = 0 ;                    //request to disable changing of registers
            ECanaRegs.CANMC.all     = ECanaCopy.CANMC.all;
            do {ECanaCopy.CANES.all = ECanaRegs.CANES.all;
            } while(ECanaCopy.CANES.bit.CCE != 0);          //wait for disabling of registers

            EDIS;

        ECanaMboxes.BOX[16].MSGID.all = (Uint32)0x600 << 18;
        ECanaMboxes.BOX[17].MSGID.all = (Uint32)0x600 << 18;
        ECanaMboxes.BOX[18].MSGID.all = (Uint32)0x600 << 18;
        ECanaMboxes.BOX[19].MSGID.all = (Uint32)0x600 << 18;
        ECanaMboxes.BOX[20].MSGID.all = (Uint32)0x600 << 18;


  • Henry,

    look like your code has been snippet at the end of your mail. Where is the initialization for the OPC etc?

     

  •     ECanaRegs.CANOPC.all = 0xFFFFFF00;

    that's the code. I've set all my receive boxes to be overwrite protected. I've only shown the setup of the boxes pertaining to this issue above. The other boxes are for different CAN IDs. That are not sent in bursts.

  • sorry, i also mistaken left out these lines

    ECanaRegs.CANME.all = 0x00000000;

    //the above setup of mailboxes goes here.

    ECanaRegs.CANMD.all = 0xFFFFFF00; //set box 0-7 for Tx, box 8-31 for Rx

    ECanaRegs.CANME.all = 0xFFFFFFFF;

  • Does any know where I can find some sample code that uses interrupts to receive CAN messages?

    I am still having problems, and the available samples do not use interrupts.

  • Henry,

    I have attrached a simple CAN example from my 2812-lessons. It is a duplex CAN-Tx and CAN-Rx interrupt example. The example uses LEDs at GPIO B0--B7 to display the incoming messages.

     

     

  • Hello

    My software needs to send and receive messages using interrupts.

    I have used your sample attached but i have an issue:

     

    interrupt void ecan1intA_isr(void)
    {
      unsigned int mailbox_nr;
     
        mailbox_nr = ECanaRegs.CANGIF1.bit.MIV1;

      if(mailbox_nr == 0)  // mailbox #1 receive message
      {     
    //    GpioDataRegs.GPBDAT.all = ECanaMboxes.MBOX1.MDL.byte.BYTE0 & 0x000000FF;
    //    ECanaShadow.CANRMP.bit.RMP1 = 1;
    //    ECanaRegs.CANRMP.all = ECanaShadow.CANRMP.all;
       
        CTC_FetchRequest();
      }
     
      if(mailbox_nr == 5)  // mailbox #5 transmit-message
      {   
    //    ECanaShadow.CANTA.all = 0;
    //    ECanaShadow.CANTA.bit.TA5 = 1;
    //    ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;
         
        CTC_MASTER_ProcessVCUrequest();     
         
           CanMBox5Quit = 1;
      }
     
      PieCtrlRegs.PIEACK.bit.ACK9 = 1;
    }

    void main()

    {

    //
        LedInit();
       
    // Initialize System Control registers, PLL, WatchDog, Clocks to default state:
    // This function is found in the DSP28_SysCtrl.c file.       
        InitSysCtrl();

    //    Enable Watchdog
        EALLOW;
          SysCtrlRegs.WDCR= 0x00AE;
          EDIS;
         
    // Initialise the physical pins of the DSP
        Gpio_select();     
       
    // Initialize Interrupt System PIE
        InitPieCtrl();
          InitPieVectTable();

    // Overload CPU Timer 0 and CAN1 ISR - entry
          EALLOW;
          PieVectTable.TINT0 = &cpu_timer0_isr;
          PieVectTable.ECAN1INTA = &ecan1intA_isr;
          EDIS;

    // Iitialize CPU - Timer system   
        InitCpuTimers();

        //
        InitECan(); // TODO: Le rescriem
       
        ///
        ConfigMailBox_0_RX(); // TODO: Le rescriem
       
    // enable interrupt lines
        PieCtrlRegs.PIEIER1.bit.INTx7 = 1;  // TINT0
        PieCtrlRegs.PIEIER9.bit.INTx6 = 1;  // ECAN1INTA
          IER |= 0x0101;
          EINT;   


    // setup CPU-Timer 0 to 50 ms   
          ConfigCpuTimer(&CpuTimer0,150,50000);
          CpuTimer0.InterruptCount =0;
          CpuTimer0Regs.TCR.bit.TSS = 0;

     

    while (1)

    {

    !!!(1)    if(CpuTimer0.InterruptCount >= 20)
        {
            CpuTimer0.InterruptCount = 0;
            if(CanMBox5Quit == 1)     // prev. transmission completed
            {
                CanMBox5Quit=0;
               
                //ECanaMboxes.MBOX5.MDL.byte.BYTE0 = send_data & 0x00FF;
       
                //ECanaShadow.CANTRS.bit.TRS5 = 1;
                //ECanaRegs.CANTRS = ECanaShadow.CANTRS;
       
                //send_data++;        // next payload
                //send_data %= 256;  // limit to 8 bit
               
                LedSwitch();
               
                GpioDataRegs.GPBTOGGLE.bit.GPIOB0 = 1;
            }
        }

    }

     

    }

     

    !!!(1) - what is the utility of this condition and variable CpuTimer0.InterruptCount??

    2 - the interrupt function it never gets runed.

     

    Thanks.

    Regards.

     

  • hello

    i have resolved the interrupt issue, but how:    CanMBox5Quit = 1;
    //
        LedInit();   
       
       (1 !!!!!!!!!!!!!!!) //InitECan(); // TODO: Le rescriem
       
    // Initialize System Control registers, PLL, WatchDog, Clocks to default state:
    // This function is found in the DSP28_SysCtrl.c file.       
        InitSysCtrl();

    //    Enable Watchdog
        EALLOW;
          SysCtrlRegs.WDCR= 0x00AE;
          EDIS;
         
    // Initialise the physical pins of the DSP
        Gpio_select();     
       
    // Initialize Interrupt System PIE
        InitPieCtrl();
          InitPieVectTable();

    // Overload CPU Timer 0 and CAN1 ISR - entry
          EALLOW;
          PieVectTable.TINT0 = &cpu_timer0_isr;
          PieVectTable.ECAN1INTA = &ecan1intA_isr;
          EDIS;

    // Iitialize CPU - Timer system   
        InitCpuTimers();

        (2 !!!!!!!!!!)//
        InitECan(); // TODO: Le rescriem
       
        DINT;
        IER = 0x0000;
        IFR = 0x0000;
       
        ///
        ConfigMailBox_0_RX(); // TODO: Le rescriem
       
    // enable interrupt lines
        PieCtrlRegs.PIEIER1.bit.INTx7 = 1;  // TINT0
        PieCtrlRegs.PIEIER9.bit.INTx6 = 1;  // ECAN1INTA
          IER |= 0x0101;          
          EINT;   


    // setup CPU-Timer 0 to 50 ms   
          ConfigCpuTimer(&CpuTimer0,150,50000);
          CpuTimer0.InterruptCount =0;
          CpuTimer0Regs.TCR.bit.TSS = 0;

     

    that is my hardware configuration code

    if i use the InitECan() to step (1 !!!!!!!!), the module triggers the ecan1intA_isr method and replys to the can buss with 600 identical messages instead of 1

    if i use the InitECan() to step (2 !!!!!!!!), the module triggers the ecan1intA_isr method and replys to the can buss with 32 000 identical messages instead of 1

     

    can you help?

     

    thanks

  • We have SAE J1939 and ISO 15765 source code for the C2000 family.  If you have any questions, please feel free to contact us.

    http://www.simmasoftware.com/j1939.html

    http://www.simmasoftware.com/i15765.html

     

  • Like Liviu, I attempted to adapt the ISR ecan1intA_isr() in
    lab_CAN_5.txt to my application and have run into a
    stumbling block.

    The statement:

      mailbox_nr = ECanaRegs.CANGIF1.bit.MIV1;

    appears to initialize mailbox_nr with a single bit from the
    CANGIF1 register.  Lower down, we compare it with 5:

      if(mailbox_nr == 5)  // mailbox #5 transmit-message

    As I read it, the only way mailbox_nr could be 5 at this
    point would be if the ISR was itself interrupted by a
    higher-priority ISR, which changed mailbox_nr again.

    What am I missing?

  • Gary,

    the MIV1 field is actually a 5-bit field for numbers between 0 and 31. It indicates the number of the mailbox, which has caused the interrupt request.

    The instruction: mailbox_nr = ECanaRegs.CANGIF1.bit.MIV1; reads this number and makes a local copy in mailbox_nr. Later in the code I can use this variable to decide, if I have to execute code, which is specific for that mailbox.

    Regards

     

     


  • Oops! My mistake.

    I thought I had read that header file thoroughly, but
    obviously I did not.

    Thanks for explaining.