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

#include <isotp.h>

Inheritance diagram for CanStreamerState:
Inheritance graph
[legend]
Collaboration diagram for CanStreamerState:
Collaboration graph
[legend]

Public Member Functions

 CanStreamerState (ICanTransmitter *p_txTransport, ICanReceiver *p_rxTransport, size_t p_busIndex, uint32_t p_rxFrameId, uint32_t p_txFrameId)
 
void reset ()
 
int sendFrame (const IsoTpFrameHeader &header, const uint8_t *data, int num, can_sysinterval_t timeout)
 
int receiveFrame (const 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)
 
- Public Member Functions inherited from IsoTpBase
 IsoTpBase (ICanTransmitter *p_txTransport, size_t p_busIndex, uint32_t p_rxFrameId, uint32_t p_txFrameId)
 
int sendFrame (const IsoTpFrameHeader &header, const uint8_t *data, int num, can_sysinterval_t timeout)
 
void sendFlowControl (can_sysinterval_t timeout)
 
can_msg_t transmit (CanTxMessage &ctfp, 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 waitingForNumBytes = 0
 
int waitingForFrameIndex = 0
 
ICanReceiverrxTransport
 
bool isComplete {}
 
- Data Fields inherited from IsoTpBase
size_t isoHeaderByteIndex = 0
 
ICanTransmittertxTransport
 
size_t busIndex
 
uint32_t rxFrameId
 
uint32_t txFrameId
 

Detailed Description

Definition at line 135 of file isotp.h.

Constructor & Destructor Documentation

◆ CanStreamerState()

CanStreamerState::CanStreamerState ( ICanTransmitter p_txTransport,
ICanReceiver p_rxTransport,
size_t  p_busIndex,
uint32_t  p_rxFrameId,
uint32_t  p_txFrameId 
)
inline

Definition at line 154 of file isotp.h.

155 :
156 IsoTpBase(p_txTransport, p_busIndex, p_rxFrameId, p_txFrameId),
157 rxTransport(p_rxTransport)
158 {}
ICanReceiver * rxTransport
Definition isotp.h:151

Member Function Documentation

◆ getDataFromFifo()

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

Definition at line 272 of file isotp.cpp.

272 {
273 if (rxFifoBuf.isEmpty())
274 return 0;
275 int numReadFromFifo = minI(numBytes, rxFifoBuf.getCount());
276 // move bytes from the FIFO buffer
277 int i;
278 for (i = 0; !rxFifoBuf.isEmpty() && i < numReadFromFifo; i++) {
279 rxbuf[i] = rxFifoBuf.get();
280 numBytes--;
281 }
282 return i;
283}
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > rxFifoBuf
Definition isotp.h:138

Referenced by streamReceiveTimeout().

Here is the caller graph for this function:

◆ receiveFrame()

int CanStreamerState::receiveFrame ( const 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 90 of file isotp.cpp.

90 {
91 if (rxmsg.DLC < 1 + isoHeaderByteIndex)
92 return 0;
94 int frameType = (rxmsg.data8[isoHeaderByteIndex] >> 4) & 0xf;
96 efiPrintf("receiveFrame frameType=%d", frameType);
97#if EFI_PROD_CODE
98 printCANRxFrame(-1, rxmsg);
99#endif // EFI_PROD_CODE
100 }
101 int numBytesAvailable, frameIdx;
102 const uint8_t *srcBuf;
103 switch (frameType) {
105 numBytesAvailable = rxmsg.data8[isoHeaderByteIndex] & 0xf;
106 this->waitingForNumBytes = numBytesAvailable;
107 srcBuf = rxmsg.data8 + 1 + isoHeaderByteIndex;
108 break;
110 this->waitingForNumBytes = ((rxmsg.data8[isoHeaderByteIndex] & 0xf) << 8) | rxmsg.data8[isoHeaderByteIndex + 1];
111 this->waitingForFrameIndex = 1;
112 numBytesAvailable = minI(this->waitingForNumBytes, 6 - isoHeaderByteIndex);
113 srcBuf = rxmsg.data8 + 2 + isoHeaderByteIndex;
114 if (rxTransport) {
115 rxTransport->onTpFirstFrame(); // used to send flow control message
116 }
117 break;
119 frameIdx = rxmsg.data8[isoHeaderByteIndex] & 0xf;
120 if (this->waitingForNumBytes < 0 || this->waitingForFrameIndex != frameIdx) {
121 // todo: that's an abnormal situation, and we probably should react?
122 return 0;
123 }
124 numBytesAvailable = minI(this->waitingForNumBytes, 7 - isoHeaderByteIndex);
125 srcBuf = rxmsg.data8 + 1 + isoHeaderByteIndex;
126 this->waitingForFrameIndex = (this->waitingForFrameIndex + 1) & 0xf;
127 break;
129 // todo: currently we just ignore the FC frame
130 return 0;
131 default:
132 // bad frame type
133 return 0;
134 }
135
136/** performance optimization specific to TS over CAN tunnelling
137TODO: refactor into child class if we ever choose to revive this logic
138#if defined(TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME)
139 if (frameType == ISO_TP_FRAME_SINGLE) {
140 // restore the CRC on the whole packet
141 uint32_t crc = crc32((void *) srcBuf, numBytesAvailable);
142 // we need a separate buffer for crc because srcBuf may not be word-aligned for direct copy
143 uint8_t crcBuffer[sizeof(uint32_t)];
144 *(uint32_t *) (crcBuffer) = SWAP_UINT32(crc);
145
146 // now set the packet size
147 *(uint16_t *) shortCrcPacketStagingArea = SWAP_UINT16(numBytesAvailable);
148 // copy the data
149 if (numBytesAvailable > 0)
150 memcpy(shortCrcPacketStagingArea + sizeof(uint16_t), srcBuf, numBytesAvailable);
151 // copy the crc to the end
152 memcpy(shortCrcPacketStagingArea + sizeof(uint16_t) + numBytesAvailable, crcBuffer, sizeof(crcBuffer));
153
154 // use the reconstructed tmp buffer as a source buffer
155 srcBuf = shortCrcPacketStagingArea;
156 // we added the 16-bit size & 32-bit crc bytes
157 numBytesAvailable += sizeof(uint16_t) + sizeof(crcBuffer);
158 }
159#endif *//* TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME */
160
161 int numBytesToCopy = minI(availableAtBuffer, numBytesAvailable);
162 if (destinationBuff != nullptr) {
163 memcpy(destinationBuff, srcBuf, numBytesToCopy);
164 }
165 srcBuf += numBytesToCopy;
166 waitingForNumBytes -= numBytesAvailable;
168 numBytesAvailable -= numBytesToCopy;
169 // if there are some more bytes left, we save them for the next time
170 for (int i = 0; i < numBytesAvailable; i++) {
171 rxFifoBuf.put(srcBuf[i]);
172 }
173
174 // according to the specs, we need to acknowledge the received multi-frame start frame
175 if (frameType == ISO_TP_FRAME_FIRST) {
176 sendFlowControl(timeout);
177 }
178
179 return numBytesToCopy;
180}
void printCANRxFrame(const size_t busIndex, const CANRxFrame &rx)
Definition can_rx.cpp:29
int waitingForNumBytes
Definition isotp.h:148
bool isComplete
Definition isotp.h:160
int waitingForFrameIndex
Definition isotp.h:149
bool pauseCANdueToSerial
Definition engine.h:127
virtual void onTpFirstFrame()=0
void sendFlowControl(can_sysinterval_t timeout)
Definition isotp.cpp:80
size_t isoHeaderByteIndex
Definition isotp.h:114
static EngineAccessor engine
Definition engine.h:421
static constexpr engine_configuration_s * engineConfiguration
@ ISO_TP_FRAME_CONSECUTIVE
Definition isotp.h:32
@ ISO_TP_FRAME_FIRST
Definition isotp.h:31
@ ISO_TP_FRAME_FLOW_CONTROL
Definition isotp.h:33
@ ISO_TP_FRAME_SINGLE
Definition isotp.h:30
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:

◆ reset()

void CanStreamerState::reset ( )

Definition at line 182 of file isotp.cpp.

182 {
185 isComplete = false;
186}

◆ sendDataTimeout()

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

Definition at line 188 of file isotp.cpp.

188 {
189 int offset = 0;
190
192 PRINT("*** INFO: sendDataTimeout %d" PRINT_EOL, numBytes);
193 }
194
195 if (numBytes < 1)
196 return 0;
197
198 // 1 frame
199 if (numBytes <= 7 - isoHeaderByteIndex) {
200 IsoTpFrameHeader header;
202 header.numBytes = numBytes;
203 return IsoTpBase::sendFrame(header, txbuf, numBytes, timeout);
204 }
205
206 // multiple frames
207
208 // send the first header frame (FF)
209 IsoTpFrameHeader header;
211 header.numBytes = numBytes;
212 int numSent = IsoTpBase::sendFrame(header, txbuf + offset, numBytes, timeout);
213 offset += numSent;
214 numBytes -= numSent;
215
216 // get a flow control (FC) frame
217#if !EFI_UNIT_TEST // todo: add FC to unit-tests?
218 CANRxFrame rxmsg;
219 for (size_t numFcReceived = 0; ; numFcReceived++) {
220 if (rxTransport->receive(&rxmsg, timeout) != CAN_MSG_OK) {
221#ifdef SERIAL_CAN_DEBUG
222 PRINT("*** ERROR: CAN Flow Control frame not received" PRINT_EOL);
223#endif /* SERIAL_CAN_DEBUG */
224 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control frame not received");
225 return 0;
226 }
227 receiveFrame(rxmsg, nullptr, 0, timeout);
228 uint8_t frameType = (rxmsg.data8[isoHeaderByteIndex] >> 4) & 0xf;
229 uint8_t flowStatus = rxmsg.data8[isoHeaderByteIndex] & 0xf;
230 // if something is not ok
231 if ((frameType != ISO_TP_FRAME_FLOW_CONTROL) || (flowStatus != CAN_FLOW_STATUS_OK)) {
232 // if the receiver is not ready yet and asks to wait for the next FC frame (give it 3 attempts)
233 if ((frameType == ISO_TP_FRAME_FLOW_CONTROL) && (flowStatus == CAN_FLOW_STATUS_WAIT_MORE) && (numFcReceived < 3)) {
234 continue;
235 }
236#ifdef SERIAL_CAN_DEBUG
237 efiPrintf("*** ERROR: CAN Flow Control mode not supported");
238#endif /* SERIAL_CAN_DEBUG */
239 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control mode not supported");
240 return 0;
241 }
242 uint8_t blockSize = rxmsg.data8[isoHeaderByteIndex + 1];
243 uint8_t minSeparationTime = rxmsg.data8[isoHeaderByteIndex + 2];
244 if (blockSize != 0 || minSeparationTime != 0) {
245 // todo: process other Flow Control fields (see ISO 15765-2)
246#ifdef SERIAL_CAN_DEBUG
247 efiPrintf("*** ERROR: CAN Flow Control fields not supported");
248#endif /* SERIAL_CAN_DEBUG */
249 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN Flow Control fields not supported");
250 }
251 break;
252 }
253#endif /* EFI_UNIT_TEST */
254
255 // send the rest of the data
256 int idx = 1;
257 while (numBytes > 0) {
258 int len = minI(numBytes, 7 - isoHeaderByteIndex);
259 // send the consecutive frames
261 header.index = ((idx++) & 0x0f);
262 header.numBytes = len;
263 numSent = IsoTpBase::sendFrame(header, txbuf + offset, len, timeout);
264 if (numSent < 1)
265 break;
266 offset += numSent;
267 numBytes -= numSent;
268 }
269 return offset;
270}
int receiveFrame(const CANRxFrame &rxmsg, uint8_t *buf, int num, can_sysinterval_t timeout)
Definition isotp.cpp:90
virtual can_msg_t receive(CANRxFrame *crfp, can_sysinterval_t timeout)=0
int sendFrame(const IsoTpFrameHeader &header, const uint8_t *data, int num, can_sysinterval_t timeout)
Definition isotp.cpp:14
IsoTpFrameType frameType
Definition isotp.h:38
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 
)

◆ streamAddToTxTimeout()

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

Definition at line 285 of file isotp.cpp.

285 {
286 int numBytes = *np;
287 int offset = 0;
288
290 PRINT("*** INFO: streamAddToTxTimeout adding %d, in buffer %d" PRINT_EOL, numBytes, txFifoBuf.getCount());
291 }
292
293 // we send here only if the TX FIFO buffer is getting overflowed
294 while (numBytes >= txFifoBuf.getSize() - txFifoBuf.getCount()) {
295 int numBytesToAdd = txFifoBuf.getSize() - txFifoBuf.getCount();
296 txFifoBuf.put(txbuf + offset, numBytesToAdd);
297 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
298
300 PRINT("*** INFO: streamAddToTxTimeout numBytesToAdd %d / numSent %d / numBytes %d" PRINT_EOL, numBytesToAdd, numSent, numBytes);
301 }
302
303 if (numSent < 1)
304 break;
305 txFifoBuf.clear();
306 offset += numBytesToAdd;
307 numBytes -= numBytesToAdd;
308 }
309
311 PRINT("*** INFO: streamAddToTxTimeout remaining goes to buffer %d" PRINT_EOL, numBytes);
312 }
313
314 // now we put the rest on hold
315 txFifoBuf.put(txbuf + offset, numBytes);
316
317
319 PRINT("*** INFO: in buffer %d" PRINT_EOL, txFifoBuf.getCount());
320 }
321
322 return CAN_MSG_OK;
323}
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > txFifoBuf
Definition isotp.h:139
int sendDataTimeout(const uint8_t *txbuf, int numBytes, can_sysinterval_t timeout)
Definition isotp.cpp:188

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 325 of file isotp.cpp.

325 {
326 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
327 if (numSent != txFifoBuf.getCount()) {
328 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN sendDataTimeout() problems");
329 }
330 txFifoBuf.clear();
331
332 return CAN_MSG_OK;
333}
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 335 of file isotp.cpp.

335 {
336 size_t availableBufferSpace = *np;
337
338 // first, fill the data from the stored buffer (saved from the previous CAN frame)
339 int receivedSoFar = getDataFromFifo(rxbuf, availableBufferSpace);
340
341 // if even more data is needed, then we receive more CAN frames
342 while (availableBufferSpace > 0) {
343 CANRxFrame rxmsg;
344 if (rxTransport->receive(&rxmsg, timeout) == CAN_MSG_OK) {
345 int numReceived = receiveFrame(rxmsg, rxbuf + receivedSoFar, availableBufferSpace, timeout);
346
347 if (numReceived < 1)
348 break;
349 availableBufferSpace -= numReceived;
350 receivedSoFar += numReceived;
351 } else {
352 break;
353 }
354 }
355 *np -= availableBufferSpace;
356
357#ifdef SERIAL_CAN_DEBUG
358 efiPrintf("* ret: %d %d (%d)", i, *np, availableBufferSpace);
359 for (int j = 0; j < receivedSoFar; j++) {
360 efiPrintf("* [%d]: %02x", j, rxbuf[j]);
361 }
362#endif /* SERIAL_CAN_DEBUG */
363
364 return CAN_MSG_OK;
365}
int getDataFromFifo(uint8_t *rxbuf, size_t &numBytes)
Definition isotp.cpp:272
Here is the call graph for this function:

Field Documentation

◆ isComplete

bool CanStreamerState::isComplete {}

Definition at line 160 of file isotp.h.

160{};

Referenced by receiveFrame(), and reset().

◆ rxFifoBuf

fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> CanStreamerState::rxFifoBuf

Definition at line 138 of file isotp.h.

Referenced by getDataFromFifo(), and receiveFrame().

◆ rxTransport

ICanReceiver* CanStreamerState::rxTransport

Definition at line 151 of file isotp.h.

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

◆ txFifoBuf

fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> CanStreamerState::txFifoBuf

Definition at line 139 of file isotp.h.

Referenced by streamAddToTxTimeout(), and streamFlushTx().

◆ waitingForFrameIndex

int CanStreamerState::waitingForFrameIndex = 0

Definition at line 149 of file isotp.h.

Referenced by receiveFrame(), and reset().

◆ waitingForNumBytes

int CanStreamerState::waitingForNumBytes = 0

Definition at line 148 of file isotp.h.

Referenced by receiveFrame(), and reset().


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