I have a project that needs to log all CAN-FD packets on a bus. It is working fine for low data rates (100Hz packets) but as soon as I turn the data rate up I get the overrun flag set and drop data.
The exact same logging code but reading from an external SPI CAN-FD device, which should be significantly slower, can keep up with 400Hz packets.
This makes me suspect it's some sort of buffering issue, I just need to turn the correct feature on but I can't see what that is.
Currently data is read in a loop in a teensyThread that queues it up into a buffer. This buffer is then written to the SD card in a different thread. The buffer is large enough that it's not overflowing.
I know polling in a thread like this isn't ideal but works fine for the SPI device, it could be that the SPI device has more buffering.
Moving to an RxInterrupt based solution would be fine but when I try this I don't get any interrupts, again hopefully something simple that I've missed.
It's part of a larger project so hard to give full code but I think I've included all the relevant bits below. setup(); calls the init function and then starts the thread.
The exact same logging code but reading from an external SPI CAN-FD device, which should be significantly slower, can keep up with 400Hz packets.
This makes me suspect it's some sort of buffering issue, I just need to turn the correct feature on but I can't see what that is.
Currently data is read in a loop in a teensyThread that queues it up into a buffer. This buffer is then written to the SD card in a different thread. The buffer is large enough that it's not overflowing.
I know polling in a thread like this isn't ideal but works fine for the SPI device, it could be that the SPI device has more buffering.
Moving to an RxInterrupt based solution would be fine but when I try this I don't get any interrupts, again hopefully something simple that I've missed.
It's part of a larger project so hard to give full code but I think I've included all the relevant bits below. setup(); calls the init function and then starts the thread.
Code:
FlexCAN_T4FD<CAN3, RX_SIZE_1024, TX_SIZE_16> IntCAN;
void initInternalCAN() {
IntCAN.begin();
CANFD_timings_t config;
config.clock = CLK_24MHz;
config.baudrate = 1000000;
config.baudrateFD = 2000000;
config.propdelay = 190;
config.bus_length = 1;
config.sample = 85;
IntCAN.setBaudRate(config);
IntCAN.setRegions(64);
IntCAN.onReceive(internalCANRxIrq);
}
void internalCANRxIrq(const CANFD_message_t &packetIn){
// this never gets called
}
void CAN_Thread() {
CANFD_message_t IntFrameIn;
IntCAN.events();
Serial.println("CAN thread running");
while (1) {
if (IntCAN.read(IntFrameIn)) {
if (readIntCan(IntFrameIn,CANQueue+CANQueue_WritePtr)) {
// increase packet queue tracking - queue never overflows.
}
} else if (useExternal && ExtCan.receive (ExtFrameIn)) {
if (readExtCan(ExtFrameIn,CANQueue+CANQueue_WritePtr)) {
// increase packet queue tracking - queue never overflows.
}
} else {
threads.yield();
}
}
}
bool readIntCan(CANFD_message_t &packetIn, RL_CANPacket_t *PacketConverted) {
// Serial.println("Internal CAN rx");
if (packetIn.esi || packetIn.flags.overrun) {
if (packetIn.flags.overrun)
Serial.println("Overrun"); // hit this line with packet rates over 100Hz
return false;
}
// convert packet data to common logging structure
// ....
//
return true;
}
bool readExtCan(ExternalCANPacketStruct &packetIn, RL_CANPacket_t *PacketConverted) {
// convert packet data to common logging structure
// ....
//
return true;
}