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
 
int 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 112 of file isotp.h.

113 :
114 transport(p_transport),
115 busIndex(p_busIndex),
116 txFrameId(p_txFrameId)
117 {}
ICanTransport * transport
Definition isotp.h:106

Member Function Documentation

◆ getDataFromFifo()

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

Definition at line 235 of file isotp.cpp.

235 {
236 if (rxFifoBuf.isEmpty())
237 return 0;
238 int numReadFromFifo = minI(numBytes, rxFifoBuf.getCount());
239 // move bytes from the FIFO buffer
240 int i;
241 for (i = 0; !rxFifoBuf.isEmpty() && i < numReadFromFifo; i++) {
242 rxbuf[i] = rxFifoBuf.get();
243 numBytes--;
244 }
245 return i;
246}
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}
int isoHeaderByteIndex
Definition isotp.h:100
int sendFrame(const IsoTpFrameHeader &header, const uint8_t *data, int num, can_sysinterval_t timeout)
Definition isotp.cpp:11
int waitingForNumBytes
Definition isotp.h:103
int waitingForFrameIndex
Definition isotp.h:104
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) {
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 (int 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 int flowStatus = rxmsg.data8[0] & 0xf;
192 // if something is not ok
193 if (flowStatus != CAN_FLOW_STATUS_OK) {
194 // if the receiver is not ready yet and asks to wait for the next FC frame (give it 3 attempts)
195 if (flowStatus == CAN_FLOW_STATUS_WAIT_MORE && numFcReceived < 3) {
196 continue;
197 }
198#ifdef SERIAL_CAN_DEBUG
199 efiPrintf("*** ERROR: CAN Flow Control mode not supported");
200#endif /* SERIAL_CAN_DEBUG */
201 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control mode not supported");
202 return 0;
203 }
204 int blockSize = rxmsg.data8[1];
205 int minSeparationTime = rxmsg.data8[2];
206 if (blockSize != 0 || minSeparationTime != 0) {
207 // todo: process other Flow Control fields (see ISO 15765-2)
208#ifdef SERIAL_CAN_DEBUG
209 efiPrintf("*** ERROR: CAN Flow Control fields not supported");
210#endif /* SERIAL_CAN_DEBUG */
211 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control fields not supported");
212 }
213 break;
214 }
215#endif /* EFI_UNIT_TEST */
216
217 // send the rest of the data
218 int idx = 1;
219 while (numBytes > 0) {
220 int len = minI(numBytes, 7);
221 // send the consecutive frames
223 header.index = ((idx++) & 0x0f);
224 header.numBytes = len;
225 numSent = sendFrame(header, txbuf + offset, len, timeout);
226 if (numSent < 1)
227 break;
228 totalNumSent += numSent;
229 offset += numSent;
230 numBytes -= numSent;
231 }
232 return totalNumSent;
233}
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) {
20 offset = 1;
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 248 of file isotp.cpp.

248 {
249 int numBytes = *np;
250 int offset = 0;
251
253 PRINT("*** INFO: streamAddToTxTimeout adding %d, in buffer %d" PRINT_EOL, numBytes, txFifoBuf.getCount());
254 }
255
256 // we send here only if the TX FIFO buffer is getting overflowed
257 while (numBytes >= txFifoBuf.getSize() - txFifoBuf.getCount()) {
258 int numBytesToAdd = txFifoBuf.getSize() - txFifoBuf.getCount();
259 txFifoBuf.put(txbuf + offset, numBytesToAdd);
260 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
261
263 PRINT("*** INFO: streamAddToTxTimeout numBytesToAdd %d / numSent %d / numBytes %d" PRINT_EOL, numBytesToAdd, numSent, numBytes);
264 }
265
266 if (numSent < 1)
267 break;
268 txFifoBuf.clear();
269 offset += numBytesToAdd;
270 numBytes -= numBytesToAdd;
271 }
272
274 PRINT("*** INFO: streamAddToTxTimeout remaining goes to buffer %d" PRINT_EOL, numBytes);
275 }
276
277 // now we put the rest on hold
278 txFifoBuf.put(txbuf + offset, numBytes);
279
280
282 PRINT("*** INFO: in buffer %d" PRINT_EOL, txFifoBuf.getCount());
283 }
284
285 return CAN_MSG_OK;
286}
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 288 of file isotp.cpp.

288 {
289 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
290 if (numSent != txFifoBuf.getCount()) {
291 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN sendDataTimeout() problems");
292 }
293 txFifoBuf.clear();
294
295 return CAN_MSG_OK;
296}
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 298 of file isotp.cpp.

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

Field Documentation

◆ busIndex

int CanStreamerState::busIndex

Definition at line 108 of file isotp.h.

Referenced by sendFrame().

◆ isoHeaderByteIndex

int CanStreamerState::isoHeaderByteIndex = 0

Definition at line 100 of file isotp.h.

Referenced by receiveFrame(), 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 106 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 109 of file isotp.h.

Referenced by sendFrame().

◆ waitingForFrameIndex

int CanStreamerState::waitingForFrameIndex = 0

Definition at line 104 of file isotp.h.

Referenced by receiveFrame().

◆ waitingForNumBytes

int CanStreamerState::waitingForNumBytes = 0

Definition at line 103 of file isotp.h.

Referenced by receiveFrame().


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