Issue with CAN Message Forwarding with LLCE: Only One Message Gets Forwarded

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Issue with CAN Message Forwarding with LLCE: Only One Message Gets Forwarded

429 Views
MrAlexIV
Contributor III

Hi everyone,

I'm working on a project on S32DS using the Can_Llce_DS_Can2Can_S32G399A_M7 example, and I've encountered a problem with my CAN message forwarding code. Specifically, I'm only able to forward one message at a time.

Here's what's happening: I'm receiving two CAN messages with IDs 0x01 and 0x02, and my goal is to forward these messages with new IDs 0x51 and 0x52. However, no matter what, the system always forwards only the message with ID 0x51. The two messages arrive almost simultaneously, with 0x02 arriving just a few nanoseconds before 0x01.

I've already tried a few things to resolve this issue:

  1. I've tried setting the receiver to both INTERRUPT and POLLING modes.

  2. I've experimented with using a queue.

  3. I also tried applying a filter to only forward messages with ID 0x02, and it successfully forwards 0x52, so the filter itself isn't the problem.

I'm using a single LLCE line for communication.

Does anyone have any idea what might be causing this behavior or how I can resolve it? Any insights would be greatly appreciated!

Thanks in advance!

I also leave my main.c here and attach the image of my CanController

 

#include "Can_43_LLCE.h"
#include "Can_43_LLCE_IPW.h"
#include "PlatformInit.h"
#include "Llce_Firmware_Load.h"
#include <stdbool.h>
#include "stubs.h"

/*==================================================================================================
DEFINITIONS AND MACROS
==================================================================================================*/
#define CAN_CONTROLLER_ID       (0U)
#define CAN_TRANSMIT_HTH        (CanHO_Config0_TX0)
#define CAN_ID_REWRITE_OFFSET   (0x50U)
#define MAX_KNOWN_SOURCE_IDS    (32U) // Maximum unique IDs that the gateway stores

/* --- Configuration macros --- */
#define MACRO_CONCAT(a,b)       a##b
#define CAN_VARIANT(var)        MACRO_CONCAT(Can_43_LLCE_Config_, var)
#ifndef CONFIG_VARIANT_USED
 #define CAN_LLCE_VARIANT       (NULL_PTR)
#else
 #define CAN_LLCE_VARIANT       (&CAN_VARIANT(CONFIG_VARIANT_USED))
#endif
/**
 * @brief Mask to isolate the 29-bit CAN ID from the status flags.
 * @details Can_RxId contains flags in the higher bits. This mask clears the flags and keeps only
 * the message identifier.
 */
#define CAN_ID_MASK             (0x1FFFFFFFUL)
/*==================================================================================================
GLOBAL AND STATIC VARIABLES
==================================================================================================*/
extern volatile uint32     Can_RxIndication;
extern volatile Can_IdType Can_RxId;
extern volatile uint8      Can_RxDlc;
extern volatile uint8      Can_RxData[];

// Array for anti-loop logic: stores the source IDs already processed.
static Can_IdType knownSourceIds[MAX_KNOWN_SOURCE_IDS];
static uint32     knownSourceIdsCount = 0;

#define DEBUG_ID_MSG_RECEIVED   (0x7E0U) // Sent when a message is read from the bus
#define DEBUG_ID_MSG_FORWARDED  (0x7E1U) // Sent when a message is forwarded
#define DEBUG_ID_MSG_IGNORED    (0x7E2U) // Sent when a message is ignored (echo)
static uint8 debugData[8] = {0};

void Send_Debug_Message(Can_IdType debugId, uint8 value)
{
    Can_PduType debugPdu;
    debugData[0] = value;

    debugPdu.id = debugId;
    debugPdu.length = 8;
    debugPdu.sdu = debugData;
    debugPdu.swPduHandle = 0;
    (void)Can_43_LLCE_Write(CAN_TRANSMIT_HTH, &debugPdu);
}

/*==================================================================================================
MAIN FUNCTION
==================================================================================================*/
int main(void)
{
    Std_ReturnType retval = E_NOT_OK;
    Can_PduType txPdu;
    uint32 processed_rx_count = 0;

    PlatformInit();
    Llce_Firmware_Load();
    Can_43_LLCE_Init(CAN_LLCE_VARIANT);
    Can_CallBackSetUp();

    (void)Can_43_LLCE_SetBaudrate(CAN_CONTROLLER_ID, 0);
    retval = Can_43_LLCE_SetControllerMode(CAN_CONTROLLER_ID, CAN_CS_STARTED);
    if (E_OK != retval) { while(1); }

    processed_rx_count = Can_RxIndication;

    while (1)
      {
         
          Can_43_LLCE_IPW_MainFunctionRead();

          
          while (Can_RxIndication > processed_rx_count)
          {
             

              // Process the currently available data in the global variables
              Can_IdType cleanId = Can_RxId & CAN_ID_MASK;

           
              if (cleanId < CAN_ID_REWRITE_OFFSET)
              {
                  txPdu.id = (Can_RxId & ~CAN_ID_MASK) | (cleanId + CAN_ID_REWRITE_OFFSET);
                  txPdu.length = Can_RxDlc;
                  txPdu.sdu = (uint8*) Can_RxData;
                  txPdu.swPduHandle = 0;
                  (void) Can_43_LLCE_Write(CAN_TRANSMIT_HTH, &txPdu);
              }

              // Incremental acknowledgment: we have processed ONE message.
              processed_rx_count++;

              // To handle the next message in the backlog, the driver needs
              // to reload the data of the next message into the global variables.
              // We call the read function again if there are still messages waiting.
               if (Can_RxIndication > processed_rx_count)
               {
                   Can_43_LLCE_IPW_MainFunctionRead();
               }
          }
      }
    return 0;
}

 

0 Kudos
Reply
9 Replies

410 Views
MrAlexIV
Contributor III

Also, I am using 2 CanHwObject (one for Rx and one for Tx). On the Rx, Filter code and mask are both 0

0 Kudos
Reply

401 Views
Joey_z
NXP Employee
NXP Employee

hi,MrAlexIV

Thank you for contacting us.

Do you use the RDB2 or RDB3? And which version of LLCE are you using?

Do you want to use one channel for sending two kinds of CAN frame? And are you using any routing for this LLCE CAN frame?

BR

Joey

397 Views
MrAlexIV
Contributor III

Hi
- I am using RDB3 and LLCE 1.0.9 (since there is a bug on the 1.0.10 for the example project)

- Yes, that's correct. Here is a summary of my setup:

 

1. Using One Channel for Sending and Receiving

 

I am using a single physical CAN channel (an LLCE instance) for both receiving and transmitting multiple types of CAN frames. My goal is to create a simple CAN gateway.

  • Receiving: The device listens for various CAN IDs on the bus (e.g., 0x01, 0x02, etc.).

  • Transmitting: After processing a received frame, the device sends out a new, modified frame through the same physical channel. For instance, if it receives ID 0x01, it will transmit ID 0x51.

 

2. Routing Logic

 

Yes, I am implementing the routing logic for these frames directly within my application firmware (main.c).

The routing rule is straightforward: the application reads any incoming CAN frame, modifies its ID by adding a fixed offset (e.g., 0x50), and then schedules this new frame for transmission on the same bus. The LLCE driver is simply used as the hardware interface to receive the original frames and transmit the routed ones.



I also found a similar issue on the forum, about FlexCan. There, they used RxFIFO, but I can't  find this option for LLCE

0 Kudos
Reply

353 Views
Joey_z
NXP Employee
NXP Employee

hi,MrAlexIV

Thank you for your reply.

Do you have a try that make more time for receiving two frames?

The CAN2CAN of LLCE can remap the CAN ID, do you can consider it? It uses two channels for internal routing. You can check the Can2CanRoutingTable_3 about it in the demo of  Can_Llce_DS_Can2Can_S32G399A_M7.

BR

Joey

 

343 Views
MrAlexIV
Contributor III

I attach here my configuration.
- I am using 1 CanController. In Polling for RECEIVE and INTERRUPT for Trasmit
- I am using 2 CanHwObject, one for RX and one for TX. I have also tried to use two of them for RX, one for each ID, changing the filter and the mask in 0x1, 0x7FF and 0x2,0x7FF. But it did not work anyway.

0 Kudos
Reply

348 Views
MrAlexIV
Contributor III

Hi Joey,

Thank you very much for the suggestions. This is very helpful.

  1. Timing Test: I will try your suggestion of adding more time between the two frames and I will report back with the result.

  2. Hardware CAN2CAN Routing: This sounds like an excellent solution. My main requirement is to perform this gateway function on a single physical CAN bus (i.e., receive and transmit on the same line).

Your comment mentioned that CAN2CAN routing "uses two channels". My question is: can this internal routing be configured to transmit the remapped frame back onto the very same channel it was received from (e.g., from BCAN_0 back to BCAN_0)?

If so, does this require a specific setting to be enabled, such as "Self Reception Enable" in the CanController configuration? 

Thank you for clarifying this point.

0 Kudos
Reply

61 Views
Joey_z
NXP Employee
NXP Employee

hi,MrAlexIV

Thank you for your reply.

Do you have a test for increasing the interval?

Do you have CAN communication test equipment? It CAN capture CAN frames and view communication status.

The CAN2CAN is usually internally routed to other ports, and the destination address should not be its own.

If there are frame conflict issues, could you consider the arbitration mechanism of CAN frames in your project?

BR

Joey

0 Kudos
Reply

49 Views
MrAlexIV
Contributor III

Hi Joey,
Thank you again for your reply.
Regarding to your comment:

1) Yes, I increased the interval. What I noticed is that it actually works even if the time interval is quite short, but only if the CAN messages are sent from two different devices. Let me explain better:

I’m using a CAN bus where I connect my external devices (which send CAN messages) and my LLCE line. Right now, I have two external devices connected. One sends two messages (0x01 and 0x02), and the other one sends a single message (0x05). If only the first device is active, I only forward 0x01 (as 0x51), while 0x02 gets ignored. But if I also connect the second device, which sends 0x05, then I can forward both 0x01 and 0x05 (as 0x51 and 0x55), even with a very short time interval. Why is that? Why doesn’t it forward 0x02 as well when both 0x01 and 0x02 come from the same device? Is it because they are sent by the same external device, or is it simply because the time interval is too short?


2) Yes, I’m using a CAN logger (Kvaser CANKing). I’ve attached a screenshot: in red you can see the message received from the second external device (0x05) and the one forwarded by the LLCE (0x55); in blue you can see the messages from the first external device (0x01 and 0x02) with the forwarded one from the LLCE (only 0x01, while 0x02 seems to be ignored).

3) Regarding the arbitration, what do you mean?

Thano you!

0 Kudos
Reply

37 Views
Joey_z
NXP Employee
NXP Employee

hi,MrAlexIV

Thank you for your reply and detail information.

It should be ok for your S32G CAN function for receiving CAN frame from two different device, could you try adding a time interval on a sending device? This should be useful for troubleshooting problems. It's likely that your second sending has affected the data return of the first one.

BR

Joey

 

0 Kudos
Reply