Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can Filters #34

Open
Wh1terat opened this issue Jan 16, 2021 · 17 comments
Open

Can Filters #34

Wh1terat opened this issue Jan 16, 2021 · 17 comments

Comments

@Wh1terat
Copy link

Wh1terat commented Jan 16, 2021

Hi,
Firstly - thank you for the project, very nicely documented.

Just wondering if you have some examples for CANSetFilter ?
I'm trying to filter messages from ID 0x681 AND the first byte of the message 0x03

So this works fine for filtering all messages from 0x681

  CANSetFilter(0, 1, 0, 0, 0x681 << 21, 0xFFE00000);

So I expected this would work for what I was trying to achieve:

  CANSetFilter(0, 1, 0, 0, 0x68103 << 13, 0xFFFFE000);

But I'm still receiving all messages to 0x681 with this which is odd.

@nopnop2002
Copy link
Owner

nopnop2002 commented Jan 17, 2021

Hello.

0x681 << 21 = 0xd0200000

0x68103 << 13 = 0xd0206000

The extended format 29-bit length ID range is 0x0 to 0x1FFFFFFF
0xd0206000 is out of range.

Filter bank format is:
https://www.st.com/resource/en/reference_manual/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

FilterBank

@Wh1terat
Copy link
Author

Wh1terat commented Jan 19, 2021

Thanks for reply.

Yes I understand it's 29bit for extended or 11bit for standard.
But unlike mcp2515, stm32 filter seems to read from MSB, not MSB+3.

11010000 00100000 00000000 00000000

Because this works to filter 0x681.

Infact, you can even see this in your own code from CANReceive function:

      out = ((CAN_tx_msg->id & CAN_STD_ID_MASK) << 21U);

Edit:

To clarify what I'm asking, is it possible to filter the first 2 data bytes of a standard frame using the 32bit filters?
As data bytes 1 & 2 would be in the same position as EXTID[12:0]+IDE+RTE

@nopnop2002
Copy link
Owner

nopnop2002 commented Jan 19, 2021

is it possible to filter the first 2 data bytes of a standard frame using the 32bit filters?

The Filter bank register has 28 FiR1 and 28 FiR2 respectively.

F0R1-F27R1
F0R2-F27R2

Standard frame filter:

Set the first filter to F0R1
Set a second filter on F0R2

F0R1=first filter data
F0R2=second filter data
CANSetFilter(0, 0, 1, 0, F0R1, F0R2) 

@Wh1terat
Copy link
Author

Wh1terat commented Jan 19, 2021

That is simply using list mode rather than mask mode to match multiple IDs ?

To explain my problem more clearly, Can ID 0x681 sends constant keepalive messages every 500ms, first byte of data ID is 0xF0.

I am only interested in messages where first byte of data is 0x04 - because of the frequency of the keepalive messages it makes ISR unsuitable.

With MCP2515's filter I am able to filter the ID and first 2 bytes of a standard frame, trying to replicate this functionality using STM32.

@nopnop2002
Copy link
Owner

nopnop2002 commented Jan 19, 2021

Standard frame filter Identifier List mode:

F0R1=1st id & 2nd id
F0R2=3rd id & 4th id
CANSetFilter(0, 0, 1, 0, F0R1, F0R2) 

Standard frame filter Identifier Mask mode:

F0R1=1st id & 2nd id
F0R2=1st mask & 2nd mask
CANSetFilter(0, 0, 0, 0, F0R1, F0R2) 

Extended frame filter Identifier List mode:

F0R1=1st id
F0R2=2nd id
CANSetFilter(0, 1, 1, 0, F0R1, F0R2) 

Extended frame filter Identifier Mask mode:

F0R1=1st id
F0R2=1st mask
CANSetFilter(0, 1, 0, 0, F0R1, F0R2) 

@Wh1terat
Copy link
Author

Thank you for trying to help, but I think maybe I am being unclear about my issue or what I am trying to achieve - or maybe it is not even possible.

@Elektrik1
Copy link

Elektrik1 commented Mar 16, 2021

Same issue here, transitioning from MCP2515, it is completely unclear how to configure CANSetFilter to allow particular (or range) of ID`s, also it's unclear how to filter on 0,1,2..n bytes of data, for example filter only particular (or range) where data[0] or data[n] corresponds.

For example: I want to allow only packets with ID=0x101 and data[0]=0x6B. How to set the filter?
Tried this, no success:
CANSetFilter(0, 1, 0, 0, 0x101 << 21, 0x6B << 24);

@nopnop2002
Copy link
Owner

nopnop2002 commented Mar 16, 2021

From RM0008 Reference manual

24.4.1 Initialization mode

The software initialization can be done while the hardware is in Initialization mode. To enter
this mode the software sets the INRQ bit in the CAN_MCR register and waits until the
hardware has confirmed the request by setting the INAK bit in the CAN_MSR register.
To leave Initialization mode, the software clears the INRQ bit. bxCAN has left Initialization
mode once the INAK bit has been cleared by hardware.
While in Initialization Mode, all message transfers to and from the CAN bus are stopped and
the status of the CAN bus output CANTX is recessive (high).
Entering Initialization Mode does not change any of the configuration registers.
To initialize the CAN Controller, software has to set up the Bit Timing (CAN_BTR) and CAN
options (CAN_MCR) registers.

To initialize the registers associated with the CAN filter banks (mode, scale, FIFO
assignment, activation and filter values), software has to set the FINIT bit (CAN_FMR). Filter
initialization also can be done outside the initialization mode.

Case of STM32F103:

  // Configure Filters to default values
  CAN1->FMR  |=   0x1UL;                // Set to filter initialization mode
  CAN1->FMR  &= 0xFFFFC0FF;             // Clear CAN2 start bank

  // bxCAN has 28 filters.
  // These filters are used for both CAN1 and CAN2.
  // STM32F103 has only CAN1, so all 28 are used for CAN1
  CAN1->FMR  |= 0x1C << 8;              // Assign all filters to CAN1

  // Set fileter 0
  // Single 32-bit scale configuration 
  // Two 32-bit registers of filter bank x are in Identifier Mask mode
  // Filter assigned to FIFO 0 
  // Filter bank register to all 0
  CANSetFilter(0, 1, 0, 0, 0x0UL, 0x0UL); 
  
  CAN1->FMR   &= ~(0x1UL);              // Deactivate initialization mode

@va7wv
Copy link

va7wv commented May 13, 2022

I don't understand this either. I want to filter only 7E8 diagnostic response messages from OBDII.

No go even when directly editing the code as highlighted in the previous response:

CANSetFilter(0, 1, 0, 0, 0x7E8, 0x7E8);

@nopnop2002
Copy link
Owner

nopnop2002 commented May 13, 2022

FilterBank

FilterBank

If you want to filter only ID=0x7E8

  • for STD ID Data Frame
  uint32_t bank1, bank2;
  bank1 = 0x7E8 << 21;
  bank2 = 0xFFE00006; // Must be IDE=0 RTR=0
  CANSetFilter(0, 1, 0, 0, bank1, bank2);
  • for STD ID Remote Frame
  uint32_t bank1, bank2;
  bank1 = 0x7E8 << 21;
  bank1 = bank1 + 0x02; // Remote
  bank2 = 0xFFE00006; // Must be IDE=0 RTR=1
  CANSetFilter(0, 1, 0, 0, bank1, bank2);
  • for STD ID Any Frame
  uint32_t bank1, bank2;
  bank1 = 0x7E8 << 21;
  bank2 = 0xFFE00004; // Must be IDE=0
  CANSetFilter(0, 1, 0, 0, bank1, bank2);
  • for EXT ID Data Frame
  uint32_t bank1, bank2;
  bank1 = 0x7E8 << 3;
  bank1 = bank1 + 0x04; // Ext
  bank2 = 0xFFFFFFFE; // Must be IDE=1 RTR=0
  CANSetFilter(0, 1, 0, 0, bank1, bank2);
  • for EXT ID Remote Frame
  uint32_t bank1, bank2;
  bank1 = 0x7E8 << 3;
  bank1 = bank1 + 0x06; // Ext + Remote
  bank2 = 0xFFFFFFFE; // Must be IDE=1 RTR=1
  CANSetFilter(0, 1, 0, 0, bank1, bank2);
  • for EXT ID Any Frame
  uint32_t bank1, bank2;
  bank1 = 0x7E8 << 3;
  bank1 = bank1 + 0x04; // Ext
  bank2 = 0xFFFFFFFC; // Must be IDE=1
  CANSetFilter(0, 1, 0, 0, bank1, bank2);

Mask bit0 indicates that you don't care.

Mask bit1 indicates that you care.

@v-ivanyshyn
Copy link

v-ivanyshyn commented Dec 21, 2022

If anyone still struggles with setting up filters in list mode for 16bit IDs, here is how it should look:

uint32_t bank1 = (filterId1<<21) | (filterId2<<5);
uint32_t bank2 = (filterId3<<21) | (filterId4<<5);

@rmoscoloni
Copy link

rmoscoloni commented Mar 10, 2023

Please, could i ask how can i filter a range of std ids? ie 0 to 7?, list mode from v-ivanyshyn works well, but im getting confused by bitshift places. for mask mode.

I cant get why bank 2 is 0xFFE00006 In the example above:

uint32_t bank1, bank2;
bank1 = 0x7E8 << 21;
bank2 = 0xFFE00006; // Must be IDE=0 RTR=0
CANSetFilter(0, 1, 0, 0, bank1, bank2);

@nopnop2002
Copy link
Owner

nopnop2002 commented Mar 10, 2023

I cant get why bank 2 is 0xFFE00006 In the example above:

About STM32 CAN Identifier Filtering

https://schulz-m.github.io/2017/03/23/stm32-can-id-filter/

@rmoscoloni
Copy link

rmoscoloni commented Mar 13, 2023

Thanks for the answer nopnop2002:
first I have to thank you for the code you have made and shared, thank you very much!
Have the link bookmarked for a long time and I wanted to follow the example of filtering from 0 to 7 but in std id.
I was trying to understand how to include in your code to filter the mentioned range.

Answering my own question and for reference to future readers,
0xFFE00006 --> 0x7ff << 21 + 0x06
11111111111000000000000000000000+
00000000000000000000000000000110=
11111111111000000000000000000110

why include 0x06 in the filter? 0x7ff<<21 is not enough?

@nopnop2002
Copy link
Owner

nopnop2002 commented Mar 13, 2023

why include 0x06 in the filter? 0x7ff<<21 is not enough?

This is because IDE and RTR are used to distinguish between frame types.

Bit 2 IDE: Identifier extension
This bit defines the identifier type of message in the mailbox.
0: Standard identifier.
1: Extended identifier.
Bit 1 RTR: Remote transmission request
0: Data frame
1: Remote frame

|<------->| Can ID for Standard
|<------------------------->| Can ID for Extended
11111111111000000000000000000110
                             ||
                             |+-->RTR
                             +-->IDE
                                                        

There are 4 frames type

  • Standard identifier & data frame (IDE=0 RTR=0)
  • Standard identifier & remote frame (IDE=0 RTR=1)
  • Extended identifier & data frame (IDE=1 RTR=0)
  • Extended identifier & remote frame (IDE=1 RTR=1)

If you don't include 0x06 in your filter, these will match

ID=0x467 and ID=0x119C000 pass the filter even though only ID=0x467 is needed.

   ID=100-0110-0111=0x467
<----------->
1000 1100 1110 0000 0000 0000 0000 0000 // Standard data frame

   ID=0x467
<----------->
1000 1100 1110 0000 0000 0000 0000 0010 // Standard remote frame

   ID=1-0001-1001-1100-0000-0000-0000==0x119C000
<---------------------------------->
1000 1100 1110 0000 0000 0000 0000 0100 // Extended data frame

   ID=0x119C000
<---------------------------------->
1000 1100 1110 0000 0000 0000 0000 0110 // Extended remote frame

168242049-5020bdec-d6b6-4279-bf89-151da9c5526f

@martin323232
Copy link

Having issues with filter settings,

receiving id 0x101 and 0x206, how to setup a filter to just receive these messages.

Tried :

uint32_t bank1 = (0x101<<21) | (0x206<<5);
uint32_t bank2 = (0x0<<21) | (0x0<<5);

CANSetFilter(0, 0, 1, 0, bank1, bank2);
uint32_t bank1 = (0x101<<21) | (0x101<<5);
uint32_t bank2 = (0x206<<21) | (0x206<<5);

CANSetFilter(0, 0, 1, 0, bank1, bank2);

@nopnop2002
Copy link
Owner

nopnop2002 commented Oct 31, 2023

Case of STM32F103:

CAN1->FMR  |=   0x1UL;                // Set to filter initialization mode

fileter setting

CAN1->FMR   &= ~(0x1UL);              // Deactivate initialization mode

Otherwise: Look at the source.

FilterBank

/*
Bit IDE: Identifier extension
This bit defines the identifier type of message in the mailbox.
0: Standard identifier.
1: Extended identifier.
Bit RTR: Remote transmission request
0: Data frame
1: Remote frame
*/

int IDE1=0;
int IDE2=0;
int IDE3=0;
int IDE4=0;
int RTR1=0or1;
int RTR2=0or1;
int RTR3=0or1;
int RTR4=0or1;

uint32_t bank1 = (STID1<<21) | (RTR1<<20) | (IDE1<<19) | (STID2<<5) | (RTR2<<4) | (IDE2<<3);
uint32_t bank2 = (STID3<<21) | (RTR3<<20) | (IDE3<<19) | (STID4<<5) | (RTR4<<4) | (IDE4<<3);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants