FlexCAN_T4 - FlexCAN for Teensy 4

did you read last line of the xlsx? :)
You basically need to keep transmitting whatever within 60 seconds for it to remain active, if you stop transmitting for 60 seconds thats it. so send every 30 seconds if you want
yes, now thanks to you, I understood everything :)
I am very grateful to you for your help!
and if, can you tell me how to write the code correctly, for these purposes ?
I will be your debtor!
 
1 then 0 workes because on the chart, Online in green is for CAN, because you were sending 1 then 1, you actually disabled canbus so the normal voltage would be output, Offline meant no canbus traffic allowed
 
try using the FIFO with interrupts example so you can see what the responses are, then try to send the message with byte0 as 1 and byte 1 as 0 and repeat send in loop with delay(5), see what it responds?

everytime its sending every 5 seconds, the powersupply 60 second counter resets, so it shouldnt timeout since your hitting it every 5 seconds, thats more of a powersupply safety, if no data is communicating it'll most likely shut down and wait
 
try using the FIFO with interrupts example so you can see what the responses are, then try to send the message with byte0 as 1 and byte 1 as 0 and repeat send in loop with delay(5), see what it responds?

everytime its sending every 5 seconds, the powersupply 60 second counter resets, so it shouldnt timeout since your hitting it every 5 seconds, thats more of a powersupply safety, if no data is communicating it'll most likely shut down and wait
Thank you for your reply!
but for me it is difficult, I cannot do that, I lack knowledge :(
I plan to send two commands sequentially,
first online, then offline, probably this is not correct, but otherwise I have no idea how to do it :)
 
this?

Code:
#include <IFCT.h>

CAN_message_t msg;

void setup() {
  Can0.setBaudRate(125000);
  Can0.enableFIFO();

  msg.ext = 1;
  msg.id = 0x108180fe;
  msg.len = 8;
  msg.buf[0] = 0x01;
  msg.buf[1] = 0x00;
  msg.buf[2] = 0x00;
  msg.buf[3] = 0x00;
  msg.buf[4] = 0x00;
  msg.buf[5] = 0x00;
  msg.buf[6] = 0xd6; //Voltage
  msg.buf[7] = 0x00;

  Can0.write(msg);
}

void loop() {


Can0.write(msg);
delay(5000);

}
 
this?

Code:
#include <IFCT.h>

CAN_message_t msg;

void setup() {
  Can0.setBaudRate(125000);
  Can0.enableFIFO();

  msg.ext = 1;
  msg.id = 0x108180fe;
  msg.len = 8;
  msg.buf[0] = 0x01;
  msg.buf[1] = 0x00;
  msg.buf[2] = 0x00;
  msg.buf[3] = 0x00;
  msg.buf[4] = 0x00;
  msg.buf[5] = 0x00;
  msg.buf[6] = 0xd6; //Voltage
  msg.buf[7] = 0x00;

  Can0.write(msg);
}

void loop() {


Can0.write(msg);
delay(5000);

}
Yes fine! Thank you!
 
tonton81, maybe you will have a free minute,
can you show me how to receive data from a block please?
with not a lot of sample code?
 
you need to use the "FIFO with interrupts" example and use the same loop() with delay you added earlier, then you'll see the responses every 5 seconds you transmit, according to the xlsx, you'll get a frame reply ACK after the send
 
you need to use the "FIFO with interrupts" example and use the same loop() with delay you added earlier, then you'll see the responses every 5 seconds you transmit, according to the xlsx, you'll get a frame reply ACK after the send
ok, I understand you, I will try to figure it out.
thank you again for your time!
 
Great work here. I am try to find out more of an understanding of the best way to set up for receiving specific messages. But, I do not know the messages at compile time so I need to set the filters in a loop. I am reading in a DBC file and I only want to receive messages in the DBC file.

Is this possible?

Also, what happens if I need to receive more than 128 messages? Can you set filter masking?

Is is 128 filters per channels or for all 3 channels?

Thoughts on the best way to set up MB/FIFO (either/or/both) when you do not know what the messages are in advance of compile time?

Any hints where to find more information on filtering/masking?

Thanks

Bruce
 
I don't see a need to filter excessively each id. FIFO has 128 filters however only the first 32 are independant, the rest work off a global filter that doesn't sense to use. There are also 64 mailboxes on T4 and 16 on T3. each mailbox (or channel as you call it?) is ONE filter, but the functions allow mixing one or more IDs on ONE filter. You can use mailboxes, or FIFO, or both. Most people use FIFO for ordered receptions and you can use additional mailboxes for interrupt (or if not using interrupts the mailboxes guarentee the latest stored ID frame remains in that mailbox until read, so other frames won't jump in, good for polling). Most people will just use FIFO with interrupts, no need for mailboxes, you can apply filters to FIFO via setFIFOFilter(0, 0x123, STD);
FILTER #0, CANID 0x123, STANDARD FRAME
by default, FIFO consumes 8 mailboxes leaving the rest as transmit, and 8 filters (0-7).

Teensy is fast enough to not drop frames, you can just filter your ID in the callback:

if ( msg.id == 0x123 ) { doSomething(); }
 
Thanks for the quick response.

The #'s you are quoting above are they for each can instance (can1,2 and 3) or for all 3?

Is there a way to set the automatic filtering in a loop or an array?

MB filter

bool setMBFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4, uint32_t id5); /* input 5 ID's to be filtered */

for example the above can set 5 id's....is there a way to set and array of ID's?

Also for the FIFO filters

Also I am trying to understand the following a little more:

What is the difference functionality between the following:

bool setFIFOUserFilter(uint8_t filter, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4, uint32_t mask, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote = NONE);

and

bool setFIFOFilter(uint8_t filter, uint32_t id1, uint32_t id2, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote = NONE); /* 2 ID's per filter */

and

bool setFIFOFilter(uint8_t filter, uint32_t id1, const FLEXCAN_IDE &ide1, const FLEXCAN_IDE &remote1, uint32_t id2, const FLEXCAN_IDE &ide2, const FLEXCAN_IDE &remote2); /* TableB 2 ID / filter */
bool setFIFOFilter(uint8_t filter, uint32_t id1, uint32_t id2, const FLEXCAN_IDE &ide1, const FLEXCAN_IDE &remote1, uint32_t id3, uint32_t id4, const FLEXCAN_IDE &ide2, const FLEXCAN_IDE &remote2); /* TableB 4 minimum ID / filter */

also the difference between:

bool setFIFOFilterRange(uint8_t filter, uint32_t id1, uint32_t id2, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote = NONE); /* ID range per filter */

and

bool setFIFOFilterRange(uint8_t filter, uint32_t id1, uint32_t id2, const FLEXCAN_IDE &ide1, const FLEXCAN_IDE &remote1, uint32_t id3, uint32_t id4, const FLEXCAN_IDE &ide2, const FLEXCAN_IDE &remote2); /* TableB dual range based IDs */

Sorry for all the questions but as you said the filtering is complicated and I could be flaying for weeks and getting no where.

Thanks

Bruce
 
Thats alot to explain, but what it comes all down to is just giving it an ID to match to and the hardware will filter that from the rest of the frames. Each instance of can1/2/3 is a completely different controller, they have their own 64 mailboxes and filters.

CanID filters and masks are a bit challenging to understand, thats why the masks are automatically generated in my code for you, so you only need to assign an ID to the function and the mailbox filter is written to the hardware register.

With the library normally you'd write 1 ID filter to a mailbox, however by using id1, id2, etc you can write up to 5 IDs that you want the hardware filter to pass. Keep in mind if there are any IDs that overlap the multiple ID filter mask, they will bleed through, this is normal expected behavior. The range function allows you to get IDs between A to B. So if you wanted IDs from 0x50 to 0x64 then it calculates the mask for all those IDs in range and writes the register, so the hardware will pass those frames in the same mailbox. The userfilter is if you want to set your own custom filter, that was added because a user wanted to mask the last 16 bits to accept multiple IDs with the last matching bits matching the acceptance. That is a little more complex for you in this case since you are just starting with filters the library generates it for you automatically. If you want to learn how to make a mask on your own there are sites out there to research on but it's not easy to explain, thats why I wrote the code to generate it for you, makes it easier to use
 
How would you handle J1939?

For example, how would you filter to ignore source and/or destination in the message ID?

Thanks

Bruce
 
Another quick question, what happens if I have more than say 60 mailboxes X 4 so 240 message of interest on the buss. How would I filter the rest of the traffic?

Also, if ISO-TP is also required, does this only work with FIFO enabled? How many MB are required for the ISO-TP (of TeensyCAN which ever is more appropriate)?

For example on vehicle of interest has standard 500K CAN traffic along with SAEJ1979 OBD messages on the same bus. So if we need to monitor for example mode $09, we needs to receive multi-frame messages.

How would you configure this along with filtering standard CAN frames?

Guidance is much appreciated rather flaying in obscurity.

Thanks

Bruce
 
the reassembly is automatic in callback for isotp, the VIN will be assembled into an array and passed to the callback with the size, just need to read the indices after.. isotp works whether you use fifo or mailboxes, doesn't matter. Why would you want 240 filters? Recommended nodes are around 40 but cars usually have ~60-80, I don't see a need to filter 240 individual IDs but you can put a range if you want in a filter and everything else will be blocked. How you decide what you want or don't want filtered I cannot guess but if I had to type out 240 assumption filters because I don't know what you want filtered I can't exactly help there :)

You don't need to specify isotp to look for mode 09, the isotp library is non-invasive you request mode 09 as usual, send a continue frame as usual (thats 2 frames you send), and the VIN should appear in the callback
 
Sorry I did not reply sooner but I just parsed 3 files...two specific to a project and one with some general PIDS just to test it.

Stats are as follows:

CAN1.dbc
CAN2.dbc
CAN3.dbc
Total Signal Count: 831
CAN: 1
Messages: 65
DBC Signals: 357
PID: 0
CAN: 2
Messages: 1
DBC Signals: 149
PID: 114
CAN: 3
Messages: 69
DBC Signals: 682
PID: 0


So realistically going to double up on some of the mail box filters.

For S and G I decided to parse a DBC file with a majority if not all J3939 and I received the following stats:

CAN: 1
Messages: 353
DBC Signals: 2146

That took a while...even for the mighty Teensy 4.1.

Thanks

Bruce
 
keep in mind if the filter is occupied and no other mailbox accepts it then the message is overridden and the overrun flag is set, you lose old message and keep latest one. For critical frames and gateways interrupts are always necessary to clear the mailboxes so new frames can be pulled in.

Also the behaviour of 2 mailboxes capturing the same IDs, in flexcan (hardware), the absolute last mailbox gets overwritten and run if the other mailboxes are not read, so if you have 3 mailboxes with same filter to catch that ID, you'll have 2 stale and 1 always latest to be read
 
Can you explain the relationship between the "RX_SIZE" and "TX_SIZE" to the # of mail boxes?

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> myCan1;

Is the RX and TX queues global to each of the can channels or per mail box?

I am assuming global? What are the steps, received in the queue/placed on the queue and then filtered/place in mailbox/FIFO or transmitted?

It says "This allows in-sketch user definable RX and TX queue size adjustments!" does this mean in compile time or in run time? If run time what function is used?

Thanks

Bruce
 
global per controller. transmits are interrupt based, they get sent out from queue while the write function just queues em. the receive queues work if you use canx.events() in loop(). if you dont use events(), the RX queue is unused and the message will fire the callback directly. the hardware filter is not done via software, so the hardware will capture only what you wanted in the controller. It's a compile time template, so the size is defined at compile time and can't be adjusted at runtime.
 
So the RX queue is not really needed if everything is put into a mailbox?

So essentially I would used the void onReceive(_MB_ptr handler); /* global callback function */ and then reference the MB which was received?

Thanks

Bruce
 
OK, now I am even more confused then before.

My concept is to use the mailboxes to filter the messages in the DBC files so I do not need to search the list of messages to find the signals which are needed to calculate the signal.

I have parsed the DBC file, one for each can channel into a message structure, a PID structure, and a signal structure. The messages structure points to the index(s) of the signals associated with that message. If the message is a PID response from J1979 which has a specific message range then the message structure points to the specific PID response(s) associated response message then the PID points to the signal(s) associated with that PID.

Once the indexes of the signals are known then the received frame can be parsed and the signal(s) contained within the frame can be calculated into engineering units and logged to the SD card.

So if I use the the mailboxes I could directly point to one or two messages to search though instead of looking through the whole 60 or so messages in each dbc file. So the question is the only way to access a mail box is either to use an interrupt or use events an the queue?

What I am afraid of is that the interrupt servicing will take up to much microcontroller time but using the queue will take up a lot of memory?

Given the above scenario what would you suggest?

Thanks for the advice in advance!

Bruce
 
without the queue the only latency you face if any will be your callback. with the queue the same callback will be ran from the events() in loop() you just need to ensure the loop can process the queue fast enough so that you wont lose any frames.
 
Back
Top