FlexCAN_T4 - FlexCAN for Teensy 4

Your sketch does not transmit any CAN frame. You have not setup the mailbox correctly.

Follow the example sketch : mailbox_filtering_example_with_interrupts.ino

Code:
Can0.begin();
  Can0.setBaudRate(250000);
  Can0.setMaxMB(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES);
  for (int i = 0; i<NUM_RX_MAILBOXES; i++){
    Can0.setMB((FLEXCAN_MAILBOX)i,RX,EXT);
  }
  for (int i = NUM_RX_MAILBOXES; i<(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES); i++){
    Can0.setMB((FLEXCAN_MAILBOX)i,TX,EXT);
  }
  Can0.setMBFilter(REJECT_ALL);
  Can0.enableMBInterrupts();
  Can0.onReceive(MB0,canSniff);
  Can0.onReceive(MB1,canSniff);
  Can0.onReceive(MB2,canSniff);
  Can0.setMBUserFilter(MB0,0x00,0xFF);
  Can0.setMBUserFilter(MB1,0x03,0xFF);
  Can0.setMBUserFilter(MB2,0x0B,0xFF);
  Can0.mailboxStatus();

Change Can0 to your can2
 
Your sketch does not transmit any CAN frame. You have not setup the mailbox correctly.

Follow the example sketch : mailbox_filtering_example_with_interrupts.ino

Code:
Can0.begin();
  Can0.setBaudRate(250000);
  Can0.setMaxMB(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES);
  for (int i = 0; i<NUM_RX_MAILBOXES; i++){
    Can0.setMB((FLEXCAN_MAILBOX)i,RX,EXT);
  }
  for (int i = NUM_RX_MAILBOXES; i<(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES); i++){
    Can0.setMB((FLEXCAN_MAILBOX)i,TX,EXT);
  }
  Can0.setMBFilter(REJECT_ALL);
  Can0.enableMBInterrupts();
  Can0.onReceive(MB0,canSniff);
  Can0.onReceive(MB1,canSniff);
  Can0.onReceive(MB2,canSniff);
  Can0.setMBUserFilter(MB0,0x00,0xFF);
  Can0.setMBUserFilter(MB1,0x03,0xFF);
  Can0.setMBUserFilter(MB2,0x0B,0xFF);
  Can0.mailboxStatus();

Change Can0 to your can2
I am struggling to understand how I have setup the mailboxes incorrectly?
On can1 I have setup a single mailbox to recieve messages and it will trigger canSniff on receive.
On can2 I have setup a single mailbox to transmit messages.

You can see these two mailboxes setup in the serial output in my last message.

Even when I hookup a cansniffer box to can2 directly (all the correct 120ohm terminations of course) it still doesn't transmit from the mailbox.

The message is stuck in the mailbox and won't transmit properly, from what I've read this is because it is not getting an ACK but both the cansniffer box and can1 should be able to ACK this.
 
Hello, Im having issues with setting a filter for my CANBus. Ideally, I give my motors a desiredVelocity/Position, and the motor will return a ActualVelocity/Position (encoder feedback). I attempted to do this by setting the filter to be the API key (in hexidecimal) of the encoder feedback. However, the value im getting returned is the wrong API key. I am unsure why, dont know if im setting up CAN incorrectly or if the company APi documentation I bought the motors from is not up to date.
C++:
static constexpr uint32_t BASE = 0x0205B880;      // lower 6 bits = 0


void CANBus::CANBusInit(){
    can.begin();
    can.setRFFN(true);
    can.setClock(CLK_60MHz);
    can.setBaudRate(1000000);
    can.setFIFOFilter(REJECT_ALL);
    can.enableFIFO();
    can.enableFIFOInterrupt();
    for(int i = 1; i <= 8; i++){
        can.setFIFOFilter(i - 1, BASE | i, EXT, NONE);
    }
    can.onReceive(FIFO,canSniff);

    delay(2000);
}



void canSniff(const CAN_message_t &msg){
    if(msg.flags.extended != 1){    // checking if we are getting an extened message
        return;
    } else {
        steer_mb[2] = msg.id;   // if so check the CAN ID
        return;
    }
}

// this is what is getting returned "0205B808"
// instead of 0x0205B880;
 
Hi,

I submitted a bug report to the github repo issue reporter. I can't provide an example program at the moment, but has anyone experienced something similar?

Data is damaged/changed when I send data. More information is in the whistleblower. (I formatted and attached information as well).

Thanks in advance if anyone can help with this. (Including @tonton81 who made the library)

https://github.com/tonton81/FlexCAN_T4/issues/78

megax
I found the root cause of the issue. I’ve attached my response and the code here as well (it also includes other development work):
https://github.com/tonton81/FlexCAN_T4/issues/78#issuecomment-3734570651
 
Hi all, I am trying to do my own CAN bus bridge for my car.
I want to be able to replace a few bytes on one ID and let the Teensy live in the car so I don't have to take it out all the time.

I tried the BiDirectionalForward example and it looked like all is well and it works like a charm, except when the OTA updates came to the car. The ECU flashing session crashes every time, I approved it on the table myself by checking both CAN1 with incoming traffic and CAN2 with outgoing in realtime with other tool while simulating the flash on the table.

Looks like Teensy is unable to handle CAN message bursts on that one ID while using this sketch when the CAN bus is under medium load. Incoming bytes are sent out in different order than they were received in random moments of flashing, sometimes at 2%, sometimes 50%, sometimes 83% and so on, for example:

7E0#21 04 42 98 81 28 82 03
7E0#23 14 32 48 24 45 65 12
7E0#22 13 11 96 8a a8 82 19

I also tried to simulate the ECU flashing when there are no other ID's talking around on the bus, then it works like a charm.

I have wasted few days trying to understand the purpose of FIFO, interrupts, callbacks, mailboxes, TX_SIZE and RX_size, have a very basic understanding about all of that, tried almost everything I could find from other posts and it only makes everything worse, so I have no more ideas than try to ask the creator of FlexCAN_t4 library and the community. There is also no good way to debug what is wrong with the CAN controller or what does it feel in that moment, at least I can't find any.

What could be the cause of this wrong byte ordering?

This is my test code.


C++:
#include <FlexCAN_T4.h>

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

void setup(void) {
  can1.begin();
  can1.setBaudRate(500000);
  can2.begin();
  can2.setBaudRate(500000);
}

void loop() {
  if ( can1.read(msg) ) {
    can2.write(msg);
  }
  else if ( can2.read(msg) ) {
    can1.write(msg);
  }
}
 
Last edited:
Hi all, I am trying to do my own CAN bus bridge for my car.
I want to be able to replace a few bytes on one ID and let the Teensy live in the car so I don't have to take it out all the time.

I tried the BiDirectionalForward example and it looked like all is well and it works like a charm, except when the OTA updates came to the car. The ECU flashing session crashes every time, I approved it on the table myself by checking both CAN1 with incoming traffic and CAN2 with outgoing in realtime with other tool while simulating the flash on the table.

Looks like Teensy is unable to handle CAN message bursts on that one ID while using this sketch when the CAN bus is under medium load. Incoming bytes are sent out in different order than they were received in random moments of flashing, sometimes at 2%, sometimes 50%, sometimes 83% and so on, for example:

7E0#21 04 42 98 81 28 82 03
7E0#23 14 32 48 24 45 65 12
7E0#22 13 11 96 8a a8 82 19

I also tried to simulate the ECU flashing when there are no other ID's talking around on the bus, then it works like a charm.

I have wasted few days trying to understand the purpose of FIFO, interrupts, callbacks, mailboxes, TX_SIZE and RX_size, have a very basic understanding about all of that, tried almost everything I could find from other posts and it only makes everything worse, so I have no more ideas than try to ask the creator of FlexCAN_t4 library and the community. There is also no good way to debug what is wrong with the CAN controller or what does it feel in that moment, at least I can't find any.

What could be the cause of this wrong byte ordering?
Hi, you need to set msg.seq = 1; in the message you are about to send. This tells the code to transmit the messages in order.

Additionally, I found a related bug in the library, which I reported here:
https://github.com/tonton81/FlexCAN_T4/issues/78#issuecomment-3734570651

My fix can be found in this repository:
https://github.com/The-Megax/FlexCAN_T4

You might want to try my modified library if setting seq does not help. I struggled with this for quite a while myself before figuring out what the issue was.

I also recommend using TX_SIZE_256 or TX_SIZE_128 so the transmit buffer is large enough. However, the root cause of the issue is actually the buffer creation itself, which I explained in detail in the bug report.
 
Hi, you need to set msg.seq = 1; in the message you are about to send. This tells the code to transmit the messages in order.

Additionally, I found a related bug in the library, which I reported here:
https://github.com/tonton81/FlexCAN_T4/issues/78#issuecomment-3734570651

My fix can be found in this repository:
https://github.com/The-Megax/FlexCAN_T4

You might want to try my modified library if setting seq does not help. I struggled with this for quite a while myself before figuring out what the issue was.

I also recommend using TX_SIZE_256 or TX_SIZE_128 so the transmit buffer is large enough. However, the root cause of the issue is actually the buffer creation itself, which I explained in detail in the bug report.

I also tried a combination like this, it crashes the flashing at the beginning already.

C++:
#include <FlexCAN_T4.h>

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_256> can1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_256> can2;
CAN_message_t msg;

void setup(void) {
  can1.begin();
  can1.setBaudRate(500000);
  can2.begin();
  can2.setBaudRate(500000);
}

void loop() {
  if ( can1.read(msg) ) {
    msg.seq = 1;
    can2.write(msg);
  }
  else if ( can2.read(msg) ) {
    msg.seq = 1;
    can1.write(msg);
  }
}

I was also reading about your problems before I posted but didn't have a clue that you made a fork. Will give it a try!
 
Code:
#include <FlexCAN_T4.h>

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_256> can1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_256> can2;
CAN_message_t msg;

void setup(void) {
  can1.begin();
  can1.setBaudRate(500000);
  can2.begin();
  can2.setBaudRate(500000);
}

void loop() {
  if ( can1.read(msg) ) {
    msg.seq = 1;
    can2.write(msg);
  }

  if ( can2.read(msg) ) {
    msg.seq = 1;
    can1.write(msg);
  }
}

This use. Not okay if and else if use. Better 1 cycle 2 read checking.
 
@megax Thanks for trying to help, I tried this code, also tried your fork but it didn't help.
When I try your code, the packets are getting lost from all the IDs, it is like the Teensy gets stuck and then unfreezes after a second
 
You could also try this. In theory, read() does not use a buffer, so there might be data loss there as well. This is my last idea. With my code it works, even with a large codebase. Of course, in some cases this might make things worse. In any case, if you can, give this a try as well.

Code:
#include <FlexCAN_T4.h>

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_256> can1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_256> can2;
CAN_message_t msg;

void setup(void) {
  can1.begin();
  can1.setBaudRate(500000);
  can1.enableFIFO();
  can1.enableFIFOInterrupt();
  can1.withoutFIFOCallback();

  can2.begin();
  can2.setBaudRate(500000);
  can2.enableFIFO();
  can2.enableFIFOInterrupt();
  can2.withoutFIFOCallback();
}

void loop() {
  can1.events();
  can2.events();

  if ( can1.read(msg) ) {
    msg.seq = 1;
    can2.write(msg);
  }

  if ( can2.read(msg) ) {
    msg.seq = 1;
    can1.write(msg);
  }
}

Important! If you use sequential writing, only one mailbox is active. Previously you were using 8 mailboxes, if I remember correctly—that’s the default. So the number of outgoing messages that the hardware can actually transmit dropped to 1/8.


I haven’t tested my fix with such a large amount of data. It should work, but the mailbox will fill up. The additions I made to the code are meant to force the transmission.
 
Last edited:
You could also try this. In theory, read() does not use a buffer, so there might be data loss there as well. This is my last idea. With my code it works, even with a large codebase. Of course, in some cases this might make things worse. In any case, if you can, give this a try as well.

Code:
#include <FlexCAN_T4.h>

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_256> can1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_256> can2;
CAN_message_t msg;

void setup(void) {
  can1.begin();
  can1.setBaudRate(500000);
  can1.enableFIFO();
  can1.enableFIFOInterrupt();
  can1.withoutFIFOCallback();

  can2.begin();
  can2.setBaudRate(500000);
  can2.enableFIFO();
  can2.enableFIFOInterrupt();
  can2.withoutFIFOCallback();
}

void loop() {
  can1.events();
  can2.events();

  if ( can1.read(msg) ) {
    msg.seq = 1;
    can2.write(msg);
  }

  if ( can2.read(msg) ) {
    msg.seq = 1;
    can1.write(msg);
  }
}

Important! If you use sequential writing, only one mailbox is active. Previously you were using 8 mailboxes, if I remember correctly—that’s the default. So the number of outgoing messages that the hardware can actually transmit dropped to 1/8.


I haven’t tested my fix with such a large amount of data. It should work, but the mailbox will fill up. The additions I made to the code are meant to force the transmission.

Actually, your last code really passed the flashing procedure through and it flashed!
Only problem now is the Teensy getting stuck in some moments for 0.5 seconds. Maybe you know what could cause that?
 
Actually, your last code really passed the flashing procedure through and it flashed!
Only problem now is the Teensy getting stuck in some moments for 0.5 seconds. Maybe you know what could cause that?
Does the program itself visibly stall, or is it that the outgoing data is not transmitted for about 0.5 seconds? It’s possible that the single mailbox is the bottleneck. In theory, since your program isn’t doing anything else, it shouldn’t be stealing time from other operations to keep re-enabling the transmit ISR continuously (I changed its behavior slightly).

Basically, it’s a valid question what could be causing this. Unfortunately, I can’t promise a clear, definitive solution. Sequential writing is handled with limitations even in the original FlexCAN (1 mailbox). You could try increasing the buffer size to 512 for both read and write. That might not necessarily solve the problem, but it’s worth a try.

Possibly someone else who has ideas about this could help as well. In any case, sequential writing clearly suffers from a bug—at least that’s how it looks based on my tests.

The ideal solution with this amount of data would be if multiple mailboxes could transmit sequentially. I believe that would be the best approach. Unfortunately, at the moment I don’t know whether that’s even feasible. The current code definitely does not support this.
 
Back
Top