rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
Public Member Functions | Data Fields
CanStreamerState Class Reference

#include <isotp.h>

Collaboration diagram for CanStreamerState:
Collaboration graph
[legend]

Public Member Functions

 CanStreamerState (ICanTransport *p_transport, int p_busIndex, int p_txFrameId)
 
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)
 
int getDataFromFifo (uint8_t *rxbuf, size_t &numBytes)
 
int sendDataTimeout (const uint8_t *txbuf, int numBytes, can_sysinterval_t timeout)
 
can_msg_t streamAddToTxTimeout (size_t *np, const uint8_t *txbuf, can_sysinterval_t timeout)
 
can_msg_t streamFlushTx (can_sysinterval_t timeout)
 
can_msg_t streamReceiveTimeout (size_t *np, uint8_t *rxbuf, can_sysinterval_t timeout)
 

Data Fields

fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > rxFifoBuf
 
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > txFifoBuf
 
size_t isoHeaderByteIndex = 0
 
int waitingForNumBytes = 0
 
int waitingForFrameIndex = 0
 
ICanTransporttransport
 
int busIndex
 
int txFrameId
 

Detailed Description

Definition at line 88 of file isotp.h.

Constructor & Destructor Documentation

◆ CanStreamerState()

CanStreamerState::CanStreamerState ( ICanTransport p_transport,
int  p_busIndex,
int  p_txFrameId 
)
inline

Definition at line 114 of file isotp.h.

115 :
116 transport(p_transport),
117 busIndex(p_busIndex),
118 txFrameId(p_txFrameId)
119 {}
ICanTransport * transport
Definition isotp.h:108

Member Function Documentation

◆ getDataFromFifo()

int CanStreamerState::getDataFromFifo ( uint8_t *  rxbuf,
size_t numBytes 
)

Definition at line 236 of file isotp.cpp.

236 {
237 if (rxFifoBuf.isEmpty())
238 return 0;
239 int numReadFromFifo = minI(numBytes, rxFifoBuf.getCount());
240 // move bytes from the FIFO buffer
241 int i;
242 for (i = 0; !rxFifoBuf.isEmpty() && i < numReadFromFifo; i++) {
243 rxbuf[i] = rxFifoBuf.get();
244 numBytes--;
245 }
246 return i;
247}
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > rxFifoBuf
Definition isotp.h:90

Referenced by streamReceiveTimeout().

Here is the caller graph for this function:

◆ receiveFrame()

int CanStreamerState::receiveFrame ( CANRxFrame rxmsg,
uint8_t *  buf,
int  num,
can_sysinterval_t  timeout 
)

performance optimization specific to TS over CAN tunnelling TODO: refactor into child class if we ever choose to revive this logic #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 *) shortCrcPacketStagingArea = SWAP_UINT16(numBytesAvailable); copy the data if (numBytesAvailable > 0) memcpy(shortCrcPacketStagingArea + sizeof(uint16_t), srcBuf, numBytesAvailable); copy the crc to the end memcpy(shortCrcPacketStagingArea + sizeof(uint16_t) + numBytesAvailable, crcBuffer, sizeof(crcBuffer));

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

Definition at line 63 of file isotp.cpp.

63 {
64 if (rxmsg == nullptr || rxmsg->DLC < 1)
65 return 0;
67 int frameType = (rxmsg->data8[isoHeaderByteIndex] >> 4) & 0xf;
68 int numBytesAvailable, frameIdx;
69 uint8_t *srcBuf = rxmsg->data8;
70 switch (frameType) {
72 numBytesAvailable = rxmsg->data8[isoHeaderByteIndex] & 0xf;
73 srcBuf = rxmsg->data8 + 1;
74 this->waitingForNumBytes = -1;
75 break;
77 this->waitingForNumBytes = ((rxmsg->data8[isoHeaderByteIndex] & 0xf) << 8) | rxmsg->data8[isoHeaderByteIndex + 1];
78 this->waitingForFrameIndex = 1;
79 numBytesAvailable = minI(this->waitingForNumBytes, 6 - isoHeaderByteIndex);
80 srcBuf = rxmsg->data8 + 2 + isoHeaderByteIndex;
81 break;
83 frameIdx = rxmsg->data8[isoHeaderByteIndex] & 0xf;
84 if (this->waitingForNumBytes < 0 || this->waitingForFrameIndex != frameIdx) {
85 // todo: that's an abnormal situation, and we probably should react?
86 return 0;
87 }
88 numBytesAvailable = minI(this->waitingForNumBytes, 7 - isoHeaderByteIndex);
89 srcBuf = rxmsg->data8 + 1 + isoHeaderByteIndex;
90 this->waitingForFrameIndex = (this->waitingForFrameIndex + 1) & 0xf;
91 break;
93 // todo: currently we just ignore the FC frame
94 return 0;
95 default:
96 // bad frame type
97 return 0;
98 }
99
100/** performance optimization specific to TS over CAN tunnelling
101TODO: refactor into child class if we ever choose to revive this logic
102#if defined(TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME)
103 if (frameType == ISO_TP_FRAME_SINGLE) {
104 // restore the CRC on the whole packet
105 uint32_t crc = crc32((void *) srcBuf, numBytesAvailable);
106 // we need a separate buffer for crc because srcBuf may not be word-aligned for direct copy
107 uint8_t crcBuffer[sizeof(uint32_t)];
108 *(uint32_t *) (crcBuffer) = SWAP_UINT32(crc);
109
110 // now set the packet size
111 *(uint16_t *) shortCrcPacketStagingArea = SWAP_UINT16(numBytesAvailable);
112 // copy the data
113 if (numBytesAvailable > 0)
114 memcpy(shortCrcPacketStagingArea + sizeof(uint16_t), srcBuf, numBytesAvailable);
115 // copy the crc to the end
116 memcpy(shortCrcPacketStagingArea + sizeof(uint16_t) + numBytesAvailable, crcBuffer, sizeof(crcBuffer));
117
118 // use the reconstructed tmp buffer as a source buffer
119 srcBuf = shortCrcPacketStagingArea;
120 // we added the 16-bit size & 32-bit crc bytes
121 numBytesAvailable += sizeof(uint16_t) + sizeof(crcBuffer);
122 }
123#endif *//* TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME */
124
125 int numBytesToCopy = minI(num, numBytesAvailable);
126 if (buf != nullptr) {
127 memcpy(buf, srcBuf, numBytesToCopy);
128 }
129 srcBuf += numBytesToCopy;
130 waitingForNumBytes -= numBytesAvailable;
131 numBytesAvailable -= numBytesToCopy;
132 // if there are some more bytes left, we save them for the next time
133 for (int i = 0; i < numBytesAvailable; i++) {
134 rxFifoBuf.put(srcBuf[i]);
135 }
136
137 // according to the specs, we need to acknowledge the received multi-frame start frame
138 if (frameType == ISO_TP_FRAME_FIRST) {
139 IsoTpFrameHeader header;
141 header.fcFlag = 0; // = "continue to send"
142 header.blockSize = 0; // = the remaining "frames" to be sent without flow control or delay
143 header.separationTime = 0; // = wait 0 milliseconds, send immediately
144 sendFrame(header, nullptr, 0, timeout);
145 }
146
147 return numBytesToCopy;
148}
size_t isoHeaderByteIndex
Definition isotp.h:102
int sendFrame(const IsoTpFrameHeader &header, const uint8_t *data, int num, can_sysinterval_t timeout)
Definition isotp.cpp:11
int waitingForNumBytes
Definition isotp.h:105
int waitingForFrameIndex
Definition isotp.h:106
bool pauseCANdueToSerial
Definition engine.h:123
IsoTpFrameType frameType
Definition isotp.h:36
int separationTime
Definition isotp.h:45
static EngineAccessor engine
Definition engine.h:413
@ ISO_TP_FRAME_CONSECUTIVE
Definition isotp.h:30
@ ISO_TP_FRAME_FIRST
Definition isotp.h:29
@ ISO_TP_FRAME_FLOW_CONTROL
Definition isotp.h:31
@ ISO_TP_FRAME_SINGLE
Definition isotp.h:28
uint8_t data8[8]
Frame data.
Definition can_mocks.h:55
uint8_t DLC
Data length.
Definition can_mocks.h:42

Referenced by sendDataTimeout(), and streamReceiveTimeout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sendDataTimeout()

int CanStreamerState::sendDataTimeout ( const uint8_t *  txbuf,
int  numBytes,
can_sysinterval_t  timeout 
)

Definition at line 150 of file isotp.cpp.

150 {
151 int offset = 0;
152
154 PRINT("*** INFO: sendDataTimeout %d" PRINT_EOL, numBytes);
155 }
156
157 if (numBytes < 1)
158 return 0;
159
160 // 1 frame
161 if (numBytes <= 7 - isoHeaderByteIndex) {
162 IsoTpFrameHeader header;
164 header.numBytes = numBytes;
165 return sendFrame(header, txbuf, numBytes, timeout);
166 }
167
168 // multiple frames
169
170 // send the first header frame (FF)
171 IsoTpFrameHeader header;
173 header.numBytes = numBytes;
174 int numSent = sendFrame(header, txbuf + offset, numBytes, timeout);
175 offset += numSent;
176 numBytes -= numSent;
177 int totalNumSent = numSent;
178
179 // get a flow control (FC) frame
180#if !EFI_UNIT_TEST // todo: add FC to unit-tests?
181 CANRxFrame rxmsg;
182 for (size_t numFcReceived = 0; ; numFcReceived++) {
183 if (transport->receive(&rxmsg, timeout) != CAN_MSG_OK) {
184#ifdef SERIAL_CAN_DEBUG
185 PRINT("*** ERROR: CAN Flow Control frame not received" PRINT_EOL);
186#endif /* SERIAL_CAN_DEBUG */
187 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control frame not received");
188 return 0;
189 }
190 receiveFrame(&rxmsg, nullptr, 0, timeout);
191 uint8_t frameType = (rxmsg.data8[isoHeaderByteIndex] >> 4) & 0xf;
192 uint8_t flowStatus = rxmsg.data8[isoHeaderByteIndex] & 0xf;
193 // if something is not ok
194 if ((frameType != ISO_TP_FRAME_FLOW_CONTROL) || (flowStatus != CAN_FLOW_STATUS_OK)) {
195 // if the receiver is not ready yet and asks to wait for the next FC frame (give it 3 attempts)
196 if ((frameType == ISO_TP_FRAME_FLOW_CONTROL) && (flowStatus == CAN_FLOW_STATUS_WAIT_MORE) && (numFcReceived < 3)) {
197 continue;
198 }
199#ifdef SERIAL_CAN_DEBUG
200 efiPrintf("*** ERROR: CAN Flow Control mode not supported");
201#endif /* SERIAL_CAN_DEBUG */
202 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control mode not supported");
203 return 0;
204 }
205 uint8_t blockSize = rxmsg.data8[isoHeaderByteIndex + 1];
206 uint8_t minSeparationTime = rxmsg.data8[isoHeaderByteIndex + 2];
207 if (blockSize != 0 || minSeparationTime != 0) {
208 // todo: process other Flow Control fields (see ISO 15765-2)
209#ifdef SERIAL_CAN_DEBUG
210 efiPrintf("*** ERROR: CAN Flow Control fields not supported");
211#endif /* SERIAL_CAN_DEBUG */
212 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control fields not supported");
213 }
214 break;
215 }
216#endif /* EFI_UNIT_TEST */
217
218 // send the rest of the data
219 int idx = 1;
220 while (numBytes > 0) {
221 int len = minI(numBytes, 7);
222 // send the consecutive frames
224 header.index = ((idx++) & 0x0f);
225 header.numBytes = len;
226 numSent = sendFrame(header, txbuf + offset, len, timeout);
227 if (numSent < 1)
228 break;
229 totalNumSent += numSent;
230 offset += numSent;
231 numBytes -= numSent;
232 }
233 return totalNumSent;
234}
int receiveFrame(CANRxFrame *rxmsg, uint8_t *buf, int num, can_sysinterval_t timeout)
Definition isotp.cpp:63
virtual can_msg_t receive(CANRxFrame *crfp, can_sysinterval_t timeout)=0
static constexpr engine_configuration_s * engineConfiguration
uint16_t offset
Definition tunerstudio.h:0

Referenced by streamAddToTxTimeout(), and streamFlushTx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sendFrame()

int CanStreamerState::sendFrame ( const IsoTpFrameHeader header,
const uint8_t *  data,
int  num,
can_sysinterval_t  timeout 
)

https://en.wikipedia.org/wiki/ISO_15765-2

Definition at line 11 of file isotp.cpp.

11 {
12 int dlc = 8; // standard 8 bytes
13 CanTxMessage txmsg(CanCategory::SERIAL, txFrameId, dlc, busIndex, IS_EXT_RANGE_ID(txFrameId));
14
15 // fill the frame data according to the CAN-TP protocol (ISO 15765-2)
16 txmsg[isoHeaderByteIndex] = (uint8_t)((header.frameType & 0xf) << 4);
17 int offset, maxNumBytes;
18 switch (header.frameType) {
21 maxNumBytes = minI(header.numBytes, dlc - offset);
22 txmsg[isoHeaderByteIndex] |= maxNumBytes;
23 break;
25 txmsg[isoHeaderByteIndex] |= (header.numBytes >> 8) & 0xf;
26 txmsg[isoHeaderByteIndex + 1] = (uint8_t)(header.numBytes & 0xff);
28 maxNumBytes = minI(header.numBytes, dlc - offset);
29 break;
31 txmsg[isoHeaderByteIndex] |= header.index & 0xf;
33 // todo: is it correct?
34 maxNumBytes = dlc - offset;
35 break;
37 txmsg[isoHeaderByteIndex] |= header.fcFlag & 0xf;
38 txmsg[isoHeaderByteIndex + 1] = (uint8_t)(header.blockSize);
39 txmsg[isoHeaderByteIndex + 2] = (uint8_t)(header.separationTime);
41 maxNumBytes = 0; // no data is sent with 'flow control' frame
42 break;
43 default:
44 // bad frame type
45 return 0;
46 }
47
48 int numBytes = minI(maxNumBytes, num);
49 // copy the contents
50 if (data != nullptr) {
51 for (int i = 0; i < numBytes; i++) {
52 txmsg[i + offset] = data[i];
53 }
54 }
55
56 // send the frame!
57 if (transport->transmit(&txmsg, timeout) == CAN_MSG_OK)
58 return numBytes;
59 return 0;
60}
virtual can_msg_t transmit(const CanTxMessage *ctfp, can_sysinterval_t timeout)=0

Referenced by receiveFrame(), and sendDataTimeout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ streamAddToTxTimeout()

can_msg_t CanStreamerState::streamAddToTxTimeout ( size_t np,
const uint8_t *  txbuf,
can_sysinterval_t  timeout 
)

Definition at line 249 of file isotp.cpp.

249 {
250 int numBytes = *np;
251 int offset = 0;
252
254 PRINT("*** INFO: streamAddToTxTimeout adding %d, in buffer %d" PRINT_EOL, numBytes, txFifoBuf.getCount());
255 }
256
257 // we send here only if the TX FIFO buffer is getting overflowed
258 while (numBytes >= txFifoBuf.getSize() - txFifoBuf.getCount()) {
259 int numBytesToAdd = txFifoBuf.getSize() - txFifoBuf.getCount();
260 txFifoBuf.put(txbuf + offset, numBytesToAdd);
261 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
262
264 PRINT("*** INFO: streamAddToTxTimeout numBytesToAdd %d / numSent %d / numBytes %d" PRINT_EOL, numBytesToAdd, numSent, numBytes);
265 }
266
267 if (numSent < 1)
268 break;
269 txFifoBuf.clear();
270 offset += numBytesToAdd;
271 numBytes -= numBytesToAdd;
272 }
273
275 PRINT("*** INFO: streamAddToTxTimeout remaining goes to buffer %d" PRINT_EOL, numBytes);
276 }
277
278 // now we put the rest on hold
279 txFifoBuf.put(txbuf + offset, numBytes);
280
281
283 PRINT("*** INFO: in buffer %d" PRINT_EOL, txFifoBuf.getCount());
284 }
285
286 return CAN_MSG_OK;
287}
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > txFifoBuf
Definition isotp.h:91
int sendDataTimeout(const uint8_t *txbuf, int numBytes, can_sysinterval_t timeout)
Definition isotp.cpp:150

Referenced by canStreamAddToTxTimeout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ streamFlushTx()

can_msg_t CanStreamerState::streamFlushTx ( can_sysinterval_t  timeout)

Definition at line 289 of file isotp.cpp.

289 {
290 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
291 if (numSent != txFifoBuf.getCount()) {
292 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN sendDataTimeout() problems");
293 }
294 txFifoBuf.clear();
295
296 return CAN_MSG_OK;
297}
Here is the call graph for this function:

◆ streamReceiveTimeout()

can_msg_t CanStreamerState::streamReceiveTimeout ( size_t np,
uint8_t *  rxbuf,
can_sysinterval_t  timeout 
)

Definition at line 299 of file isotp.cpp.

299 {
300 size_t availableBufferSpace = *np;
301
302 // first, fill the data from the stored buffer (saved from the previous CAN frame)
303 int receivedSoFar = getDataFromFifo(rxbuf, availableBufferSpace);
304
305 // if even more data is needed, then we receive more CAN frames
306 while (availableBufferSpace > 0) {
307 CANRxFrame rxmsg;
308 if (transport->receive(&rxmsg, timeout) == CAN_MSG_OK) {
309 int numReceived = receiveFrame(&rxmsg, rxbuf + receivedSoFar, availableBufferSpace, timeout);
310
311 if (numReceived < 1)
312 break;
313 availableBufferSpace -= numReceived;
314 receivedSoFar += numReceived;
315 } else {
316 break;
317 }
318 }
319 *np -= availableBufferSpace;
320
321#ifdef SERIAL_CAN_DEBUG
322 efiPrintf("* ret: %d %d (%d)", i, *np, availableBufferSpace);
323 for (int j = 0; j < receivedSoFar; j++) {
324 efiPrintf("* [%d]: %02x", j, rxbuf[j]);
325 }
326#endif /* SERIAL_CAN_DEBUG */
327
328 return CAN_MSG_OK;
329}
int getDataFromFifo(uint8_t *rxbuf, size_t &numBytes)
Definition isotp.cpp:236
Here is the call graph for this function:

Field Documentation

◆ busIndex

int CanStreamerState::busIndex

Definition at line 110 of file isotp.h.

Referenced by sendFrame().

◆ isoHeaderByteIndex

size_t CanStreamerState::isoHeaderByteIndex = 0

Definition at line 102 of file isotp.h.

Referenced by receiveFrame(), sendDataTimeout(), and sendFrame().

◆ rxFifoBuf

fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> CanStreamerState::rxFifoBuf

Definition at line 90 of file isotp.h.

Referenced by getDataFromFifo(), and receiveFrame().

◆ transport

ICanTransport* CanStreamerState::transport

Definition at line 108 of file isotp.h.

Referenced by sendDataTimeout(), sendFrame(), and streamReceiveTimeout().

◆ txFifoBuf

fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> CanStreamerState::txFifoBuf

Definition at line 91 of file isotp.h.

Referenced by streamAddToTxTimeout(), and streamFlushTx().

◆ txFrameId

int CanStreamerState::txFrameId

Definition at line 111 of file isotp.h.

Referenced by sendFrame().

◆ waitingForFrameIndex

int CanStreamerState::waitingForFrameIndex = 0

Definition at line 106 of file isotp.h.

Referenced by receiveFrame().

◆ waitingForNumBytes

int CanStreamerState::waitingForNumBytes = 0

Definition at line 105 of file isotp.h.

Referenced by receiveFrame().


The documentation for this class was generated from the following files: