FlexCAN_T4 - FlexCAN for Teensy 4

tonton81

Well-known member
This initial release is a remodeled design of IFCT built from the ground up. In it's base format currently, features and enhancements will be added later on in future once more tests are completed. Here are the current features:

CAN2.0 currently supported, FD later on...

1) User instantiated templated class object working on both bus interfaces using user named objects.
This allows in-sketch user definable RX and TX queue size adjustments!
Code:
FlexCAN_T4<[COLOR="#FF0000"]CAN1[/COLOR], [COLOR="#A52A2A"]RX_SIZE_256[/COLOR], [COLOR="#A52A2A"]TX_SIZE_16[/COLOR]> [COLOR="#0000CD"]Can0[/COLOR];
FlexCAN_T4<[COLOR="#FF0000"]CAN2[/COLOR], [COLOR="#A52A2A"]RX_SIZE_256[/COLOR], [COLOR="#A52A2A"]TX_SIZE_16[/COLOR]> [COLOR="#0000CD"]Can1[/COLOR];

2) FIFO support with up to 128 filter support, as well as up to 64 mailbox capability. FIFO Tables implemented are Table A and B, C and D are not necessary and quite unusual with partial masking.

3) Automatic Filtering, which supports all mailboxes and 128 filters provided in the FIFO.

4) On Beta1 of Teensy, pins 0 and 1 are used for CAN2, pins 22 and 23 are used for CAN1.

5) The initialized clock for the flexcan controller is defaulted to 24MHz oscillator in the library. You can change it to up to 60MHz during runtime using:
Code:
  Can0.setClock(CLK_60MHz);

6) Transmit and reception queues are supported, including sequential frames.

7) Loop based callback firing via dequeue (Can0.events()). Should threading/timer support be added, they would work as well.

8) Up to 64 mailbox callbacks can be used. If FIFO is used, MB0 callback will be assigned and fired for reception, as FIFO occupies the first mailbox onwards till end of FIFO map.

More work to do! :)

https://github.com/tonton81/FlexCAN_T4

I'd also like to thank Mike for contributing and bug checks to this and many other libraries he has helped work on

Tony
 
Last edited:
Is it possible to include a simple test example for this.

Hi,

Is it possible to include a simple test example for this? I tried to use the example from existing FlexCan but I see no read data. So I found during debug there is no output on the TX pin its stuck high- I see no data toggling on a scope. So I checked my teensy4 was still good by checking the tx pin toggles by making a simple sketch to drive the pin high and low and I see data toggling as expected on pin22.

-Ken


Code:
// -------------------------------------------------------------
// CANtest for Teensy 4.0 using CAN2 and CAN2 bus
#include <FlexCAN_T4.h>

#define debug(msg) Serial.print("["); Serial.print(__FILE__); Serial.print("::"); Serial.print(__LINE__);  Serial.print("::"); Serial.print(msg); Serial.println("]");
void debug_pause(void)
{
  Serial.print("Paused...");
  while (!Serial.available());
  while (Serial.available()) Serial.read();
  Serial.println("Restarted.");
}

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> Can2;

static CAN_message_t msg;
static uint8_t hex[17] = "0123456789abcdef";

// -------------------------------------------------------------
static void hexDump(uint8_t dumpLen, uint8_t *bytePtr)
{
  uint8_t working;
  while( dumpLen-- ) {
    working = *bytePtr++;
    Serial.write( hex[ working>>4 ] );
    Serial.write( hex[ working&15 ] );
  }
  Serial.write('\r');
  Serial.write('\n');
}


// -------------------------------------------------------------
void setup(void)
{
  Serial.begin(115200);
  int iSerialTimeout = 1000000;
  delay(100);
  while (!Serial && (iSerialTimeout-- != 0));  
  debug (F("start setup"));

  Can1.begin();  
  Can2.begin();

  pinMode(0, INPUT);
  pinMode(1, OUTPUT);
  pinMode(22, OUTPUT);
  pinMode(23, INPUT);



  // t4 missing msg.ext = 0;
  msg.id = 0x100;
  msg.len = 8;
  msg.flags.extended = 0;
  msg.flags.remote   = 0;
  msg.flags.overrun  = 0;
  msg.flags.reserved = 0;
  msg.buf[0] = 10;
  msg.buf[1] = 20;
  msg.buf[2] = 0;
  msg.buf[3] = 100;
  msg.buf[4] = 128;
  msg.buf[5] = 64;
  msg.buf[6] = 32;
  msg.buf[7] = 16;
  debug (F("setup complete"));
  //debug_pause();
}


// -------------------------------------------------------------
void loop(void)
{
  Serial.println("T4.0cantest - Repeat: Read bus2, Write bus1");
  CAN_message_t inMsg;
  while (Can2.read(inMsg)!=0) 
  {
    Serial.print("W RD bus 2: "); hexDump(8, inMsg.buf);
  }
  msg.buf[0]++;
  Can1.write(msg);
  msg.buf[0]++;
  Can1.write(msg);
  msg.buf[0]++;
  Can1.write(msg);
  msg.buf[0]++;
  Can1.write(msg);
  msg.buf[0]++;
  Can1.write(msg);  
  delay(20);
}
 
Can you try that test on 1.47beta5 teensyduino?

msg.ext is a macro in t3.6, you should be able to use msg.flags.extended in both t3/4

do you have resistor 120 ohm on the line?
 
Hi,

Is it possible to include a simple test example for this? I tried to use the example from existing FlexCan but I see no read data. So I found during debug there is no output on the TX pin its stuck high- I see no data toggling on a scope. So I checked my teensy4 was still good by checking the tx pin toggles by making a simple sketch to drive the pin high and low and I see data toggling as expected on pin22.

-Ken


Code:
// -------------------------------------------------------------
// CANtest for Teensy 4.0 using CAN2 and CAN2 bus
#include <FlexCAN_T4.h>

#define debug(msg) Serial.print("["); Serial.print(__FILE__); Serial.print("::"); Serial.print(__LINE__);  Serial.print("::"); Serial.print(msg); Serial.println("]");
void debug_pause(void)
{
  Serial.print("Paused...");
  while (!Serial.available());
  while (Serial.available()) Serial.read();
  Serial.println("Restarted.");
}

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> Can2;

static CAN_message_t msg;
static uint8_t hex[17] = "0123456789abcdef";

// -------------------------------------------------------------
static void hexDump(uint8_t dumpLen, uint8_t *bytePtr)
{
  uint8_t working;
  while( dumpLen-- ) {
    working = *bytePtr++;
    Serial.write( hex[ working>>4 ] );
    Serial.write( hex[ working&15 ] );
  }
  Serial.write('\r');
  Serial.write('\n');
}


// -------------------------------------------------------------
void setup(void)
{
  Serial.begin(115200);
  int iSerialTimeout = 1000000;
  delay(100);
  while (!Serial && (iSerialTimeout-- != 0));  
  debug (F("start setup"));

  Can1.begin();  
  Can2.begin();

  pinMode(0, INPUT);
  pinMode(1, OUTPUT);
  pinMode(22, OUTPUT);
  pinMode(23, INPUT);



  // t4 missing msg.ext = 0;
  msg.id = 0x100;
  msg.len = 8;
  msg.flags.extended = 0;
  msg.flags.remote   = 0;
  msg.flags.overrun  = 0;
  msg.flags.reserved = 0;
  msg.buf[0] = 10;
  msg.buf[1] = 20;
  msg.buf[2] = 0;
  msg.buf[3] = 100;
  msg.buf[4] = 128;
  msg.buf[5] = 64;
  msg.buf[6] = 32;
  msg.buf[7] = 16;
  debug (F("setup complete"));
  //debug_pause();
}


// -------------------------------------------------------------
void loop(void)
{
  Serial.println("T4.0cantest - Repeat: Read bus2, Write bus1");
  CAN_message_t inMsg;
  while (Can2.read(inMsg)!=0) 
  {
    Serial.print("W RD bus 2: "); hexDump(8, inMsg.buf);
  }
  msg.buf[0]++;
  Can1.write(msg);
  msg.buf[0]++;
  Can1.write(msg);
  msg.buf[0]++;
  Can1.write(msg);
  msg.buf[0]++;
  Can1.write(msg);
  msg.buf[0]++;
  Can1.write(msg);  
  delay(20);
}

You don't need to configure the pins with pinmode the library configures them for FlexCAN automatically. You can give that a try first.

Another question are you directly from CAN1 to CAN2 or have CAN transceivers attached to both?
 
Hi,
Thanks for responging.
>Can you try that test on 1.47beta5 teensyduino?
Ok will try it out.

>do you have resistor 120 ohm on the line?
yes have two IFX1050GVIO transievers hooked together. With 120oh resistors at each end. I measure 60ohms .
When I say the TX lines aren't toggling; what I am saying is I scope at the teensy pin 22 before transciever and I dont see any toggling.
I assume even if I dont have this hooked up to the transiever correctly, at least this would toggle. I disconnected the trans

>You don't need to configure the pins with pinmode
Yeah I tried it without, with it setup before the begin, and with pin mode set after the pin, but I will remove and recheck.
 
Hi,

I downgraded to 1.47 beta5. I was on release. I started on release and cloned the FlexCAN_T4 repo so I dunno if this is related.

Anyways, I get an error during compile for beta5:
E:\arduino\libraries\FlexCAN_T4/FlexCAN_T4.tpp:17:27: error: 'CCM_CSCMR2' was not declared in this scope

if ( clock == CLK_OFF ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(3) | CCM_CSCMR2_CAN_CLK_PODF(0);
 
Thanks Your right it switched the board type after install. Ok it compiles fine now but same result. I scope to tx and rx pins at both CAN1 and CAN2 and they a driving static hi level while the loop is going. (pins 0,1 and pins 22,23). There is no messages during the setup and I see the write messages in serial monitor as it loops. I tried switch the rd and wr buses so CAN2 writes an CAN1 reads but no pins toggle.
 
You haven't posted any picture of your wiring or what transceiver you are using so I am taking guesses here. You have rx going to rx on the transceiver and TX going to tx. The high on the can transceiver going to high on the can transceiver.

I would double check the wiring.

If there is an enable pin on the transceiver you forgot to hook up and drive low?
 
I'm using two IFX1050GVIO chips. I have it on bread board with just bread board wires. I currently do not see any data coming out of teensy TX pin so I'm not sure if it matters to see the mass ball of wires. I mean if the tx was toggling then yes SI issues would be next to look. But since no tx toggles at all, I woulnd't expect any read data coming back.
 
Ok, so I just toggled pin22 in a loop to create a 1.1mhz clock on (CTX1) high and low using digital write in a loop. I see it go high and low, I also see RX path going high and low back on pin 23. I also see the same signal pin 0 CRX2. So I think my setup is fine.
 
common ground? i get why you dont want us to see a ball of wires but sometimes if we see a little we might spot something :)
 
@kito - @tonton81

I changed your sketch around a little bit.
Code:
// -------------------------------------------------------------
// CANtest for Teensy 4.0 using CAN2 and CAN2 bus
#include <FlexCAN_T4.h>

#define debug(msg) Serial.print("["); Serial.print(__FILE__); Serial.print("::"); Serial.print(__LINE__);  Serial.print("::"); Serial.print(msg); Serial.println("]");
void debug_pause(void)
{
  Serial.print("Paused...");
  while (!Serial.available());
  while (Serial.available()) Serial.read();
  Serial.println("Restarted.");
}

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> Can2;

static CAN_message_t msg;
static uint8_t hex[17] = "0123456789abcdef";

// -------------------------------------------------------------
static void hexDump(uint8_t dumpLen, uint8_t *bytePtr)
{
  uint8_t working;
  while( dumpLen-- ) {
    working = *bytePtr++;
    Serial.write( hex[ working>>4 ] );
    Serial.write( hex[ working&15 ] );
  }
  Serial.write('\r');
  Serial.write('\n');
}


// -------------------------------------------------------------
void setup(void)
{
  Serial.begin(115200);
  int iSerialTimeout = 1000000;
  delay(100);
  while (!Serial && (iSerialTimeout-- != 0));  
  debug (F("start setup"));

  Can1.begin();  
  Can2.begin();
  Can1.setBaudRate(1000000);   [COLOR="#FF0000"]// I like to set the baud rates just to be on the safe side[/COLOR]
  Can2.setBaudRate(1000000);

  // t4 missing msg.ext = 0;
  msg.id = 0x100;
  msg.len = 8;
  msg.flags.extended = 0;
  msg.flags.remote   = 0;
  msg.flags.overrun  = 0;
  msg.flags.reserved = 0;
  msg.buf[0] = 10;
  msg.buf[1] = 20;
  msg.buf[2] = 0;
  msg.buf[3] = 100;
  msg.buf[4] = 128;
  msg.buf[5] = 64;
  msg.buf[6] = 32;
  msg.buf[7] = 16;
  debug (F("setup complete"));
  //debug_pause();
}


// -------------------------------------------------------------
void loop(void)
{
  msg.buf[0]++;      [COLOR="#FF0000"] //since you are in a loop i just incremented each time in stead of doing it 5 times[/COLOR]
  Can1.write(msg);   [COLOR="#FF0000"] //you could do it your way as well[/COLOR]
  Serial.println("T4.0cantest - Repeat: Read bus2, Write bus1");
  CAN_message_t inMsg;
  if (Can2.read(inMsg)!=0)     [COLOR="#FF0000"]// Changed this to if as as opposed to while - the way you had it just gets stuck since you haven't even sent a message yet[/COLOR] 
  {
    Serial.print("W RD bus 2: "); hexDump(8, inMsg.buf);
  }
  delay(20);
}
I tested this with the latest release (1.47) and beta-5.
 
@mjs513

I can confirm can1 and can2 works with your sketch.

I then changed can1 to can3 that also works on pin CRX3 and CTX3.

I want to try can3 on CAN FD now.
 
@skpang

Thanks for the confirmation that the sketch works for you. We (@tonton81 and me) did previous testing to verify CAN3 works in CAN2.0 legacy mode.

@tonton81 is still working on incorporating changes into the library for CAN-FD into his FLEXCAN-FD library. Step 1 is mailboxes only. Step 2 will be FD FIFO if I can get it operational in the NXP SDK environment.
 
@mjs513 your script work on my setup too. Thanks.

I debugged you code vs my example and it seems the baud rate was the issue. The baud rate should be AFTER the begin() method.
I tried setting the baud rate before the begin statement that does not work.

I was so fixated on the fact that I see no tx output at all on tx pin that I thought my teensy was bad.

Also its it prbably dumb of me not to set the buad rate, but if I dont set the baud rate I see no output on the tx pin. Even though I can run up to around 1.3Mhz on my setup.
 
It’s okay, the library is still in development, base functionality is the goal and once it’s setup I will add features like I did in IFCT. Aside from the baudrate it’s setup to use the oscillator clock by default, you can also change it to peripheral clock, functions are added, to make it go as fast as 60MHz rather than 24MHz. (IFCT uses 24MHz osc clock).

Flexcan_T4FD is a work in progress, as mike said, FIFO is the last thing I will work on as the memory offsets will require complex calculations to detached mailboxes. The SDK uses too many divisions in a constant loop for every call for every tx and receive, too much processing overhead. SDK is hardcoded to only one of the 2 memory regions, FlexCAN_T4FD has direct access to the mailboxes in both memory regions even if they use different sized data fields, 8,16,32,64 bytes.

Still alot of work to do...
 
I figured u guys could get a good laugh at my expert soldering skills and my total commitment to cleaning flux of my board.

IMG_20190822_144755.jpg
 
Good news guys, finally have FD working on teensy 4.0. It’s so fast I had to slow it down, kept crashing the other node running the SDK. :) But running stable so far on its own.

Both memory regions are supported, even with mixed sizes, the offsets are spot on perfect and tested confirmed results.
There is still work to do adding more basic functions that will enhance the system further.
Interrupts are not handled yet, as I just finished working on getting polling frames working.


I need ideas for the memory region interface, what enums should we use to facilitate it for users to change:
By default, both regions support 32 mailboxes of 8 data bytes, totalling 64MBs.
if a user sets both regions to 64bytes payloads, a total max is 14 mailboxes can be used.
FlexCAN_T4FD has no issues with offsets in any memory sets.

If a user wanted to change it from 8 bytes, what would you suggest for enum names?
I am thinking of 2 functions that can be called right after begin():
setRegion0(xxx); and setRegion1(xxx);

for simplicity sake theres only 4 values, 8,16,32,64 in payload sizes
then you have actual mailboxes in that region changes
64 gives u 7 mailboxes, 8 gives you 32

Any enum we can think that can be easy for the user? or we use those values?
Most of IFCT/FlexCAN_T4 have been known for enum simplicity, so it will be weird if we start throwing numbers in? :)

I could also use it as a payload input i guess, have the user input the max length he will use (ex. 24?) and 32 would be selected automatically, and the return type will display the max mailboxes in that region.
That sounds like an easier method.

I also will work on absolute first TX mailbox based on memory region capacity. This will be used later on for sequential writes. if you have a TX mailbox in region0 8 bytes and one in region1 32 bytes, the first TX mailbox will be taken from region1 for sequential writes, and fall back to region 0 if none found, and if the user sends more data than the DLC supports it will be truncated.

There is also no DLC concern for the user. The library handles the conversions automatically and length will be returned to the user frame automatically
 
Last edited:
yes skpang, i might need help with the bittiming as thats beyond my current expertise, currently i matched the ones against the SDK, but i will be needing help with the calculations, so if your interested let me know, i will have it posted later today after i work on some functions, FD mode will have an example included for send/receive in poll mode
 
setRegions(x) has been added and included in the beta demo on github
x can be 8,16,32,64 and the amount of total mailboxes are returned.
If you attempt to put 24, 32 will be selected, process of elimination.

first TX mailbox code was updated to support the biggest payload region for future primary sequential writes

code on github, works on 1.47b5
 
I'm trying your beta_sample example but couldn't get past FD.begin();

Code:
void setup(void) {
  Serial.begin(115200); delay(1000);
  pinMode(6, OUTPUT); digitalWrite(6, LOW);

  Serial.println("FlexCAN_T4 test");
  FD.begin();
  Serial.println("After FlexCAN_T4 ");
  
  FD.setRegions(64);
  //    FD.setMB(MB6, RX);
  //    FD.setMB(MB11, RX);
  //    FD.setMB(MB22, RX);
  //    FD.setMB(MB31, RX);
  //      FD.setMB(MB45, TX);

}

Tried changing the Optimize setting but didn't make any difference.

Are there any other settings I should make ?

I noticed the files are now tpp and not cpp.
 
they were always tpp, its a templated library with compile time objects :)
This way you can choose custom buffers and load only resources for the controller(s) you use and omit wasting it on other can hardware you don’t use.

2.0 and FD have their own separate tpp files since they use a different template structure.

mike has it running good on 1.47b5 however it doesnt work on newer versions of teensyduino and is still trying to be figured out, neither flexcan_t4fd nor sdk works unless you are on 1.47b5

the lockup on begin means your not on 1.47b5, mike explained this symptom to me earlier

what is even more weirder is that CAN2.0 is not affected by this lockup issue on the same bus on newest teensyduino, but FD is...........
 
FLEXCAN_T4 FD ISSUE

@PaulStoffregen

Ran into an interesting problem a week or so ago with using the FlexCAN FD sdk example I put together a while ago. When I tried to use it with Teensyduino 1.47 it failed - as noted in the above posts it doesn't get out of begin - think its a problem updating the MCR register again. However, as @tonton81 noted it does work with 1.47beta5 without an issue. I didn't report it sooner because I was waiting for Tony's implementation to determine if it was an issue with the SDK implementation or not. But it seems like anything to do with FlexCAN FD now fails with 1.47.

I also tested the sketches with 1.47beta6 at it fails with that as well. Nothing appears to have changed with the imxrt.h file between core versions so not sure what the issue causing it to fail. Any suggestions would be appreciated.
 
Back
Top