-
Notifications
You must be signed in to change notification settings - Fork 93
Description
Hi, firstly, thanks for this library!
Brief TLDR into whats happening here for this odd use case. Essentially, im writing a J2534 driver for the Macchina M2 (Essentially an arduino Due with extra hardware), and am using the due_can library for interfacing with the CAN bus on ODB2 port.
The specification states that the device should terminate and re-use CAN Interfaces, So I wrote a custom wrapper class around your can0/can1 interfaces, a simplified version of the wrapper below:
#include "can_handler.h"
#include "pc_comm.h"
// Try to init CAN interface on one of the 2 avaliable built in interfaces
canbus_handler::canbus_handler(uint8_t id, uint32_t baud) {
char buf[30] = {0x00};
sprintf(buf, "CAN Speed: %lu bps", baud);
PCCOMM::logToSerial(buf);
switch(id) {
case 0:
PCCOMM::logToSerial("Setting up Can0");
this->actLED = CAN0_LED;
this->useCan1 = false;
PCCOMM::logToSerial("Done");
this->getIface().begin(baud);
this->getIface().watchFor();
PCCOMM::logToSerial("Done1");
break;
case 1:
PCCOMM::logToSerial("Setting up Can1");
this->actLED = CAN1_LED;
this->useCan1 = true;
PCCOMM::logToSerial("Done");
this->getIface().begin(baud);
this->getIface().watchFor();
PCCOMM::logToSerial("Done1");
break;
default: // No more free CAN Interfaces! Alert the host driver
PCCOMM::logToSerial("ERROR SETTING UP CAN INVALID ID");
return;
}
}
// Couldn't find a way to store references to can0 or can1 - Macchina freezes when
// attempting to access references to them??
// So do it this way instead
CANRaw canbus_handler::getIface() {
return this->useCan1 ? Can0 : Can1;
}
// Set a filter on one of the Rx mailboxes
void canbus_handler::setFilter(uint8_t filterID, uint32_t canid, uint32_t mask, bool isExtended) {
char buf[40] = {0x00};
sprintf(buf, "Setting Rx Filters - MASK: 0x%04X, Filter: 0x%04X", mask, canid);
PCCOMM::logToSerial(buf);
for (int i = 0; i < 7; i++) {
this->getIface().setRXFilter(filterID, canid, mask, isExtended);
}
}
// Transmits a frame on the bus
void canbus_handler::transmit(CAN_FRAME f) {
digitalWrite(this->actLED, LOW);
char buf[100] = {0x00};
sprintf(buf, "CAN Sending CAN Frame. ID: 0x%04X - DLC: %d", f.id, f.length);
PCCOMM::logToSerial(buf);
if (!this->getIface().sendFrame(f)) {
PCCOMM::logToSerial("Error sending CAN Frame!");
}
}
// Attempts to read an avaliable frame from one of the mailboxes
bool canbus_handler::read(CAN_FRAME f) {
if (this->getIface().available() > 0) {
PCCOMM::logToSerial("CAN Frames avaliable");
digitalWrite(this->actLED, LOW);
this->getIface().read(f);
return true;
}
return false;
}
void canbus_handler::reset() {
PCCOMM::logToSerial("Resetting CAN Interface");
//TODO Clear Tx and Rx buffers here, and put CAN To sleep
}
// nullptr implies they are not used yet
extern canbus_handler *h0 = nullptr; // First avaliable interface (Use can0)
extern canbus_handler *h1 = nullptr; // Second avaliable interface (Use can1)Bare in mind that these classes get disposed quite reguarly and a new one is created whenever the API asks for it.
With that in mind, I've observed the following issues:
- Attempting to reference can0/can1 as a reference will cause a hard lockup when calling any method on the can interfaces (hence now the use of the getIface function in my code)
- After a re-use of my class, transmitting no longer works! - I have a arduino with an mcp2515 module hooked up to the macchina attempting to read incomming can frames
- read() does not read anything for some reason?, again, this is only after a deletion and re-creation of my handler class.
Any help much appreciated with this! - You can find the full macchina code base here if it is of any use.