Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 15 additions & 50 deletions firmware/console/binary/serial_can.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static CanTsListener listener;
int CanStreamerState::sendFrame(
const IsoTpFrameHeader& header, const uint8_t* data, int num, can_sysinterval_t timeout) {
int dlc = 8; // standard 8 bytes
CanTxMessage txmsg(CAN_ECU_SERIAL_TX_ID, dlc, CanBusIndex::Bus0, false);
CanTxMessage txmsg(this->txId, dlc, this->busIndex, false);

// fill the frame data according to the CAN-TP protocol (ISO 15765-2)
txmsg[0] = (uint8_t)((header.frameType & 0xf) << 4);
Expand All @@ -56,9 +56,8 @@ int CanStreamerState::sendFrame(
maxNumBytes = minI(header.numBytes, dlc - offset);
break;
case ISO_TP_FRAME_CONSECUTIVE:
txmsg[0] |= header.index & 0xf;
txmsg[0] |= (uint8_t)(header.index & 0xf);
offset = 1;
// todo: is it correct?
maxNumBytes = dlc - offset;
break;
case ISO_TP_FRAME_FLOW_CONTROL:
Expand All @@ -82,7 +81,7 @@ int CanStreamerState::sendFrame(
}

// send the frame!
if (streamer->transmit(CAN_ANY_MAILBOX, &txmsg, timeout) == CAN_MSG_OK) {
if (streamer->transmit(this->txId, CAN_ANY_MAILBOX, &txmsg, timeout) == CAN_MSG_OK) {
return numBytes;
}
return 0;
Expand Down Expand Up @@ -120,36 +119,14 @@ int CanStreamerState::receiveFrame(CANRxFrame* rxmsg, uint8_t* buf, int num, can
this->waitingForFrameIndex = (this->waitingForFrameIndex + 1) & 0xf;
break;
case ISO_TP_FRAME_FLOW_CONTROL:
// todo: currently we just ignore the FC frame
// Flow control is handled inside sendDataTimeout
return 0;
default:
// bad frame type
return 0;
}

#if defined(TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME)
if (frameType == ISO_TP_FRAME_SINGLE) {
// restore the CRC on the whole packet
uint32_t crc = crc32((void*)srcBuf, numBytesAvailable);
// we need a separate buffer for crc because srcBuf may not be word-aligned for direct copy
uint8_t crcBuffer[sizeof(uint32_t)];
*(uint32_t*)(crcBuffer) = SWAP_UINT32(crc);

// now set the packet size
*(uint16_t*)tmpRxBuf = SWAP_UINT16(numBytesAvailable);
// copy the data
if (numBytesAvailable > 0) {
memcpy(tmpRxBuf + sizeof(uint16_t), srcBuf, numBytesAvailable);
}
// copy the crc to the end
memcpy(tmpRxBuf + sizeof(uint16_t) + numBytesAvailable, crcBuffer, sizeof(crcBuffer));

// use the reconstructed tmp buffer as a source buffer
srcBuf = tmpRxBuf;
// we added the 16-bit size & 32-bit crc bytes
numBytesAvailable += sizeof(uint16_t) + sizeof(crcBuffer);
}
#endif /* TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME */

int numBytesToCopy = minI(num, numBytesAvailable);
if (buf != nullptr) {
Expand Down Expand Up @@ -214,9 +191,7 @@ int CanStreamerState::sendDataTimeout(const uint8_t* txbuf, int numBytes, can_sy
CANRxFrame rxmsg;
for (int numFcReceived = 0;; numFcReceived++) {
if (streamer->receive(CAN_ANY_MAILBOX, &rxmsg, timeout) != CAN_MSG_OK) {
#ifdef SERIAL_CAN_DEBUG
PRINT("*** ERROR: CAN Flow Control frame not received" PRINT_EOL);
#endif /* SERIAL_CAN_DEBUG */

// warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control frame not received");
return 0;
}
Expand All @@ -228,21 +203,14 @@ int CanStreamerState::sendDataTimeout(const uint8_t* txbuf, int numBytes, can_sy
if (flowStatus == CAN_FLOW_STATUS_WAIT_MORE && numFcReceived < 3) {
continue;
}
#ifdef SERIAL_CAN_DEBUG
efiPrintf("*** ERROR: CAN Flow Control mode not supported");
#endif /* SERIAL_CAN_DEBUG */

// warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control mode not supported");
return 0;
}
int blockSize = rxmsg.data8[1];
int minSeparationTime = rxmsg.data8[2];
if (blockSize != 0 || minSeparationTime != 0) {
// todo: process other Flow Control fields (see ISO 15765-2)
#ifdef SERIAL_CAN_DEBUG
efiPrintf("*** ERROR: CAN Flow Control fields not supported");
#endif /* SERIAL_CAN_DEBUG */
// warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control fields not supported");
}
(void)blockSize;
(void)minSeparationTime;
break;
}
#endif /* EFI_UNIT_TEST */
Expand Down Expand Up @@ -359,12 +327,7 @@ can_msg_t CanStreamerState::streamReceiveTimeout(size_t* np, uint8_t* rxbuf, can
}
*np -= availableBufferSpace;

#ifdef SERIAL_CAN_DEBUG
efiPrintf("* ret: %d %d (%d)", i, *np, availableBufferSpace);
for (int j = 0; j < i; j++) {
efiPrintf("* [%d]: %02x", j, rxbuf[j]);
}
#endif /* SERIAL_CAN_DEBUG */


return CAN_MSG_OK;
}
Expand All @@ -387,11 +350,12 @@ void CanTsListener::decodeFrame(const CANRxFrame& frame, efitick_t /*nowNt*/) {

#if HAL_USE_CAN

void CanStreamer::init() {
void CanStreamer::init(uint32_t rxId) {
listener.init(rxId);
registerCanListener(listener);
}

can_msg_t CanStreamer::transmit(canmbx_t /*mailbox*/, const CanTxMessage* /*ctfp*/, can_sysinterval_t /*timeout*/) {
can_msg_t CanStreamer::transmit(uint32_t /*eid*/, canmbx_t /*mailbox*/, const CanTxMessage* /*ctfp*/, can_sysinterval_t /*timeout*/) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why add this parameter? it's never used!

// we do nothing here - see CanTxMessage::~CanTxMessage()
return CAN_MSG_OK;
}
Expand All @@ -406,8 +370,9 @@ can_msg_t CanStreamer::receive(canmbx_t /*mailbox*/, CANRxFrame* crfp, can_sysin
return CAN_MSG_TIMEOUT;
}

void canStreamInit(void) {
streamer.init();
void canStreamInit(uint32_t rxId, uint32_t txId, CanBusIndex busIndex) {
streamer.init(rxId);
state.init(txId, busIndex);
}

msg_t canStreamAddToTxTimeout(size_t* np, const uint8_t* txbuf, sysinterval_t timeout) {
Expand Down
33 changes: 23 additions & 10 deletions firmware/console/binary/serial_can.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class IsoTpFrameHeader {
// We need an abstraction layer for unit-testing
class ICanStreamer {
public:
virtual can_msg_t transmit(canmbx_t mailbox, const CanTxMessage* ctfp, can_sysinterval_t timeout) = 0;
virtual can_msg_t transmit(uint32_t eid, canmbx_t mailbox, const CanTxMessage* ctfp, can_sysinterval_t timeout) = 0;
virtual can_msg_t receive(canmbx_t mailbox, CANRxFrame* crfp, can_sysinterval_t timeout) = 0;
};

Expand All @@ -64,20 +64,24 @@ class CanStreamerState {
fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> rxFifoBuf;
fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> txFifoBuf;

#if defined(TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME)
// used to restore the original packet with CRC
uint8_t tmpRxBuf[13];
#endif


// used for multi-frame ISO-TP packets
int waitingForNumBytes = 0;
int waitingForFrameIndex = 0;

ICanStreamer* streamer;
uint32_t txId;
CanBusIndex busIndex;

public:
CanStreamerState(ICanStreamer* s)
: streamer(s) {}
: streamer(s), txId(0), busIndex(CanBusIndex::Bus0) {}

void init(uint32_t txIdValue, CanBusIndex busIndexValue) {
this->txId = txIdValue;
this->busIndex = busIndexValue;
}

int sendFrame(const IsoTpFrameHeader& header, const uint8_t* data, int num, can_sysinterval_t timeout);
int receiveFrame(CANRxFrame* rxmsg, uint8_t* buf, int num, can_sysinterval_t timeout);
Expand Down Expand Up @@ -111,7 +115,15 @@ class CanRxMessage {
class CanTsListener : public CanListener {
public:
CanTsListener()
: CanListener(CAN_ECU_SERIAL_RX_ID) {}
: CanListener(0) {}

void init(uint32_t idValue) {
m_id = idValue;
}

bool acceptFrame(CanBusIndex /*busIndex*/, const CANRxFrame& frame) const override {
return CAN_ID(frame) == m_id;
}

void decodeFrame(const CANRxFrame& frame, efitick_t nowNt) override;

Expand All @@ -120,19 +132,20 @@ class CanTsListener : public CanListener {
}

protected:
uint32_t m_id = 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this shadows the base class's m_id, intentional?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(add a protected setter to set the base class member, rather than shadowing)

fifo_buffer_sync<CanRxMessage, CAN_FIFO_FRAME_SIZE> rxFifo;
};

#if HAL_USE_CAN
class CanStreamer : public ICanStreamer {
public:
void init();
void init(uint32_t rxId);

virtual can_msg_t transmit(canmbx_t mailbox, const CanTxMessage* ctfp, can_sysinterval_t timeout) override;
virtual can_msg_t transmit(uint32_t eid, canmbx_t mailbox, const CanTxMessage* ctfp, can_sysinterval_t timeout) override;
virtual can_msg_t receive(canmbx_t mailbox, CANRxFrame* crfp, can_sysinterval_t timeout) override;
};

void canStreamInit(void);
void canStreamInit(uint32_t rxId, uint32_t txId, CanBusIndex busIndex);

// we don't have canStreamSendTimeout() because we need to "bufferize" the stream and send it in fixed-length packets
msg_t canStreamAddToTxTimeout(size_t* np, const uint8_t* txbuf, sysinterval_t timeout);
Expand Down
2 changes: 1 addition & 1 deletion firmware/console/binary/ts_can_channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ static CanTsThread canTsThread;

void startCanConsole() {
canTsThread.startThread();
canStreamInit();
canStreamInit(CAN_ECU_SERIAL_RX_ID, CAN_ECU_SERIAL_TX_ID, CanBusIndex::Bus0);
}

#endif // EFI_CAN_SERIAL
Loading