Skip to main content
Stepan Podhorsky
Associate II
August 15, 2017
Question

CAN messages filtering

  • August 15, 2017
  • 3 replies
  • 5705 views
Posted on August 15, 2017 at 14:16

Hello,

I have been developing control software based on STM32F207 and I have been using

CAN interface for communication. There are several messages with different IDs 

on the CAN bus which my software is interested in. I know that I have to

configure the CAN receiving filters but I don't know what is the better solution.

Shall I configure several filters for exact match of message identifier or shall

I configure only one filter with more general mask setting to receive more messages.

Thanks for any suggestions.

#stm32f2 #can
This topic has been closed for replies.

3 replies

valentin
Associate III
August 15, 2017
Posted on August 15, 2017 at 22:28

It depends. Are there any messages on the bus you're not interested in? Then you can create as few filters as possible to ignore those.

Or do you want to have specific messages routed to fifo0 and others to fifo1? Then you need to set up more filters and do that.

Filtering only gets really important when you have a very high bus load, very little cpu resources and are only interested in a small subset of the messages and want to do priority sorting by using the two fifos.

In short: Just start by accepting them all and see how your system handles it.

Stepan Podhorsky
Associate II
August 15, 2017
Posted on August 15, 2017 at 23:01

Hello Valentin,

thank you for your reaction. I am interested in only three message IDs so I have configured three filters for exact ID match. It seems to be functional. I have also thought about one filter configuration with a mask. The IDs I am interested in are 0x610, 0x660 and 0x6C1. I wasn't able to invent a mask only for these three IDs. Please can you tell me what are the c

onsequences to program processing speed in case I have three filters configured and in case I have only one filter configured

? Thanks.
valentin
Associate III
August 15, 2017
Posted on August 15, 2017 at 23:10

The filters are hardware, so there is no impact on your processing speed whatsoever. It doesn't make a difference whether you use a mask or set up individual filters. Until you run out of filter banks it doesn't.

Here's a little code snippet I'm using from my personal can filter library. You can use these two functions to calculate the settings for the ID and MASK registers if you want to filter certain ID ranges.

/**
 * Calculates a mask to mask out all numbers outside id_min & id_max as good as possible.
 * This usually leads to masking out all numbers greater than the closest power of 2 of id_max.
 * Still, all combinations are checked.
 *
 * The criteria applied to keep a received frame is as follows: (received ID) AND (ID mask) = (ID arbitration), where AND is a bitwise operator.
 * A way to define a range by using these registers is to fill the MASK one with
 * (~((id_high) - (id_low)))
 * and the ID one with
 * ((id_low) & (id_high)).
 * Consequently, for id_low, it is generally better to choose a value with some LSBs cleared,
 * and for id_high a value that “logically contains�? id_low and with the same LSBs set. Example: the range 0x100-0x3FF
 * will work, but the range 0x100-0x2FF will not because 0x100 is not logically contained in 0x2FF (i.e. 0x100 & 0x2FF = 0).
 *
 * Note: (id_min & id_max) != 0
 *
 * Note 2: id_max-id_min needs to be increased to the next pow(2) - 1
 * This allows too many ids to pass and slightly increases cpu load but that's better than missing some wanted messages!
 *
 * @param id_minMinimum allowed ID (Std or Ext)
 * @param id_maxMax allowed ID
 * @returnRaw 32 bit mask. Not shifted, no IDE or RTR care bits set. In case of error: 0xFFFFFFFF -> id_min is not logically contained in id_max!
 */
uint32_t can_calc_range_mask(uint32_t id_min, uint32_t id_max) {
if (id_min >= id_max) {
return 0xffffffff;
}
/*
 * Round id_max-id_min up to next highest power of 2 - 1
 * -> https://community.st.com/external-link.jspa?url=http%3A%2F%2Fgraphics.stanford.edu%2F%7Eseander%2Fbithacks.html%23RoundUpPowerOf2Float
 */
uint32_t tmp = id_max - id_min;
tmp |= tmp >> 1;
tmp |= tmp >> 2;
tmp |= tmp >> 4;
tmp |= tmp >> 8;
tmp |= tmp >> 16;
id_max = id_min + tmp;
assert_param((id_min & id_max) != 0);
if ((id_min & id_max) == 0) {
// id_min not logically contained in id_max -> problem
/*
 * 0xFFFFFFFF should never be used in mask mode as this filters only ONE id for which list mode should be used.
 * Therefore this value now becomes an error flag.
 */
return 0xffffffff;
} else
return ~((id_max) - (id_min));
}
/**
 * Calculates the ID register for filtering a range of IDs.
 * See can_calc_range_mask for description of algorithm.
 *
 * Note: (id_min & id_max) != 0
 *
 * @param id_minMinimum allowed ID (Std or Ext)
 * @param id_maxMax allowed ID
 * @returnRaw 32 bit ID register value. Not shifted, no IDE or RTR care bits set.
 */
uint32_t can_calc_range_ID(uint32_t id_min, uint32_t id_max) {
assert_param((id_min & id_max) != 0); // catch here for now.
if ((id_min & id_max) == 0 || id_min >= id_max) {
// id_min not logically contained in id_max -> problem
/*
 * 0xFFFFFFFF should never be used in mask mode as this filters only ONE id for which list mode should be used.
 * Therefore this becomes an error flag.
 */
return 0xffffffff;
} else
return ((id_min) & (id_max));
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Enjoy!

Stepan Podhorsky
Associate II
August 16, 2017
Posted on August 16, 2017 at 19:29

Valentine, thank you very much for the code snippet you have added. It is very useful for me.

valentin
Associate III
August 18, 2017
Posted on August 18, 2017 at 05:08

Clive's reply got me thinking though. I'm currently working on improving my algorithm so that it doesn't matter any more which id_min and id_max I enter. It should always create a filter set so that at least

:(

all desired IDs pass.

That is only the case with Clive's method, not with mine. Let's see whether I can merge them