FlexCAN_T4 - FlexCAN for Teensy 4

what is the point of available() if read() returns 1 if a message is found? if there are no messages then it will return 0.

now think about this, we could check the IFLAG registers for message flags, but that includes transmits, which means we have to for-loop the non-interrupt message boxes and check for receive only boxes with messages.

Now, we have to do this again for the read() function as well. Do you want to do double redundant checks? :)

that available() i think is for the queue, but why would you check a queue if you are trying to read a mailbox?
 
Thank you. that helps

I got the available() use from an example in the old libraries github page. If it is unnecessary, I don't need it.
 
ONLY CAN3 CAN2.0 supports DMA (not FD), it doesn't use interrupts. You are still responsible for using read() periodically to prevent missing frames. Not very ideal if you ask me :)

freeze mode halts the controller from operation. this is used only to modify critical registers on the controller that REQUIRE it to be in freeze mode first. Normally, the user does not touch this, the library handles all the configurations.
 
Hi tonton81, I've been working with FlexCAN_T4 for a while now, using Standard and FD mode.
My configuration needs 500k in arbitration and 2M in data mode.
I did not find an example for this constellation so I tested some configuration and ended up with this:

config.clock = CLK_24MHz;
config.baudrate = 500000;
config.baudrateFD = 2000000;
config.propdelay = 190;
config.bus_length = 1;
config.sample = 87.5;

This works for approx. 99% but unfortunately not 100%. I now have an ECU as communication partner where some messages I should receive are clipped somehow...

When I do the same with a RPi and socketcan, it works 100% so far. The init string for socketcan is:
set can0 type can bitrate 500000 sample-point 0.6 sjw 6 dbitrate 2000000 dsample-point 0.8 dsjw 2 fd on.

Do you have a suggestion for a more precise init of FlexCan for the bitrates 500k/2M?

Thank you in advance!

Best regards Ralph
 
freeze mode halts the controller from operation. this is used only to modify critical registers on the controller that REQUIRE it to be in freeze mode first. Normally, the user does not touch this, the library handles all the configurations.

I am just wondering if FLEXCAN_EnterFreezeMode would help avoid having MB fill up on one controller while another controller or some other device is set up? I envision set up a controller, freezing it while doing the same for all the other controllers, finish setting up everything else then at the bottom set up unfreezing all the controllers.

That way you doing fall behind before you even start.

Thanks

Bruce
 
why would you initialize, disable, initialize, disable, initialize, disable, then all enable? I don't see a use case for that nor will anyone except you use that?
 
Ralsi, you can play with sample point and clock (try 60MHz?)

are you using interrupts? are you reading events() periodically to prevent missing frames? Tried increasing the constructor's RX buffer?
 
freeze

why would you initialize, disable, initialize, disable, initialize, disable, then all enable? I don't see a use case for that nor will anyone except you use that?
So the whole system (other than just the CAN) can be set up before filling up all the MB with message which will call an interrupt to clear it.
 
FlexCAN_T4 - FlexCAN for Teensy 4.1 with SN65HVD230

Hi,
I have this setup: https://imgur.com/a/iwCOfs5

Can someone provide me a code sample to send something like e.g. the ASCII-Table from CAN1 to CAN2 on one Teensy 4.1. After recieving the answer send it to the serial port. I don't have some loggers or analyzing tools for the can bus. I just wanted to check out if the can bus is useable to me. For a quick test I ordered 5 parts SN65HVD230 @ amazon and now nothink works.

The wiring and the setup:
https://imgur.com/a/iwCOfs5

Thanks a lot!
 
use the new isotp integration in FlexCAN_T4. It can send/receive payloads between multiple teensies. Examples are on the repo, and it's currently running in my car project receiving isotp payloads from an ESP32
 
OK...I am stumped.

By set up and CAN sourced are confirmed with the examples so I do not think that is the issue.

Read in the DBC file and set the filters. There are only 45 ID's so 1 ID per filter.

Set the common "onReceive" function. Store the selected msg data in a structure (one per active controller) and nothing.

Should the mask be set to "07FF" for standard frames?

No quite sure why I can not get an response?

Code snippet is below:
Code:
static FlexCAN_T4_Base* myCAN[3] = { nullptr };
FlexCAN_T4<CAN1, RX_SIZE_2, TX_SIZE_16> Can1;
FlexCAN_T4<CAN2, RX_SIZE_2, TX_SIZE_16> Can2;
FlexCAN_T4<CAN3, RX_SIZE_2, TX_SIZE_16> Can3;


bool StartCAN()
{
  myCAN[0] = &Can1;
  myCAN[1] = &Can2;
  myCAN[2] = &Can3;

for (uint8_t j = 0; j < CanChannels; j++)
  {
    if (counts.messagecnt[j] > 0)
    {
      if (!SetCAN(j))
      {
#ifdef CANInitDebug
        cout << F("SetCAN Channel ") << (uint16_t)j << F(" NG") << endl;
#endif
        counts.messagecnt[j] = 0;///disable channel for the rest of the process.
        return false;
      }
      myCAN[j]->onReceive(canRecv);//set global call pack for each
    }
  }
  return true;
}
bool SetCAN(uint8_t channel)
{

    myCAN[channel]->begin();
    myCAN[channel]->setClock(CAN_Clock);
    myCAN[channel]->disableFIFO();
    myCAN[channel]->setMBFilter(REJECT_ALL);
    myCAN[channel]->setBaudRate((uint16_t)(bus[channel].BaudRate * 500));
    myCAN[channel]->setMaxMB(NUM_TX_MAILBOXES + Num_Tot_RX_MB);
...
set in a loop
myCAN[channel]->setMB((FLEXCAN_MAILBOX)i, TX, STD)
set in a loop
myCAN[channel]->setMB((FLEXCAN_MAILBOX)i, RX, STD)
...
myCAN[channel]->setMBUserFilter((FLEXCAN_MAILBOX)i, messages[channel][messcnt].ID, MAX_Std_ID)
myCAN[channel]->enhanceFilter((FLEXCAN_MAILBOX)i);


void canRecv(const CAN_message_t &msg) // global callback
{
  uint8_t busidx =  msg.bus - 1;
  GotData = true;//set data recieved flag
  cout << F("Got Frame") << endl;
  recvFrame[busidx].newFrame = true; //indicate if new frame data is recieved.
  recvFrame[busidx].id = msg.id;          // can identifier
  recvFrame[busidx].overrun = msg.flags.overrun; // message overrun
  recvFrame[busidx].len = msg.len;      // length of data
  memcpy(recvFrame[busidx].buf, msg.buf, sizeof(msg.buf[0])*msg.len);
  //uint8_t buf[8] = { 0 };       // data
  recvFrame[busidx].mb = msg.mb;       // used to identify mailbox reception
  //recvFrame.bus = msg.bus;      // used to identify where the message came from when events() is used.
  return;
}

myCAN[j]->enableMBInterrupts();//set interrupts for each active controller

I attached my code in case you can take a look.

CAN set up is all in one tab.

Mailboxstatus gives me:

FIFO Disabled
Mailboxes:
MB0 code: TX_INACTIVE
MB1 code: TX_INACTIVE
MB2 code: TX_INACTIVE
MB3 code: TX_INACTIVE
MB4 code: RX_EMPTY (Standard Frame)
MB5 code: RX_EMPTY (Standard Frame)
MB6 code: RX_EMPTY (Standard Frame)
MB7 code: RX_EMPTY (Standard Frame)
MB8 code: RX_EMPTY (Standard Frame)
MB9 code: RX_EMPTY (Standard Frame)
MB10 code: RX_EMPTY (Standard Frame)
MB11 code: RX_EMPTY (Standard Frame)
MB12 code: RX_EMPTY (Standard Frame)
MB13 code: RX_EMPTY (Standard Frame)
MB14 code: RX_EMPTY (Standard Frame)
MB15 code: RX_EMPTY (Standard Frame)
MB16 code: RX_EMPTY (Standard Frame)
MB17 code: RX_EMPTY (Standard Frame)
MB18 code: RX_EMPTY (Standard Frame)
MB19 code: RX_EMPTY (Standard Frame)
MB20 code: RX_EMPTY (Standard Frame)
MB21 code: RX_EMPTY (Standard Frame)
MB22 code: RX_EMPTY (Standard Frame)
MB23 code: RX_EMPTY (Standard Frame)
MB24 code: RX_EMPTY (Standard Frame)
MB25 code: RX_EMPTY (Standard Frame)
MB26 code: RX_EMPTY (Standard Frame)
MB27 code: RX_EMPTY (Standard Frame)
MB28 code: RX_EMPTY (Standard Frame)
MB29 code: RX_EMPTY (Standard Frame)
MB30 code: RX_EMPTY (Standard Frame)
MB31 code: RX_EMPTY (Standard Frame)
MB32 code: RX_EMPTY (Standard Frame)
MB33 code: RX_EMPTY (Standard Frame)
MB34 code: RX_EMPTY (Standard Frame)
MB35 code: RX_EMPTY (Standard Frame)
MB36 code: RX_EMPTY (Standard Frame)
MB37 code: RX_EMPTY (Standard Frame)
MB38 code: RX_EMPTY (Standard Frame)
MB39 code: RX_EMPTY (Standard Frame)
MB40 code: RX_EMPTY (Standard Frame)
MB41 code: RX_EMPTY (Standard Frame)
MB42 code: RX_EMPTY (Standard Frame)
MB43 code: RX_EMPTY (Standard Frame)
MB44 code: RX_EMPTY (Standard Frame)
MB45 code: RX_EMPTY (Standard Frame)

Thanks

Bruce
 

Attachments

  • 1_Defines.zip
    14.6 KB · Views: 53
why are you using setMBUserFilter? use the intended setMBFilter .

Also setMaxMB should be set before setMBFilters
Better yet you should be testing this with the simple demo before implementing it on a huge code, at least to see if you got the filter worked out :)
 
why are you using setMBUserFilter? use the intended setMBFilter .

Also setMaxMB should be set before setMBFilters
Better yet you should be testing this with the simple demo before implementing it on a huge code, at least to see if you got the filter worked out :)


I am using setMBUserFilter so I can use the mask so I can eventually do J1939 ID filtering (not implemented yet). This is why I am trying to grab the protocol type from the DBC file.

As you can see in the code snippet below setmaxmb is set after baud rate before setting up the MB type for setting up the filter.

So I set the max MB and MB type based the ID count/type on the then set the user filters based on the DBC file ID's.

Is there a way to check the status of the MB interrupt like the FIFO interrupt?

Thanks

Bruce
 
Yes

did you check first on a simple sketch to see if you can receive that frame with and without a filter?

I used one of the FIFO examples to confirm my CAN bus hardware is good.

I am using SavvyCAN and GRVET hardware. Thanks Collin. He has help me with Due CAN also.

Anyways so then I went for it.

So now I fell back to the MB with interrupt example but modified for the CAN traffic I have.

Code:
#include <FlexCAN_T4.h>
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can0;

#define NUM_TX_MAILBOXES 2
#define NUM_RX_MAILBOXES 4
void setup(void) {
  Serial.begin(115200); delay(400);
  // Wait for USB Serial
  while (!Serial) {
    yield();
  }
  Serial.println(F("Type any character to start"));
  while (!Serial.available()) {
    yield();
  }
  
  Can0.begin();
  Can0.disableFIFO();
  Can0.setBaudRate(500000);
  Can0.setMaxMB(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES);
  for (int i = 0; i<NUM_RX_MAILBOXES; i++){
    Can0.setMB((FLEXCAN_MAILBOX)i,RX,STD);
  }
  for (int i = NUM_RX_MAILBOXES; i<(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES); i++){
    Can0.setMB((FLEXCAN_MAILBOX)i,TX,STD);
  }
  Can0.setMBFilter(REJECT_ALL);
  Can0.enableMBInterrupts();
/*  Can0.onReceive(MB0,canSniff);
  Can0.onReceive(MB1,canSniff);*/
  Can0.onReceive(canSniff);
  Can0.setMBUserFilter(MB0,0x1A2,0x7FF);
  Can0.setMBUserFilter(MB1,0x1A0,0x7FF);
  Can0.setMBUserFilter(MB2,0x378,0x7FF);
  Can0.setMBUserFilter(MB3,0x379,0x7FF);
  Can0.mailboxStatus();
}

Well I have traffic not but no filtering"

MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 31944 ID: 379 Buffer: 10 0 0 FC 0 1E 3B FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 32292 ID: 1B5 Buffer: CC 1 5 90 22 20 22 20
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 32611 ID: 4BC Buffer: 0 0 0 12 27 10 0 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 32737 ID: 2B6 Buffer: 28 7D 4 E0 28 7D 4 E0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 32859 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 34309 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 34433 ID: 1B7 Buffer: 0 0 0 FF FF 0 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 37075 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 37309 ID: 1B3 Buffer: C6 32 0 0 7D 0 0 FC
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 37433 ID: 4BE Buffer: 0 0 0 0 0 0 0 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 37563 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 37690 ID: 2A8 Buffer: 0 0 0 0 0 0 0 FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 37825 ID: 4B6 Buffer: 3A 39 29 95 30 39 0 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 39310 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 41841 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 41969 ID: 379 Buffer: 10 0 0 FC 0 1E 3B FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 42273 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 42400 ID: 2B0 Buffer: E5 39 3A 10 24 40 24 A0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 44622 ID: 1A2 Buffer: 13 5F 0 0 0 0 FA 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 48068 ID: 2B2 Buffer: FF FF FF FF FF 7F 1F 1F
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 48194 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 48322 ID: 1B3 Buffer: C6 32 0 0 7D 0 0 FC
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 48446 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 49202 ID: 1A2 Buffer: 13 5F 0 0 0 0 FA 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 51823 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 51951 ID: 379 Buffer: 10 0 0 FC 0 1E 3B FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 52219 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 52415 ID: 2B4 Buffer: FF FF FF FF FF 7F 1F 1F
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 54824 ID: 1A2 Buffer: 13 5F 0 0 0 0 FA 0

Everything is captured in MB0.

I switch to the standard setMBFilter and magic:

FIFO Disabled
Mailboxes:
MB0 code: RX_EMPTY (Standard Frame)
MB1 code: RX_EMPTY (Standard Frame)
MB2 code: RX_EMPTY (Standard Frame)
MB3 code: RX_EMPTY (Standard Frame)
MB4 code: TX_INACTIVE
MB5 code: TX_INACTIVE
MB 1 OVERRUN: 0 LEN: 8 EXT: 0 TS: 52561 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 2 OVERRUN: 0 LEN: 8 EXT: 0 TS: 52812 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 3 OVERRUN: 0 LEN: 8 EXT: 0 TS: 53338 ID: 379 Buffer: 10 0 0 FC 0 1E 3A FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 54340 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 1 OVERRUN: 0 LEN: 8 EXT: 0 TS: 57255 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 2 OVERRUN: 0 LEN: 8 EXT: 0 TS: 57507 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 59372 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 1 OVERRUN: 0 LEN: 8 EXT: 0 TS: 61872 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 2 OVERRUN: 0 LEN: 8 EXT: 0 TS: 62389 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 3 OVERRUN: 0 LEN: 8 EXT: 0 TS: 63472 ID: 379 Buffer: 10 0 0 FC 0 1E 3A FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 64468 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 1 OVERRUN: 0 LEN: 8 EXT: 0 TS: 2407 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 2 OVERRUN: 0 LEN: 8 EXT: 0 TS: 2785 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 3852 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 1 OVERRUN: 0 LEN: 8 EXT: 0 TS: 6268 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 2 OVERRUN: 0 LEN: 8 EXT: 0 TS: 6749 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 3 OVERRUN: 0 LEN: 8 EXT: 0 TS: 7777 ID: 379 Buffer: 10 0 0 FC 0 1E 3A FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 8984 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 1 OVERRUN: 0 LEN: 8 EXT: 0 TS: 11803 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 2 OVERRUN: 0 LEN: 8 EXT: 0 TS: 12410 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 13879 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 1 OVERRUN: 0 LEN: 8 EXT: 0 TS: 17642 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 2 OVERRUN: 0 LEN: 8 EXT: 0 TS: 17770 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 3 OVERRUN: 0 LEN: 8 EXT: 0 TS: 18006 ID: 379 Buffer: 10 0 0 FC 0 1E 3A FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 19282 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0
MB 1 OVERRUN: 0 LEN: 8 EXT: 0 TS: 21723 ID: 1A0 Buffer: F9 0 0 0 0 0 0 0
MB 2 OVERRUN: 0 LEN: 8 EXT: 0 TS: 22634 ID: 378 Buffer: 10 FF FF FF FF C1 FF FF
MB 0 OVERRUN: 0 LEN: 8 EXT: 0 TS: 24770 ID: 1A2 Buffer: 13 5E 0 0 0 0 FA 0

So in the example the "user" filter does not filter but that still does not help me figure out why I do not have an interrupt fire in my code????

Thanks

Bruce
 
the User filter you may be doing it wrong. the last example used on repo used 0xFF to match the last 8 bits of listed CAN frames.

what happens if you set it to 0? 0 is pass through and each bits is checked if used if > 0

if setMBfilter works it means the mask is wrong in your user filter. the only difference between setmbfilter and setmbuserfilter is one calculates the mask automatically and the other uses your own mask...
 
For the std frame I was using 0x7ff as the mask in the example. In my code I did both 0x7ff and 0...neither worked. Could it have something to do with "enhance filter". As you can see above in the example I had one std Id with 0x7ff as the Mask and it did not filter

Thanks Bruce
 
enhancefilter is for setmbfilter

So what happens when I use it with setmbuserfilter? I can't use a mask to ignore J1939 SA and use enhancefilter?

That still does not explain why I can't use a 7ff mask with the setmbuser filter as in the same code?

It does not filter and just allows reception mb0 in the code above.

Why isn't setmbuser free not filtering with a 7ff mask?
 
if only MB0 is receiving it means everything is being captured in MB0 and read fast enough by interrupt that no other frames reach the remaining mailboxes. try setting the filter the same as the ID and see if the other's fall through?
 
As in the modified example code above I set 4 I'd of a dozen or so on the bus with setmbuserfilter and used 07ff as the mask. Only mb0 was receiving. I switched to setmbfilter and then only 4 IDs are are captured in the correct mb per the filter. Again setmbuserfilter does not filter with 0x7ff as a mask.

Thanks bruce
 
the mask is for setmbfilter is calculated properly
your mask must be wrong, try to debug the setmbfilter to print out what the mask should actually look like so you know what to put for usermask, all 32 bits are important here, even though you're using 11, then you'll see what was wrong? :)

i created the automatic masking calculations to make it easy for people to just enter IDs

the demo someone made for j1939 used 0xFF, which means the remaining 24 bits were set to don't care
 
Last edited:
Back
Top