Closed flybrianfly closed 1 year ago
try to run can.enableMBInterrupts() last, changing mailbox configuration will by default reset the interrupt flag for it
enableFIFO is for the legacy CAN2.0
The FD on the t4.x has no FIFO
Thanks, I tried your suggestion, the following, with the same results - no interrupts driven without events in the loop.
#include <FlexCAN_T4.h>
FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_64> can;
CANFD_message_t msg;
void setup(void) {
Serial.begin(115200);
delay(400);
can.begin();
CANFD_timings_t cfg;
cfg.clock = CLK_80MHz;
cfg.baudrate = 1000000;
cfg.baudrateFD = 8000000;
cfg.propdelay = 190;
cfg.bus_length = 1;
cfg.sample = 70;
can.setRegions(64);
can.setBaudRate(cfg);
can.setMBFilter(REJECT_ALL);
can.onReceive(MB0, isr);
can.setMBFilterRange(MB0, 0x00, 0xFF);
can.enableMBInterrupts();
can.mailboxStatus();
}
void isr(const CANFD_message_t &msg) {
Serial.println("RECEIVED INT");
}
void loop() {
if (can.read(msg)) {
Serial.println("RECEIVED LOOP");
}
}
are the terminations/transceiver correct? what happens if you transmit a few frames then check mailboxStatus(), if mailboxStatus shows frames stuck in TX it's a transceiver link issue
Terminations and transceivers should be correct, everything works fine if I poll in loop using read or events.
If I run the following receiver code and check mailboxStatus in loop once per second, I can see the MB0 to MB3 fill. Notice that this has the mailbox setup and enableMBInterrupts removed.
#include <FlexCAN_T4.h>
FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_64> can;
CANFD_message_t msg;
void setup(void) {
Serial.begin(115200);
delay(400);
can.begin();
CANFD_timings_t cfg;
cfg.clock = CLK_80MHz;
cfg.baudrate = 1000000;
cfg.baudrateFD = 8000000;
cfg.propdelay = 190;
cfg.bus_length = 1;
cfg.sample = 70;
can.setRegions(64);
can.setBaudRate(cfg);
can.mailboxStatus();
}
void isr(const CANFD_message_t &msg) {
Serial.println("RECEIVED INT");
}
void loop() {
can.mailboxStatus();
delay(1000);
}
However, if I run the code that I'm trying to get to work and fire a MB interrupt, I don't see the MB fill.
#include <FlexCAN_T4.h>
FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_64> can;
CANFD_message_t msg;
void setup(void) {
Serial.begin(115200);
delay(400);
can.begin();
CANFD_timings_t cfg;
cfg.clock = CLK_80MHz;
cfg.baudrate = 1000000;
cfg.baudrateFD = 8000000;
cfg.propdelay = 190;
cfg.bus_length = 1;
cfg.sample = 70;
can.setRegions(64);
can.setBaudRate(cfg);
can.setMBFilter(REJECT_ALL);
can.onReceive(MB0, isr);
can.setMBFilterRange(MB0, 0x00, 0xFF);
can.enableMBInterrupts();
can.mailboxStatus();
}
void isr(const CANFD_message_t &msg) {
Serial.println("RECEIVED INT");
}
void loop() {
can.mailboxStatus();
delay(1000);
}
It almost seems like the onReceive interrupt is firing, but not propagating to the ISR.
curious, what happens if you individually enable the mailboxes ? (no s) enableMBinterrupt(MB)
No change.
#include <FlexCAN_T4.h>
FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_64> can;
CANFD_message_t msg;
void setup(void) {
Serial.begin(115200);
delay(400);
can.begin();
CANFD_timings_t cfg;
cfg.clock = CLK_80MHz;
cfg.baudrate = 1000000;
cfg.baudrateFD = 8000000;
cfg.propdelay = 190;
cfg.bus_length = 1;
cfg.sample = 70;
can.setRegions(64);
can.setBaudRate(cfg);
can.setMBFilter(REJECT_ALL);
can.onReceive(MB0, isr);
can.setMBFilterRange(MB0, 0x00, 0xFF);
can.enableMBInterrupt(MB0);
can.mailboxStatus();
}
void isr(const CANFD_message_t &msg) {
Serial.println("RECEIVED INT");
}
void loop() {
can.mailboxStatus();
delay(1000);
}
what about without filters? if the mailbox shows empty it is probably being filtered out, no message means no interrupt, maybe need a debug line temporarily in the isr to see if thats firing as well (flexcan_interrupt), i dont have the stuff hooked up here yet for testing
I tried the following and am getting the same result:
#include <FlexCAN_T4.h>
FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_64> can;
CANFD_message_t msg;
void setup(void) {
Serial.begin(115200);
delay(400);
can.begin();
CANFD_timings_t cfg;
cfg.clock = CLK_80MHz;
cfg.baudrate = 1000000;
cfg.baudrateFD = 8000000;
cfg.propdelay = 190;
cfg.bus_length = 1;
cfg.sample = 70;
can.setRegions(64);
can.setBaudRate(cfg);
can.onReceive(MB0, isr);
can.enableMBInterrupt(MB0);
can.mailboxStatus();
}
void isr(const CANFD_message_t &msg) {
Serial.println("RECEIVED INT");
}
void loop() {
can.mailboxStatus();
delay(1000);
}
Again, if I remove the onReceive(MB0, isr) and enableMBInterrupt(MB0), then I can see the mail boxes fill with the mailboxStatus message.
Should I pay attention to the version of Teensyduino I'm using? Wonder when it was added to the interrupt vector table...
not sure its been along time since i worked on this, you could probably insert a serial print in the flexcan_interrupt just to see if it fires. the interrupt flags are fixed among 2 32 bit registers (identical ones used in 2.0 mode) so if theyre enabled and the ISR is not firing, then it could be an interrupt vector issue i guess
Thanks, I think I figured out the issue. flexcan_interrupt fires, but unlike the CAN2.0 implementation of struct2queueRx, the CAN-FD implementation of struct2queueRx is missing the call to mbCallbacks((FLEXCAN_MAILBOX)msg.mb, msg). It looks to me like the only way to get the mbCallbacks to fire in the CAN-FD implementation is to call the events method, which makes sense based on what I'm seeing in testing. I think if I replicate the CAN2.0 approach in the CAN-FD implementation of struct2queueRx, it should fire the onReceive callback correctly.
Merged fix, thank you
I'm trying to receive CAN-FD messages in an interrupt context without needing to call events in the loop.
Example sender code is:
Receiver code is:
My expectation is that I would see "RECEIVED INT" in the serial monitor, but I don't. I don't really care to do anything fancy with the mailboxes, I just want to receive all of the messages in the interrupt context because I plan to use the loop to do some other tasks. I would use the FIFO, but my understanding is that CAN-FD doesn't have a FIFO buffer (even though there is an enableFIFO method, so maybe my assumption is wrong). What do I need to do to make this work?