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.
Solved! Go to Solution.
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
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!
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
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
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