i.MX RT1024 CAN filter

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

i.MX RT1024 CAN filter

Jump to solution
383 Views
alvarolopes
Contributor III

 

Hi,

I want to use CAN ID´s from 0x100 to 0x200 and I would like to know how to apply a filter to a mailbox to accept this range of ID´s.  Does anyone know how to implement this filter? 

MIMXRT1024 has only a simple example that has only a specific ID and doesn´t show how to apply a filter.

Regards.

0 Kudos
1 Solution
358 Views
alvarolopes
Contributor III

Mark,

Thank you for being so helpful.

I am using CAN drivers from MCUXpresso IDE. Using these drivers and reading your tips I solve my problem like this:

 

CAN INITIALIZATION:


flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;
uint64_t flag = 1U;

    //Clock setting for FLEXCAN
    CLOCK_SetMux(kCLOCK_CanMux, FLEXCAN_CLOCK_SOURCE_SELECT);
    CLOCK_SetDiv(kCLOCK_CanDiv, FLEXCAN_CLOCK_SOURCE_DIVIDER);

    LOG_INFO("********** CAN DEFINITIONS *************\r\n");
    LOG_INFO("\r\n");
    LOG_INFO("    Message format: Standard (11 bit id)\r\n");
    LOG_INFO("    Message buffer %d used for Rx.\r\n", RX_MESSAGE_BUFFER_NUM);
    LOG_INFO("    Message buffer %d used for Tx.\r\n", TX_MESSAGE_BUFFER_NUM);
    LOG_INFO("    Interrupt Mode: Enabled\r\n");
    LOG_INFO("    Operation Mode: TX and RX --> Normal\r\n");
    LOG_INFO("\r\n");
    LOG_INFO("*****************************************\r\n\r\n");

    //Rx ID
    rxIdentifier = 0x100;
    rxIdentifier1 = 0x200;

    //Get FlexCAN module default Configuration.

    // flexcanConfig.clkSrc                             = kFLEXCAN_ClkSrc0;
     // flexcanConfig.baudRate                      = 1000000U;
     // flexcanConfig.baudRateFD                 = 2000000U;
     // flexcanConfig.maxMbNum                  = 16;
     // flexcanConfig.enableLoopBack           = false;
     // flexcanConfig.enableSelfWakeup        = false;
     // flexcanConfig.enableIndividMask         = false;
     // flexcanConfig.disableSelfReception     = false;
     // flexcanConfig.enableListenOnlyMode  = false;
     // flexcanConfig.enableDoze                    = false;

    FLEXCAN_GetDefaultConfig(&flexcanConfig);

    flexcanConfig.bitRate = CAN_SPEED;
    flexcanConfig.baudRate = CAN_SPEED;

    flexcan_timing_config_t timing_config;
    memset(&timing_config, 0, sizeof(flexcan_timing_config_t));

    if (FLEXCAN_CalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.baudRate, EXAMPLE_CAN_CLK_FREQ, &timing_config))
    {
        //Update the improved timing configuration
        memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
    }
    else
    {
        LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
    }

    FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ);

    mbConfig.format = kFLEXCAN_FrameFormatStandard;
    mbConfig.type   = kFLEXCAN_FrameTypeData;
    mbConfig.id     = FLEXCAN_ID_STD(rxIdentifier);

    //Here I am using filter, RX_MESSAGE_BUFFER_NUM1 accept from ID 0x100 to 0x1FF

    FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));

    //Configure Mailbox
    FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);

    //Set rxIdentifier1 Masking mechanism.

    //No filter here, RX_MESSAGE_BUFFER_NUM1 accept only ID 0x200

    mbConfig.format = kFLEXCAN_FrameFormatStandard;
    mbConfig.type   = kFLEXCAN_FrameTypeData;
    mbConfig.id     = FLEXCAN_ID_STD(rxIdentifier1);

    //Configure Mailbox
    FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM1, &mbConfig, true);

    //Configure interruption
    FLEXCAN_EnableMbInterrupts(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM);
    FLEXCAN_EnableMbInterrupts(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM1);

   //Enable interrupts
   (void)EnableIRQ(EXAMPLE_CAN_IRQn);

 

CAN INTERRUPTION

uint64_t flag = 1U;

    //If new data arrived
    if (0U != FLEXCAN_GetMbStatusFlags(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM))
    {
        FLEXCAN_ClearMbStatusFlags(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM);
        (void)FLEXCAN_ReadRxMb(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &rxFrame);

        rxComplete = true;
    }

    //If new data arrived
    if (0U != FLEXCAN_GetMbStatusFlags(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM1))
    {
        FLEXCAN_ClearMbStatusFlags(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM1);
        (void)FLEXCAN_ReadRxMb(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM1, &rxFrame1);

        rxComplete = true;
    }

    SDK_ISR_EXIT_BARRIER;

 

One more time, thanks a lot. 

Regards,

Alvaro

View solution in original post

0 Kudos
4 Replies
371 Views
alvarolopes
Contributor III

Hi,

I couldn´t find the uTasker project for CAN on the page  https://www.utasker.com/index.html

Follow my CAN example:

#define RX_MESSAGE_BUFFER_NUM (10)

rxIdentifier = 0x321;

FLEXCAN_SetRxMbGlobalMask(TIS3_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));

In this function above I set the filters. Follow the function inside the driver:

void FLEXCAN_SetRxMbGlobalMask(CAN_Type *base, uint32_t mask)
{
/* Enter Freeze Mode. */
FLEXCAN_EnterFreezeMode(base);

/* Setting Rx Message Buffer Global Mask value. */
base->RXMGMASK = mask;
base->RX14MASK = mask;
base->RX15MASK = mask;

/* Exit Freeze Mode. */
FLEXCAN_ExitFreezeMode(base);
}

You can note that RXMGMASK, RX14MASK, and RX15MASK receive the same parameter which should be the mask value.

FLEXCAN_EnableMbInterrupts(TIS3_CAN, flag << RX_MESSAGE_BUFFER_NUM);

rxXfer.mbIdx = (uint8_t)RX_MESSAGE_BUFFER_NUM;

rxXfer.frame = &frame;
(void)FLEXCAN_TransferReceiveNonBlocking(TIS3_CAN, &flexcanHandle, &rxXfer);

Regards!

 

 

 

 

 

 

 

0 Kudos
368 Views
mjbcswitzerland
Specialist V

Hi

Here is a reference for configuration of CANopen:

#define CANOPEN_RX_NODE_ID                  0x7a                         // we receive this node-ID
#define CANOPEN_TX_NODE_ID                  0x37                         // this is the node-ID that 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.Task_to_wake = OWN_TASK;                              // wake us on buffer events
    tCANParameters.Channel = CANopen_CHANNEL;                            // CAN interface
    tCANParameters.ulSpeed = 250000;                                     // 250k speed
    tCANParameters.ulTxID = (121);                                       // 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 | 0x7f);                     // 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
    tCANParameters.ulRxID = 0;                                           // broadcast address
    tCANParameters.ulRxIDMask = CAN_STANDARD_MASK;                       // accept ID 0
    tCANParameters.ucTxBuffers = 0;
    tCANParameters.ucRxBuffers = 1;
    fnConfigCAN(CANopenHandle, &tCANParameters);                         // configure 1 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 buffer for this logical channel
    return CANopenHandle;                                                // return CAN interface handle
}


It configures for exact matches on the extended ID 0x8yy7a, standard ID 0xyy7a and broadcasts on standard 0xyy00 ID (where yy is not checked).

The driver writes these register values to achieve this (as well as handling all other configuration details):
CANx_RX15MASK = 0x0008007f;
ID entry in the rx15 buffer = 0x0008007a;

Noting that the buffers (in memory) are defined as
typedef struct stCAN_BUF
{
volatile unsigned long ulCode_Len_TimeStamp;
volatile unsigned long ulID;
volatile unsigned long ulData[2];
} CAN_BUF;

CANx_RX14MASK = 0x1ffc0000;
ID entry in the rx14 buffer = 0x00000000;
CANx_RXGMASK = 0x01fc0000;
ID entry in the rx13 buffer = 0x01e80000;

In this case there are just 3 rx buffers used and each buffer receives only the ID matching it (so the type of content is known directly based on the buffer interrupt).

In your case I would probably configure using (assuming standard IDs):

static QUEUE_HANDLE fnInitCANInterface(void)
{
    CANTABLE tCANParameters;                                             // table for passing information to driver
    QUEUE_HANDLE CANopenHandle;

    tCANParameters.Task_to_wake = OWN_TASK;                              // wake us on buffer events
    tCANParameters.Channel = CANopen_CHANNEL;                            // CAN interface
    tCANParameters.ulSpeed = 250000;                                     // 250k speed
    tCANParameters.usMode = 0;                                           // use normal mode
    tCANParameters.ulTxID = (121);                                       // default ID of destination (not used by CANopen)
    tCANParameters.ulRxID = 0x200;                                       // ID 0x200
    tCANParameters.ulRxIDMask = CAN_STANDARD_MASK;                       // accept only exact ID match
    tCANParameters.ucTxBuffers = 0;
    tCANParameters.ucRxBuffers = 2;
    CANopenHandle = fnOpen(TYPE_CAN, FOR_I_O, &tCANParameters);          // open CAN interface and  configure 2 buffers for this logical channel
    tCANParameters.ulRxID = (0x1ff);                                     // extended node ID that we receive
    tCANParameters.ulRxIDMask = (~0x1ff);                                // receive standard addresses 0x00..0x1ff
    tCANParameters.ucTxBuffers = 2;                                      // assign two tx buffers for use
    tCANParameters.ucRxBuffers = 13;                                     // assign 13 rx buffers this range
    fnConfigCAN(CANopenHandle, &tCANParameters);                         // configure 13 buffer for this logical channel
    return CANopenHandle;                                                // return CAN interface handle
}



Meaning that it writes
CANx_RX15MASK = 0x1ffc0000;
ID entry in the rx15 buffer = 0x08000000;
CANx_RX14MASK = 0x1ffc0000;
ID entry in the rx14 buffer = 0x08000000;
CANx_RXGMASK = 0x18000000;
ID entries in the rx0..rx13 buffers = 0x07fc0000;

The result will be that ID 0x200 is received in buffers 14 or 15 and all other IDs in the range 0x00..0x1ff are received in the buffers 0..13. [hint: the buffers are allocated form 15 down to 0 due to the fact that the first two have their own masks and then subsequent ones share a single one].

Based on these values you should be able to modify your configuration to achieve the same.

Regards

Mark







0 Kudos
359 Views
alvarolopes
Contributor III

Mark,

Thank you for being so helpful.

I am using CAN drivers from MCUXpresso IDE. Using these drivers and reading your tips I solve my problem like this:

 

CAN INITIALIZATION:


flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;
uint64_t flag = 1U;

    //Clock setting for FLEXCAN
    CLOCK_SetMux(kCLOCK_CanMux, FLEXCAN_CLOCK_SOURCE_SELECT);
    CLOCK_SetDiv(kCLOCK_CanDiv, FLEXCAN_CLOCK_SOURCE_DIVIDER);

    LOG_INFO("********** CAN DEFINITIONS *************\r\n");
    LOG_INFO("\r\n");
    LOG_INFO("    Message format: Standard (11 bit id)\r\n");
    LOG_INFO("    Message buffer %d used for Rx.\r\n", RX_MESSAGE_BUFFER_NUM);
    LOG_INFO("    Message buffer %d used for Tx.\r\n", TX_MESSAGE_BUFFER_NUM);
    LOG_INFO("    Interrupt Mode: Enabled\r\n");
    LOG_INFO("    Operation Mode: TX and RX --> Normal\r\n");
    LOG_INFO("\r\n");
    LOG_INFO("*****************************************\r\n\r\n");

    //Rx ID
    rxIdentifier = 0x100;
    rxIdentifier1 = 0x200;

    //Get FlexCAN module default Configuration.

    // flexcanConfig.clkSrc                             = kFLEXCAN_ClkSrc0;
     // flexcanConfig.baudRate                      = 1000000U;
     // flexcanConfig.baudRateFD                 = 2000000U;
     // flexcanConfig.maxMbNum                  = 16;
     // flexcanConfig.enableLoopBack           = false;
     // flexcanConfig.enableSelfWakeup        = false;
     // flexcanConfig.enableIndividMask         = false;
     // flexcanConfig.disableSelfReception     = false;
     // flexcanConfig.enableListenOnlyMode  = false;
     // flexcanConfig.enableDoze                    = false;

    FLEXCAN_GetDefaultConfig(&flexcanConfig);

    flexcanConfig.bitRate = CAN_SPEED;
    flexcanConfig.baudRate = CAN_SPEED;

    flexcan_timing_config_t timing_config;
    memset(&timing_config, 0, sizeof(flexcan_timing_config_t));

    if (FLEXCAN_CalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.baudRate, EXAMPLE_CAN_CLK_FREQ, &timing_config))
    {
        //Update the improved timing configuration
        memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
    }
    else
    {
        LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
    }

    FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ);

    mbConfig.format = kFLEXCAN_FrameFormatStandard;
    mbConfig.type   = kFLEXCAN_FrameTypeData;
    mbConfig.id     = FLEXCAN_ID_STD(rxIdentifier);

    //Here I am using filter, RX_MESSAGE_BUFFER_NUM1 accept from ID 0x100 to 0x1FF

    FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));

    //Configure Mailbox
    FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);

    //Set rxIdentifier1 Masking mechanism.

    //No filter here, RX_MESSAGE_BUFFER_NUM1 accept only ID 0x200

    mbConfig.format = kFLEXCAN_FrameFormatStandard;
    mbConfig.type   = kFLEXCAN_FrameTypeData;
    mbConfig.id     = FLEXCAN_ID_STD(rxIdentifier1);

    //Configure Mailbox
    FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM1, &mbConfig, true);

    //Configure interruption
    FLEXCAN_EnableMbInterrupts(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM);
    FLEXCAN_EnableMbInterrupts(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM1);

   //Enable interrupts
   (void)EnableIRQ(EXAMPLE_CAN_IRQn);

 

CAN INTERRUPTION

uint64_t flag = 1U;

    //If new data arrived
    if (0U != FLEXCAN_GetMbStatusFlags(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM))
    {
        FLEXCAN_ClearMbStatusFlags(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM);
        (void)FLEXCAN_ReadRxMb(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &rxFrame);

        rxComplete = true;
    }

    //If new data arrived
    if (0U != FLEXCAN_GetMbStatusFlags(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM1))
    {
        FLEXCAN_ClearMbStatusFlags(EXAMPLE_CAN, flag << RX_MESSAGE_BUFFER_NUM1);
        (void)FLEXCAN_ReadRxMb(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM1, &rxFrame1);

        rxComplete = true;
    }

    SDK_ISR_EXIT_BARRIER;

 

One more time, thanks a lot. 

Regards,

Alvaro

0 Kudos
375 Views
mjbcswitzerland
Specialist V

Hi

There are three filter masks (CAN_MBUFF15, CAN_MBUFF14  and CAN_RXGMASK)

which can be used to control the ID match range accepted by the message buffers.

Therefore, in order to match a range 0x100 to 0x200 (inclusive) you could use general message buffers for 0x00001xx (allowing 0x00100..0x001ff) and a single buffer for the specific 0x00200 ID.

Regards

Mark (uTasker project lead)

See the uTasker project for CAN and CANopen for i.MX RT 10xx: https://www.utasker.com/index.html

For our discounted i.MX and Kinetis stock availability see https://www.utasker.com/Shop/semi.html

0 Kudos