How does FlexCAN CAN-ID matching mechanism work ?

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

How does FlexCAN CAN-ID matching mechanism work ?

2,823 Views
jbrud
Contributor III

Hi All,

I followed the provided SDK examples for CAN and I initialized the FlexCAN-Driver in my own example like shown below:

...

    flexcan_config_t flexcanConfig;
    flexcan_rx_mb_config_t mbConfig;



    txIdentifier = 0x080;
    rxIdentifier = 0x0A0;


    /* Get FlexCAN module default Configuration. */
    /*
     * flexcanConfig.clksrc=kFLEXCAN_ClkSrcOsc;
     * flexcanConfig.baudRate = 1000000U;
     * flexcanConfig.maxMbNum = 16;
     * flexcanConfig.enableLoopBack = false;
     * flexcanConfig.enableSelfWakeup = false;
     * flexcanConfig.enableIndividMask = false;
     * flexcanConfig.enableDoze = false;
     * flexcanConfig.timingConfig = timingConfig;
     */
    FLEXCAN_GetDefaultConfig(&flexcanConfig);
    flexcanConfig.baudRate = 500000U;
    flexcanConfig.clkSrc = kFLEXCAN_ClkSrcPeri;


    /* Init FlexCAN module. */
    FLEXCAN_Init(PE900_CAN, &flexcanConfig, PE900_CAN_CLK_FREQ);


    /* Create FlexCAN handle structure and set call back function. */
    FLEXCAN_TransferCreateHandle(PE900_CAN, &flexcanHandle, flexcan_callback, NULL);


    /* Set Rx Masking mechanism. */
    FLEXCAN_SetRxMbGlobalMask(PE900_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));


    /* Setup Rx Message Buffer. */
    mbConfig.format = kFLEXCAN_FrameFormatStandard;
    mbConfig.type = kFLEXCAN_FrameTypeData;
    mbConfig.id = FLEXCAN_ID_STD(rxIdentifier);
    FLEXCAN_SetRxMbConfig(PE900_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);


    /* Setup Tx Message Buffer. */
    FLEXCAN_SetTxMbConfig(PE900_CAN, TX_MESSAGE_BUFFER_NUM, true);


    txframe.dataByte0 = 0x0F;
    txframe.dataByte1 = 0xFF;
    txframe.dataByte2 = 0x0F;
    txframe.dataByte3 = 0xFF;
    txframe.dataByte4 = 0x01;


    /* Start receiving and wait for can messages */
    rxXfer.mbIdx = RX_MESSAGE_BUFFER_NUM;
    rxXfer.frame = &rxframe;
    FLEXCAN_TransferReceiveNonBlocking(PE900_CAN, &flexcanHandle, &rxXfer);
...‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I would expect that now only frames with CAN-ID 0x0A0 will be received but instead a lot of other ID's will be received all from 0xA0 to 0xBF.  I think relevant steps are:

    /* Set Rx Masking mechanism. */
    FLEXCAN_SetRxMbGlobalMask(PE900_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));

and

    mbConfig.id = FLEXCAN_ID_STD(rxIdentifier);

The second step is clear, nothing can be done wrongly here. But I would think the first step enables generally ID's but its usage is really clear to me. At this point the source code is also not documented well, no comment explains the meaning of rtr, ide.  See:

/*! @brief FlexCAN Rx Message Buffer Mask helper macro. */
#define FLEXCAN_RX_MB_STD_MASK(id, rtr, ide) 

Fall back to the reference manual helps me also not really.

How to setup the flexCAN driver to receive messages only from one CAN-ID ?

Any help is welcome !

Tags (2)
9 Replies

2,204 Views
nxf51211
NXP Employee
NXP Employee

Hi,

I would like to ask what board are you using for your project, and what is the name of the SDK example you described, so I can see why the RX is receiving messages from more than one ID.

Best Regards,

Ricardo Delsordo

0 Kudos

2,204 Views
jbrud
Contributor III

I' using the FRDM-K64F with a CAN-Driver IC and a USB-CAN-Adapter . But the example I referred is  twrk64f120m/driver_examples/flexcan/interrupt_transfer.  The initialization & configuration is from this example so you should able to reproduce it with this example.

0 Kudos

2,204 Views
nxf51211
NXP Employee
NXP Employee

Hi,

If you are using the FRDM-K64F, I recommend you install its SDK and use it instead of the one for the TWRK64F120M. I've tried one of the examples from this SDK (loop back transfer) and the project was able to only receive the frames from the device with the ID desired.

Best Regards,

Ricardo Delsordo

0 Kudos

2,204 Views
jbrud
Contributor III

I don't think it's meaningful to use the loop back mode for reproducing this issue. I'm sure if you take two TWRK64F120M on your desk and try the example flexcan_interrupt_transfer you will obtain the same behavior as I had.

Since this example sets:

/* Set Rx Masking mechanism. */
FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));‍‍
0 Kudos

2,204 Views
mjbcswitzerland
Specialist V

Hi

As I noted, one should not set the ID as mask so I checked the example:

    /* Set Rx Masking mechanism. */
    FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));

This is incorrect and could instead be set to

    /* Set Rx Masking mechanism. */
    FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, FLEXCAN_RX_MB_STD_MASK(0x7ff, 0, 0));

to achieve unique ID matching.

I see that the example FlexCAN interface sets all filter masks with the same value so it is not possible to mix extended and standard IDs as it is.

Regards

Mark

2,204 Views
jbrud
Contributor III

Thanks ! Now I got it. In my case I only have to support standard IDs. With FLEXCAN_RX_MB_STD_MASK(0x7ff, 0, 0)); it receives only messages from one ID. It would be still helpful if someone could clarify the usage of this macro.

0 Kudos

2,204 Views
nxf51211
NXP Employee
NXP Employee

Hi,

 

The usage of this macro is to only organize the ID, IDE and RTR parameters that you are going to use for the configuration of the CANx_RXMGMASK register which is set when you call the FLEXCAN_SetRxMbGlobalMask function:

/*! @brief FlexCAN Rx Message Buffer Mask helper macro. */
#define FLEXCAN_RX_MB_STD_MASK(id, rtr, ide)                                   \
    (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \
     FLEXCAN_ID_STD(id)) /*!< Standard Rx Message Buffer Mask helper macro. */

The IDE indicates if it is standard frame or extended frame, and the RTR indicates if it is remote frame or data frame.

Best Regards,

Ricardo Delsordo.

0 Kudos

2,204 Views
mjbcswitzerland
Specialist V

I have seen that there is another set of macros that can be used when working with extended CAN IDs although the example code doesn't allow multiple IDs or mixing extended with standard ones.

Below is the CAN interface as used by the uTasker project (compatible with Coldfire, Kinetis and i.MX RT) when configuring for CANopen operation (using standard and extended IDs for objects directories) which shows that it is simple to define the IDs, the buffers that are to be used with them, and allow efficient masking of extended node ID, standard node ID and also the broadcast ID so that dedicated Rx buffers and handlers are assigned to each.

Regards

Mark

#define CANOPEN_RX_NODE_ID                  0x7a                         // we receive this node-ID
#define CANOPEN_TX_NODE_ID                  0x37                         // this is the node-ID hat we use when transmitting

// Configure the CAN interface
//
static QUEUE_HANDLE fnInitCANopenInterface(void)
{
    CANTABLE tCANParameters;                                             // table for passing information to driver
    QUEUE_HANDLE CANopenHandle;

    tCANParameters.Channel = 1;                                          // CAN1 interface
    tCANParameters.ulSpeed = 250000;                                     // 250k speed
    tCANParameters.ulTxID = (0);                                         // default ID of destination (not used by CANopen)
    tCANParameters.ulRxID = (CAN_EXTENDED_ID | 0x00080000 | CANOPEN_RX_NODE_ID); // extended node ID that we receive
    tCANParameters.ulRxIDMask = (0x00080000 | CANOPEN_RX_NODE_ID);       // receive extended address with 0x80000 set and exactly matching the node ID
    tCANParameters.usMode = 0;                                           // use normal mode
    tCANParameters.ucTxBuffers = 2;                                      // assign two tx buffers for use
    tCANParameters.ucRxBuffers = 1;                                      // assign one rx buffers for extended ID use
    CANopenHandle = fnOpen(TYPE_CAN, FOR_I_O, &tCANParameters);          // open CAN interface for extended ID usage

    tCANParameters.ulRxID = 0;                                           // broadcast address
    tCANParameters.ulRxIDMask = CAN_STANDARD_MASK;                       // accept ID 0
    tCANParameters.ucTxBuffers = 0;
    tCANParameters.ucRxBuffers = 1;
    fnConfigCAN(CANopenHandle, &tCANParameters);                         // configure 1 further rx buffer for this logical channel

    tCANParameters.ulRxID = CANOPEN_RX_NODE_ID;                          // node ID that we receive
    tCANParameters.ulRxIDMask = 0x7f;                                    // accept only exact node ID
    tCANParameters.ucRxBuffers = 1;
    fnConfigCAN(CANopenHandle, &tCANParameters);                         // configure 1 further rx buffer for this logical channel
    return CANopenHandle;                                                // open CAN interface
}

Complete Kinetis solutions for professionals needs, training and support: http://www.utasker.com/kinetis.html
Turn-key CANopen for Kinetis - http://www.utasker.com/index.html
FlexCAN simulation: https://www.youtube.com/watch?v=Ha8cv_XEvco

0 Kudos

2,204 Views
mjbcswitzerland
Specialist V

Hi

The CAN buffer filter mask has to be set to specify which bits are checked.

For standard ID filtering (0..0x7ff) the filter mask is 0x7ff so that all bits of the 11 bit ID must match - if you have set the mask to equal your standard ID it will only be checking the bits that are '1' and allowing all other to be either '0' or '1', which is not what you want.

You will also need to check the library that you are using because it may need 0x7ff or it may need (0x7ff << 18), depending on whether to does the shift or it expects you to deliver the mask in the form as required by the FlexCAN register (for standard ID filtering).

Note also that there are three filters/masks that can be used. The global mask is used by buffers 0..13 and buffers 14 and 15 can use their own unique filters/masks which allows mixing standard and extended IDs and such.
Check also carefully the library implementation because some are unreliable at setting filters due to clock domain synchronisation issues (if in doubt, read back the values written to the register and rewrite them until they correctly match).

Regards

Mark

Complete Kinetis solutions for professionals, training and support: http://www.utasker.com/kinetis.html
Turn-key CANopen for Kinetis FlexCAN - http://www.utasker.com/index.html
FlexCAN simulation: https://www.youtube.com/watch?v=Ha8cv_XEvco