cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 config CAN Filters

Posted on July 26, 2016 at 14:35

Hello there,

For a while now I am trying to configure the CAN filter system to work properly in STM32F4 I have managed to make the system work the way that I have 2 mask filters. Depending on which the CAN ID message is received through FIFO0 or FIFO1. So it seems to be working properly. But not quite... In the HAL CAN RX interrupt routine the filter hit is checked (FMI part from CAN_RDTxR register). Even though messages come to the proper FIFO, the FMI part is always 0. I started playing with the filter ID configuration and FMI started to change, but still it didnt reflect my configured filter number at any point. This is my configuration code:

/**
* @brief Configures the Can receiving filter.
* Filter should cover the lower part of upper 16 bit mask and filter.
* @param canData: Pointer to a can conf struct, preconfigured.
* @return HAL_OK if all ok.
*/
HAL_StatusTypeDef can_ConfigRxFilter(canData_t* canData)
{
assert_param(canData);
assert_param(canData->canHandle);
HAL_StatusTypeDef retVal = HAL_OK;
CAN_FilterConfTypeDef sFilterConfig;
// First config unicast filter
sFilterConfig.FilterNumber = canData->objectId;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
// TML CAN
uint32_t EXID = canData->canAxisId << 
13
;
uint32_t 
STID
= 
EXID
& 0x7FF;
uint32_t 
EXMASK
= 
0xFF
<< 13;
uint32_t 
STMASK
= 
EXMASK
& 0x7FF;
sFilterConfig.FilterIdHigh = (uint16_t)(((STID << 5) & 0xFFE0) | ((EXID >> 13) & 0x001F));
sFilterConfig.FilterIdLow = (uint16_t)(((EXID << 
3
) & 0xFFF8));
sFilterConfig.FilterMaskIdHigh = (uint16_t)(((STMASK << 5) & 0xFFE0) | ((EXMASK >> 13) & 0x001F));
sFilterConfig.FilterMaskIdLow = (uint16_t)(((EXMASK << 
3
) & 0xFFF8));
sFilterConfig.FilterFIFOAssignment
= 
canData
->canRxFifo;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 0;
retVal += HAL_CAN_ConfigFilter(canData->canHandle, &sFilterConfig);
assert_param(!retVal);
return retVal;
}

This function is run twice. Once for canData->objectId = 0 (received message should have FMI = 0) and once for canData->objectId = 1 (FMI should be 1). Maybe it has something to do with the BankNumber, this is not very clear for me. I would appreciate all help regarding the configuration.
23 REPLIES 23
Posted on July 26, 2016 at 14:47

    uint32_t EXID  = canData->canAxisId << 13;

    uint32_t STID  = EXID & 0x7FF;

STID is *ALWAYS* zero!!

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 26, 2016 at 14:50

    uint32_t EXMASK = 0xFF << 13;

    uint32_t STMASK  = EXMASK & 0x7FF;

STMASK is always zero, who wrote this?
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 26, 2016 at 15:05

Those values can be 0, I just wrote it this way to remember the shifting needed for a certain mechanism. The important part to filter resides in the extended ID part (

https://www.dropbox.com/s/njyc0p2gpcutxfm/Zrzut%20ekranu%202016-07-26%png?dl=0

). I only need to filter out either axis ID is matching. For example if its 6, I receive it in FIFO0, if its 5 I receive it in FIFO1. And it works with the provided code. For example, CAN frames with this EXT ID go to the FIFO0 (AXIS ID = 6):

0x400C173
0x400C007
0x400C006
0x400C008

Those go to FIFO1 (AXIS ID = 5):

0x400A173
0x400A007
0x400A006
0x400A008

But even though, FMI when received can message is 0 for both situations, instead of 0 for FIFO0 and 1 for FIFO1.
Posted on July 26, 2016 at 15:21

Those values can be 0...

Really? Kind of defeats the point of filtering at a message level. Then you're surprised that a filter that passes everything always flags as the one taking the message? Look very carefully at the filters you are programing into the controller.

if ((WireData & MASK) == ID) TAKE;

if (0 == 0) // always true

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 26, 2016 at 15:28

I would say it defeats the need. The thing is that the data I want to filter are in ext ID part. for example, I want to TAKE every message that has number 0xA000 in the 29 bit ID. For this STD ID can be zero, because the value I check is above 11 bit length.

So for FIFO0:

expected ID: 5 << 13;

mask for expected ID: 0xFF << 13;

For FIFO1:

expected ID: 6 << 13;

mask for expected ID: 0xFF << 13;
Posted on July 26, 2016 at 15:39

I am not sure If I understand correctly? You mean that even though I operate only at extended ID part, the std ID part cannot be zero?

The filters seem to work because the messages are correctly distributed to FIFO0 and FIFO1. Do you mean that even though that, the message passes through only first filter?
Posted on July 26, 2016 at 15:46

For testing I have only left 1 FIFO and filter working. I have noticed that FMI for the received message equal my filter number set multiplied by 2... So when I set filter number to 1 in the code from the 1st post, FMI is 2, for filter number 2, FMI is 4 etc. Does this give you any hints what could be going on here?

EDIT: I am experiencing the exact results as described by this user

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/STM32%20CAN%20Filter&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=2587

For FIFO0 FMI is doubled and for FIFO1 FMI is always 0...

Posted on July 26, 2016 at 17:49

I don't see any errata for the CAN peripheral, you'd be better digging into the Third Party IP vendor's documentation to understand the internal mechanics. bxCAN - IPMS/CAST

The obvious reason it would be 2x is that the filtering can be done at a 16-bit level, and you'd want to be able to identify if the low or high order filter was being used when sieving the data.

The RM suggests it might be more complex, perhaps more so than the silicon is.

''The index value of the filter number does not take into account the activation state of the

 

filter banks. In addition, two independent numbering schemes are used, one for each FIFO. Refer to Figure 343 for an example.''

Remember, this isn't ST's IP, these docs are a re-interpretation by some technical writers, and IC guys, who may never have actually used CAN

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 26, 2016 at 19:56

The obvious reason it would be 2x is that the filtering can be done at a 16-bit level, and you'd want to be able to identify if the low or high order filter was being used when sieving the data.

 

 

I am not sure I understand. What is low/high order filter for CAN peripheral?

As for the Figure 343 from RM, it is extremely unclear to me. I cant figure out from it why would IFM for FIFO1 always be 0.

Tomorrow morning I will try to go deeper into the document you suggested. Thank you.

Also for example, is it possible to configure the filters in a way, that when a message comes it falls into FIFO0 and well as FIFO1, to two independently configured filters? I cannot seem to get that functionality as well. If I define two filters (same way) one for FIFO0 and one for FIFO1, the message comes only once, instead of 2 times for each FIFO.