FlexCAN_T4 - FlexCAN for Teensy 4

for different bitrates in FD mode, there is an advanced setbaudrate function which allows different timings for the same bitrates, try using that to try a different timing than the default. you can select the one you want, and it has a layout displayed in serial monitor :)

also don't forget about setting the clock rate of flexcan if needed
 
Well, here's what is going on (and it seems strange to me). I have two devices set up for CAN-FD testing. One is a Teensy MicroMod running though an MCP2562FD transceiver. This is connected to an ESP32 driving an MCP2517FD that runs through an MCP2562FD. So, both the transceivers are the same. I try sending normal CAN then CAN-FD from each side to the other. Both sides can send CAN traffic to each other and it works fine. The ESP32 can send traffic to the TeensyMM perfectly fine. However, when the TeensyMM tries to send CAN-FD traffic the ESP32 side will fault like crazy giving me all sorts of bit errors, constantly resetting to try to fix the errors then the constant barrage of traffic faults it again, over and over. For some reason the MCP2517FD chip just hates the traffic coming from the TeensyMM when it is a CAN-FD frame. I find this peculiar because the traffic works bidirectionally for CAN traffic and one direction for CAN-FD but not the other. I've looked at it with a logic analyzer and it looks like CAN-FD traffic either direction. I believe the CAN fault happens right after the CRC and it almost makes me think that the two sides might be disagreeing on whether a given frame needs CRC15, 17, or 21. That is supposed to be set in stone but the fault happens around the end of CRC so... maybe? I thought it might be nice if the Teensy didn't spam the bus so that I could test with single instances of the message. But, in practice it would not ordinarily be necessary to limit retries as a message should only very seldom fault and need a re-send.

The problem is, while I have a logic analyzer it doesn't interpret CAN-FD frames and I have no other FD capable tools so now I don't know which one is being silly. It sure sounds like you've tested the Teensy code against other CAN-FD devices, right? In that case it would seem to be a fault on my ESP32 side that makes it reject the frames from the Teensy improperly. But, the question is why? I've been working on creating a C++ plugin for Saleae Logic to make it interpret CAN-FD traffic. Of course, then I'd have three devices where I wrote the code and then I'm not really a lot further along as this whole thing could be (and likely is) all my fault and adding another thing I wrote may not help me point fingers any better. All I know is that the ESP32 rejects CAN-FD traffic from the Teensy. But, I have no proof that either of them would have trouble talking to different hardware. I have a very new car but it still doesn't use CAN-FD.

So, I wonder who has used FlexCAN_T4 in FD mode with external hardware and what their experience has been.

There are actually two versions of CAN FD. ISO and non-ISO version. Check you are using the ISO version. The ISO version uses a different CRC checking.

Check you have set the BRS flag on in the MCP2517FD config.

If you are using the API library from Microchip chip then check you have these lines or something similar:

config.IsoCrcEnable = ISO_CRC;

txObj.bF.ctrl.BRS = 1; // Switch Bitrate true (switch to new data rate)
txObj.bF.ctrl.FDF = 1; // CAN FD true

I have a Teensy 3.2 demo using the MCP2517FD chip at:
https://github.com/skpang/Teensy32_with_MCP2517FD_CAN_FD_demo
 
If I run this on a Teensy 3.2

Code:
#include "FlexCAN_T4.h"
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> can1;

void setup() {
  Serial.begin(115200);
  while (!Serial) {}
  can1.begin();
  can1.setBaudRate(250000);
  can1.enableFIFO();
  can1.mailboxStatus();
}

I get the following output:

Code:
FIFO Enabled --> Interrupt Disabled
	FIFO Filters in use: 8
	Remaining Mailboxes: 8
		MB8 code: TX_INACTIVE
		MB9 code: TX_INACTIVE
		MB10 code: TX_INACTIVE
		MB11 code: TX_INACTIVE
		MB12 code: TX_INACTIVE
		MB13 code: TX_INACTIVE
		MB14 code: TX_INACTIVE
		MB15 code: TX_INACTIVE

Why are 8 filters already in use and what are they?
 
the 8 filters are there, doesn't mean theyre used or not. by default they accept all traffic, it's just to show that FIFO can set up to 8
 
the 8 filters are there, doesn't mean theyre used or not. by default they accept all traffic, it's just to show that FIFO can set up to 8

Based on message #905, I thought there were 32 filters available to setup. Did I misunderstand that? Thanks again.
 
change the RFFN value, there is a function for that, then enableFIFO, keep in mind 8 additional filters consume 2 mailboxes, so if you set max mailboxes to 16 and enable FIFO with 16 filters, you'll have 6 remaing TX mailboxes
 
change the RFFN value, there is a function for that, then enableFIFO, keep in mind 8 additional filters consume 2 mailboxes, so if you set max mailboxes to 16 and enable FIFO with 16 filters, you'll have 6 remaing TX mailboxes

If I do that with the following code:
Code:
#include <FlexCAN_T4.h>

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;
CAN_message_t msg;

void setup() {
  Serial.begin(115200);
  while (!Serial) {}
  can1.begin();
  can1.setBaudRate(1000000);
  can1.setRFFN(RFFN_32);
  can1.enableFIFO();  // enable FIFO
  can1.setMRP(0);  // prioritize FIFO
  can1.mailboxStatus();
}

void loop() {}

I'm only seeing 14 FIFO filters on a Teensy 4.0 (leaving two mailboxes so that I can still transmit messages):
Code:
FIFO Enabled --> Interrupt Disabled
	FIFO Filters in use: 14
	Remaining Mailboxes: 2
		MB14 code: TX_INACTIVE
		MB15 code: TX_INACTIVE

I get the same result on a Teensy 3.2. Is it expected that I can only get 14 FIFO filters on Teensy 3.x (leaving at least 1 mailbox for transmit)? Why am I not seeing all 64 mailboxes on Teensy 4.x?

EDIT: when I check the return value from setFIFOFilter it seems like using setRFFN is giving me the correct number of filters and mailboxStatus is just not reporting it correctly.
 
Last edited:
you need to setMaxMB for up to 64 mailboxes, it's possible the mailboxstatus may have a bug in reporting it if it doesnt return same value as setRFFN, but setRFFN cannot exceed the amount of available mailboxes, so try pushing up the mailbox limit first to 64 and see

setrffn will return correct value despite being limited by maxMB
 
Last edited:
A question on using masks, from this thread (https://www.microchip.com/forums/m456043.aspx), my expectation was setting a mask of 11111111100 (i.e. 0x7FC) and a filter of 0 would let through ID's 1, 2, 3. However, when I try this in the library with the FIFO, it only lets through ID 0. Any hints on what I'm doing wrong?

Code:
#include "FlexCAN_T4.h"

/* Loopback test on Teensy 3.6 can0 transmitting to can1 */

FlexCAN_T4<CAN0, RX_SIZE_8, TX_SIZE_256> can0;
FlexCAN_T4<CAN1, RX_SIZE_8, TX_SIZE_256> can1;

CAN_message_t tx_msg, rx_msg;

void irq(const CAN_message_t &ref) {
  Serial.print("Received ID: ");
  Serial.println(ref.id);
}

void setup() {
  Serial.begin(115200);
  while (!Serial) {}
  Serial.println("STARTING TEST");
  /* Enable the CAN transceivers */
  pinMode(26, OUTPUT);
  pinMode(27, OUTPUT);
  digitalWriteFast(26, LOW);
  digitalWriteFast(27, LOW);
  /* Start the CAN bus and set the baud */
  can0.begin();
  can0.setBaudRate(1000000);
  can1.begin();
  can1.setBaudRate(1000000);
  can1.setRFFN(RFFN_32); // 32 filters
  can1.enableFIFO();  // enable FIFO
  can1.setMRP(0);  // prioritize FIFO
  can1.enableFIFOInterrupt();
  can1.onReceive(FIFO, irq);
  can1.setFIFOFilter(REJECT_ALL);
  can1.setFIFOUserFilter(0, 0, 0x7FC, STD);


  for (int i = 0; i < 10; i++) {
    tx_msg.id = i;
    can0.write(tx_msg);
  }
}

void loop() {}

Output:

Code:
STARTING TEST
Received ID: 0
 
Those functions were added for J1939 protocol where first value is a group of ids and the 2nd value is the last bits to mask off, a user requested that, it's different than the filtering you want.

To dive deeper into what you want, if we use the automatic setMBFilter as an example:
Code:
Can0.setMBFilter(MB15, 1, 2, 3);

If we enable some debug prints, it will show that when a filter and mask is set, relevant bits in the ID/mask also include whether it is standard or extended, and it all affects the mask functionality. When you get to FIFO end, it is even more complex as the bits are all shifted, as well as partial masking for dual masks, it gets even more tricky.

The result output of the above at the hardware register is:
the ID of the mailbox is set to 0x40000
the MASK of the mailbox is set to 0x5FF00000
now if we reverse the IDs above from 1,2,3 to 3,2,1 we get:
the ID of the mailbox is set to 0xC0000
the MASK of the mailbox is set to 0x5FF00000

the whole ID is actually shifted for 11bits, and the mask bit 30 is set to let the mailbox accept specifically what it is set to STD/EXT

in either case, the set*UserFilters is used for J1939, and there is no other custom mask ability added yet, but there are automatic functions that calculate the mask for you for that purpose when you just specify the IDs you want, including ranges
 
Thanks! I really like the filtering by ID that you implemented, but I'm working on interfacing with a library, where the library is going to provide filter and mask pairs. I'll dig into the library a little to try to see what it would take to add, otherwise, emulating in software might be the easier approach.
 
take a look at the *MBFilterProcessing internal function, if you want to test your own masks being passed directly rather than the autocalculated call you can try that (for testing you can move that function in public of the class). Unfortunately for FIFO end, if you check out the what needs to be done to set masks and actually have them work, it's a little more effort involved.

if you really need a function for that i can work on one for you, but what name should I give a function for that? the UserFilter is for J1939 and don't want to change that as it'll break existing code for users who are currently using it
 
take a look at the *MBFilterProcessing internal function, if you want to test your own masks being passed directly rather than the autocalculated call you can try that (for testing you can move that function in public of the class). Unfortunately for FIFO end, if you check out the what needs to be done to set masks and actually have them work, it's a little more effort involved.

if you really need a function for that i can work on one for you, but what name should I give a function for that? the UserFilter is for J1939 and don't want to change that as it'll break existing code for users who are currently using it

Thanks, I'll take a look. It's for integration with Drone CAN, so it might be easier to change the Drone CAN side of things too. I'll dig around a bit.
 
I believe I hit a noob problem - been a while since last working on a c++ project :)

I want CAN buses to be accessible across the Arduino code (several files) so I can not simply declare and define them in the main (.ino) file.

What I tried:

can_bus.h
Code:
#ifndef CAN_BUS_H
#define CAN_BUS_H

#include <Arduino.h>
#include <FlexCAN_T4.h>

extern FlexCAN_T4<CAN1, RX_SIZE_8, TX_SIZE_8> Can0;
extern FlexCAN_T4<CAN2, RX_SIZE_8, TX_SIZE_8> Can1;

#endif

can_bus.cpp
Code:
FlexCAN_T4<CAN1, RX_SIZE_8, TX_SIZE_8> Can0;
FlexCAN_T4<CAN2, RX_SIZE_8, TX_SIZE_8> Can1;

Of course this doesn't really work. It actually does for initialization and reading,
but the code freezes as soon as i try to do a Can0.write().

I know that declaration in can_bus.h needs to be different but I'm not sure how.
Something to do with templated classes I guess...

For the moment my 'workaround' is to keep all CAN related code in the .ino file but that makes it bloated.

Any ideas? Thank you.
 
check out how isotp.h is done, it is a separate/independant plugin for FlexCAN_T4 to demonstrate how 3rd party libraries can use FlexCAN_T4.

Isotp code is also templated, however you can still apply it's use to non templated code as it uses a base class pointer to FlexCAN_T4, extern isn't required
 
check out how isotp.h is done, it is a separate/independant plugin for FlexCAN_T4 to demonstrate how 3rd party libraries can use FlexCAN_T4.

Isotp code is also templated, however you can still apply it's use to non templated code as it uses a base class pointer to FlexCAN_T4, extern isn't required

Thank you! Didn't think of that.
 
Advice on bad CANFD signal?

Running into a weird issue with the CAN3 CANFD transmission. I've got my script setup as below, most of it matches the documentation's examples, and I've got it set up to broadcast a message every 500 ms. The system works fine for CAN2.0, but when I try and do it using CANFD, the data seems to be getting garbled in output.

Code:
#include <FlexCAN_T4.h>
​
// Specify '1' for CANFD and '2' for CAN2.0
#define CAN_MODE            1
#define LOOP_INTERVAL       500
​
#define EN_SER              false
#define SER_BAUD_RATE       115200
​
#define EN_BROADCAST        true
#define CNT_REC             false
#define CNT_SEND            false
#define CANSNIFF            false
#define CAN_MAILBOX_STATUS  true
​
#define CAN_BAUD_RATE       1000000
​
#define FLASH_LED           true
#define LED_PIN             13
​
unsigned long last_time;
​
#if FLASH_LED == true
  bool led_state = false;
#endif
​
#if CNT_REC == true
  unsigned int rec_count = 0;
#endif
#if CNT_SEND == true
  unsigned int send_count = 0;
#endif 
​
#if CAN_MODE == 1
  typedef CANFD_message_t CAN_message;
  typedef FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_16> CAN_device;
#elif CAN_MODE == 2
  typedef CAN_message_t CAN_message;
  typedef FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> CAN_device;
#endif
​
CAN_device CanDevice;
CAN_message msg_frame;
​
void setup() {
  // put your setup code here, to run once:
  #if EN_SER == true
    Serial.begin(SER_BAUD_RATE);
    Serial.println("Initializing Device...");
    Serial.println("Serial device initialized.");
  #endif
​
  #if FLASH_LED == true
    pinMode(LED_PIN, OUTPUT);
  #endif
​
  CanDevice.begin();
  
  #if CAN_MODE == 1
    CANFD_timings_t config;
    config.clock = CLK_24MHz;
    config.baudrate = 100000;
    config.baudrateFD = 200000;
    config.propdelay = 190;
    config.bus_length = 1;
    config.sample = 70;
    CanDevice.setBaudRate(config);
​
    msg_frame.len = 8;
    msg_frame.id = 0x321;
    //msg_frame.flags.extended = 1;
    //msg_frame.seq = 1;
    msg_frame.buf[0] = 1;
    //msg_frame.buf[7] = 1;
  #elif CAN_MODE == 2
    CanDevice.setBaudRate(CAN_BAUD_RATE);
    CanDevice.enableFIFO();
    CanDevice.enableFIFOInterrupt();
    
    msg_frame.len = 8;
    msg_frame.id = 0x321;
    msg_frame.seq = 1;
    msg_frame.buf[0] = 1;
    msg_frame.buf[7] = 1;
  #endif
  #if CNT_REC == true
    CanDevice.onReceive(countReceives);
  #endif
  #if CANSNIFF == true
    CanDevice.onReceive(canSniff);
  #endif
  #if CAN_MAILBOX_STATUS == true
    CanDevice.mailboxStatus(); 
  #endif
​
  last_time = millis();
}
​
void loop() {
  if (millis() > last_time + LOOP_INTERVAL) {
    
    #if EN_BROADCAST == true
      CanDevice.write(msg_frame);
      #if CNT_SEND == true
        send_count++;
      #endif
    #endif
    #if FLASH_LED == true
      if (led_state) {
        digitalWrite(LED_PIN, LOW);
        led_state = false;
      }
      else {
        digitalWrite(LED_PIN, HIGH);
        led_state = true;
      }
    #endif
    #if EN_SER == true
      #if CNT_REC == true
        Serial.print("Received ");
        Serial.print(rec_count);
        Serial.print(" messages in the last ");
        Serial.print(LOOP_INTERVAL);
        Serial.println(" milliseconds.");
        rec_count = 0;
      #endif
      #if CNT_SEND == true
        Serial.print("Sent ");
        Serial.print(send_count);
        Serial.print(" messages in the last ");
        Serial.print(LOOP_INTERVAL);
        Serial.println(" milliseconds.");
        send_count = 0;
      #endif
    #endif
    last_time = millis();
  }
}
​
#if CANSNIFF == true
  #if EN_SER == true
    void canSniff(const CAN_message &msg) {
      Serial.print("MB "); 
      Serial.print(msg.mb);
    
      Serial.print("  OVERRUN: ");
      Serial.print(msg.flags.overrun);
      
      Serial.print("  LEN: ");
      Serial.print(msg.len);
    
      Serial.print(" EXT: ");
      Serial.print(msg.flags.extended);
    
      Serial.print(" TS: ");
      Serial.print(msg.timestamp);
    
      Serial.print("ID: ");
      Serial.print(msg.id, HEX);
    
      Serial.print(" Buffer: ");
      for ( uint8_t i = 0; i < msg.len; i++) {
        Serial.print(msg.buf[i], HEX); Serial.print(" ");
      }
    
      Serial.println();
    }
  #endif
#endif
​
#if CNT_REC == true
  void countReceives(const CAN_message &msg) {
    rec_count++;
  }
#endif

I'm snooping on the line using an Analog Discovery 2 and it looks like the signal is getting messed up, with only a couple of bytes of data being sent before it shows an error. I've attached a screenshot of the data stream below.

Any advice on what is going wrong would be appreciated, I'm at a loss right now.

I'm using a TJA1050 based CAN transceiver, have two Teensy 4.0s communicating back and forth, with a logic level shifter sitting in between to handle the 5 V -> 3.3 V drop between the transceivers and the Teensys.
 

Attachments

  • CAN-sniff.jpg
    CAN-sniff.jpg
    39.9 KB · Views: 44
Running into a weird issue with the CAN3 CANFD transmission. I've got my script setup as below, most of it matches the documentation's examples, and I've got it set up to broadcast a message every 500 ms. The system works fine for CAN2.0, but when I try and do it using CANFD, the data seems to be getting garbled in output.

Code:
#include <FlexCAN_T4.h>
​
// Specify '1' for CANFD and '2' for CAN2.0
#define CAN_MODE            1
#define LOOP_INTERVAL       500
​
#define EN_SER              false
#define SER_BAUD_RATE       115200
​
#define EN_BROADCAST        true
#define CNT_REC             false
#define CNT_SEND            false
#define CANSNIFF            false
#define CAN_MAILBOX_STATUS  true
​
#define CAN_BAUD_RATE       1000000
​
#define FLASH_LED           true
#define LED_PIN             13
​
unsigned long last_time;
​
#if FLASH_LED == true
  bool led_state = false;
#endif
​
#if CNT_REC == true
  unsigned int rec_count = 0;
#endif
#if CNT_SEND == true
  unsigned int send_count = 0;
#endif 
​
#if CAN_MODE == 1
  typedef CANFD_message_t CAN_message;
  typedef FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_16> CAN_device;
#elif CAN_MODE == 2
  typedef CAN_message_t CAN_message;
  typedef FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> CAN_device;
#endif
​
CAN_device CanDevice;
CAN_message msg_frame;
​
void setup() {
  // put your setup code here, to run once:
  #if EN_SER == true
    Serial.begin(SER_BAUD_RATE);
    Serial.println("Initializing Device...");
    Serial.println("Serial device initialized.");
  #endif
​
  #if FLASH_LED == true
    pinMode(LED_PIN, OUTPUT);
  #endif
​
  CanDevice.begin();
  
  #if CAN_MODE == 1
    CANFD_timings_t config;
    config.clock = CLK_24MHz;
    config.baudrate = 100000;
    config.baudrateFD = 200000;
    config.propdelay = 190;
    config.bus_length = 1;
    config.sample = 70;
    CanDevice.setBaudRate(config);
​
    msg_frame.len = 8;
    msg_frame.id = 0x321;
    //msg_frame.flags.extended = 1;
    //msg_frame.seq = 1;
    msg_frame.buf[0] = 1;
    //msg_frame.buf[7] = 1;
  #elif CAN_MODE == 2
    CanDevice.setBaudRate(CAN_BAUD_RATE);
    CanDevice.enableFIFO();
    CanDevice.enableFIFOInterrupt();
    
    msg_frame.len = 8;
    msg_frame.id = 0x321;
    msg_frame.seq = 1;
    msg_frame.buf[0] = 1;
    msg_frame.buf[7] = 1;
  #endif
  #if CNT_REC == true
    CanDevice.onReceive(countReceives);
  #endif
  #if CANSNIFF == true
    CanDevice.onReceive(canSniff);
  #endif
  #if CAN_MAILBOX_STATUS == true
    CanDevice.mailboxStatus(); 
  #endif
​
  last_time = millis();
}
​
void loop() {
  if (millis() > last_time + LOOP_INTERVAL) {
    
    #if EN_BROADCAST == true
      CanDevice.write(msg_frame);
      #if CNT_SEND == true
        send_count++;
      #endif
    #endif
    #if FLASH_LED == true
      if (led_state) {
        digitalWrite(LED_PIN, LOW);
        led_state = false;
      }
      else {
        digitalWrite(LED_PIN, HIGH);
        led_state = true;
      }
    #endif
    #if EN_SER == true
      #if CNT_REC == true
        Serial.print("Received ");
        Serial.print(rec_count);
        Serial.print(" messages in the last ");
        Serial.print(LOOP_INTERVAL);
        Serial.println(" milliseconds.");
        rec_count = 0;
      #endif
      #if CNT_SEND == true
        Serial.print("Sent ");
        Serial.print(send_count);
        Serial.print(" messages in the last ");
        Serial.print(LOOP_INTERVAL);
        Serial.println(" milliseconds.");
        send_count = 0;
      #endif
    #endif
    last_time = millis();
  }
}
​
#if CANSNIFF == true
  #if EN_SER == true
    void canSniff(const CAN_message &msg) {
      Serial.print("MB "); 
      Serial.print(msg.mb);
    
      Serial.print("  OVERRUN: ");
      Serial.print(msg.flags.overrun);
      
      Serial.print("  LEN: ");
      Serial.print(msg.len);
    
      Serial.print(" EXT: ");
      Serial.print(msg.flags.extended);
    
      Serial.print(" TS: ");
      Serial.print(msg.timestamp);
    
      Serial.print("ID: ");
      Serial.print(msg.id, HEX);
    
      Serial.print(" Buffer: ");
      for ( uint8_t i = 0; i < msg.len; i++) {
        Serial.print(msg.buf[i], HEX); Serial.print(" ");
      }
    
      Serial.println();
    }
  #endif
#endif
​
#if CNT_REC == true
  void countReceives(const CAN_message &msg) {
    rec_count++;
  }
#endif

I'm snooping on the line using an Analog Discovery 2 and it looks like the signal is getting messed up, with only a couple of bytes of data being sent before it shows an error. I've attached a screenshot of the data stream below.

Any advice on what is going wrong would be appreciated, I'm at a loss right now.

I'm using a TJA1050 based CAN transceiver, have two Teensy 4.0s communicating back and forth, with a logic level shifter sitting in between to handle the 5 V -> 3.3 V drop between the transceivers and the Teensys.


You need to use CAN FD transceivers such as MCP2562FD or TJA1462.
 
I'm trying to get mailboxes to work, but perhaps I don't understand them. I have a specific CAN ID that I want to receive, and the rest is junk.

Pseudocode:

Code:
// https://github.com/tonton81/FlexCAN_T4
#include <FlexCAN_T4.h>
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> CanBus;

// CAN data to watch for (later needs to be in EEPROM)
#define CAN_SPEED_HEXID 0x589
#define CAN_SPEED_START_BYTE 6

void setup() {
  // Initialize CAN1
  CanBus.begin();
  CanBus.setBaudRate(1000000);
  CanBus.setMaxMB(16);

  //CanBus.setMBFilter(REJECT_ALL);
  //CanBus.setMBFilter(MB0, CAN_SPEED_HEXID);
  //CanBus.enhanceFilter(MB0);
  //CanBus.setMB(MB0, RX, STD);
  //CanBus.onReceive(MB0, canSniff);
  //CanBus.enableMBInterrupt(MB0);


  CanBus.enableFIFO();
  CanBus.enableFIFOInterrupt();
  CanBus.onReceive(canSniff);

  CanBus.mailboxStatus();
}

void loop() {
  CanBus.events();
}

In FIFO mode, when I send a message from my CAN device, using the example canSniff function, I see output in the serial monitor:

Code:
MB 99  OVERRUN: 0  LEN: 8 EXT: 0 TS: 15520 ID: 589 Buffer: 0 0 2A 0 0 0 0 0

If I comment out the FIFO stuff and UNcomment the MBfiltering, when my device sends a message on 0x589, nothing is output by canSniff.

Can you explain what I'm doing wrong with mailboxes here?

* I'm rejecting all messages with setMBFilter
* I'm telling MB0 which ID to filter (0x589)
* I'm turning on enhanced filtering on MB0
* I'm telling MB0 to receive standard frames
* I'm telling MB0 to call canSniff when it receives something

The goal:
I want to throw away any message that isn't 0x589
 
You need to use CAN FD transceivers such as MCP2562FD or TJA1462.

Ah, I see, I had attempted to verify if the TJA1050 supported CANFD, but it just cited compliance with the ISO 11898 standard, which CANFD is included under, so I had thought it was supported, thank you!
 
I'm trying to get mailboxes to work, but perhaps I don't understand them. I have a specific CAN ID that I want to receive, and the rest is junk.

Pseudocode:

Code:
// https://github.com/tonton81/FlexCAN_T4
#include <FlexCAN_T4.h>
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> CanBus;

// CAN data to watch for (later needs to be in EEPROM)
#define CAN_SPEED_HEXID 0x589
#define CAN_SPEED_START_BYTE 6

void setup() {
  // Initialize CAN1
  CanBus.begin();
  CanBus.setBaudRate(1000000);
  CanBus.setMaxMB(16);

  //CanBus.setMBFilter(REJECT_ALL);
  //CanBus.setMBFilter(MB0, CAN_SPEED_HEXID);
  //CanBus.enhanceFilter(MB0);
  //CanBus.setMB(MB0, RX, STD);
  //CanBus.onReceive(MB0, canSniff);
  //CanBus.enableMBInterrupt(MB0);


  CanBus.enableFIFO();
  CanBus.enableFIFOInterrupt();
  CanBus.onReceive(canSniff);

  CanBus.mailboxStatus();
}

void loop() {
  CanBus.events();
}

In FIFO mode, when I send a message from my CAN device, using the example canSniff function, I see output in the serial monitor:

Code:
MB 99  OVERRUN: 0  LEN: 8 EXT: 0 TS: 15520 ID: 589 Buffer: 0 0 2A 0 0 0 0 0

If I comment out the FIFO stuff and UNcomment the MBfiltering, when my device sends a message on 0x589, nothing is output by canSniff.

Can you explain what I'm doing wrong with mailboxes here?

* I'm rejecting all messages with setMBFilter
* I'm telling MB0 which ID to filter (0x589)
* I'm turning on enhanced filtering on MB0
* I'm telling MB0 to receive standard frames
* I'm telling MB0 to call canSniff when it receives something

The goal:
I want to throw away any message that isn't 0x589

yes, don't run setMB after you do the filters, it resets them.
for simplicity always test without filtering before you add filtering. by default MB0 is standard frame reception
 
yes, don't run setMB after you do the filters, it resets them.
for simplicity always test without filtering before you add filtering. by default MB0 is standard frame reception

Code:
  CanBus.setMB(MB0, RX, STD);
  CanBus.onReceive(MB0, canSniff);
  CanBus.enableMBInterrupt(MB0);
  CanBus.setMBFilter(REJECT_ALL);
  CanBus.setMBFilter(MB0, CAN_SPEED_HEXID);
  CanBus.enhanceFilter(MB0);

That was the ticket. Thanks!
 
take a look at the *MBFilterProcessing internal function, if you want to test your own masks being passed directly rather than the autocalculated call you can try that (for testing you can move that function in public of the class). Unfortunately for FIFO end, if you check out the what needs to be done to set masks and actually have them work, it's a little more effort involved.

if you really need a function for that i can work on one for you, but what name should I give a function for that? the UserFilter is for J1939 and don't want to change that as it'll break existing code for users who are currently using it

I'm going to need a way to set the ID and Mask. I'm thinking:

Code:
FCTP_FUNC bool FCTP_OPT::setMBFilterManual(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t mask);
FCTP_FUNC bool FCTP_OPT::setFIFOFilterManual(uint8_t filter, uint32_t id1, uint32_t mask, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote);

I started playing with setMBFilterManual:

Code:
FCTP_FUNC bool FCTP_OPT::setMBFilterManual(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t mask) {
  if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return 0; /* mailbox not available */
  if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return 0; /* exit on TX mailbox */
  setMBFilterProcessing(mb_num,id1,mask);
  filter_store(FLEXCAN_MULTI, mb_num, 1, id1, 0, 0, 0, 0);
  return 1;
}

It works, but I have to shift my masks by 18 bits, i.e.: 0x7FC (011111111100) becomes 0x1FF00000 (00011111111100000000000000000000). Not sure yet why it's a shift by 18 and not 20. Haven't tried with extended ID's yet, either.
 
Not sure yet why it's a shift by 18 and not 20.

Oh, duh, it's because for an extended ID, the bottom 29 bits are used and a standard ID is sharing the top 11 bits of that, all stored in a 32 bit wide variable. The bit shift makes sense now.
 
Back
Top