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)
 
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 133 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 152 of file isotp.h.

153 :
154 IsoTpBase(p_txTransport, p_busIndex, p_rxFrameId, p_txFrameId),
155 rxTransport(p_rxTransport)
156 {}
ICanReceiver * rxTransport
Definition isotp.h:149

Member Function Documentation

◆ getDataFromFifo()

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

Definition at line 253 of file isotp.cpp.

253 {
254 if (rxFifoBuf.isEmpty())
255 return 0;
256 int numReadFromFifo = minI(numBytes, rxFifoBuf.getCount());
257 // move bytes from the FIFO buffer
258 int i;
259 for (i = 0; !rxFifoBuf.isEmpty() && i < numReadFromFifo; i++) {
260 rxbuf[i] = rxFifoBuf.get();
261 numBytes--;
262 }
263 return i;
264}
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > rxFifoBuf
Definition isotp.h:136

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

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

161 {
164 isComplete = false;
165}

◆ sendDataTimeout()

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

Definition at line 167 of file isotp.cpp.

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

266 {
267 int numBytes = *np;
268 int offset = 0;
269
271 PRINT("*** INFO: streamAddToTxTimeout adding %d, in buffer %d" PRINT_EOL, numBytes, txFifoBuf.getCount());
272 }
273
274 // we send here only if the TX FIFO buffer is getting overflowed
275 while (numBytes >= txFifoBuf.getSize() - txFifoBuf.getCount()) {
276 int numBytesToAdd = txFifoBuf.getSize() - txFifoBuf.getCount();
277 txFifoBuf.put(txbuf + offset, numBytesToAdd);
278 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
279
281 PRINT("*** INFO: streamAddToTxTimeout numBytesToAdd %d / numSent %d / numBytes %d" PRINT_EOL, numBytesToAdd, numSent, numBytes);
282 }
283
284 if (numSent < 1)
285 break;
286 txFifoBuf.clear();
287 offset += numBytesToAdd;
288 numBytes -= numBytesToAdd;
289 }
290
292 PRINT("*** INFO: streamAddToTxTimeout remaining goes to buffer %d" PRINT_EOL, numBytes);
293 }
294
295 // now we put the rest on hold
296 txFifoBuf.put(txbuf + offset, numBytes);
297
298
300 PRINT("*** INFO: in buffer %d" PRINT_EOL, txFifoBuf.getCount());
301 }
302
303 return CAN_MSG_OK;
304}
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > txFifoBuf
Definition isotp.h:137
int sendDataTimeout(const uint8_t *txbuf, int numBytes, can_sysinterval_t timeout)
Definition isotp.cpp:167

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

306 {
307 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
308 if (numSent != txFifoBuf.getCount()) {
309 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN sendDataTimeout() problems");
310 }
311 txFifoBuf.clear();
312
313 return CAN_MSG_OK;
314}
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 316 of file isotp.cpp.

316 {
317 size_t availableBufferSpace = *np;
318
319 // first, fill the data from the stored buffer (saved from the previous CAN frame)
320 int receivedSoFar = getDataFromFifo(rxbuf, availableBufferSpace);
321
322 // if even more data is needed, then we receive more CAN frames
323 while (availableBufferSpace > 0) {
324 CANRxFrame rxmsg;
325 if (rxTransport->receive(&rxmsg, timeout) == CAN_MSG_OK) {
326 int numReceived = receiveFrame(rxmsg, rxbuf + receivedSoFar, availableBufferSpace, timeout);
327
328 if (numReceived < 1)
329 break;
330 availableBufferSpace -= numReceived;
331 receivedSoFar += numReceived;
332 } else {
333 break;
334 }
335 }
336 *np -= availableBufferSpace;
337
338#ifdef SERIAL_CAN_DEBUG
339 efiPrintf("* ret: %d %d (%d)", i, *np, availableBufferSpace);
340 for (int j = 0; j < receivedSoFar; j++) {
341 efiPrintf("* [%d]: %02x", j, rxbuf[j]);
342 }
343#endif /* SERIAL_CAN_DEBUG */
344
345 return CAN_MSG_OK;
346}
int getDataFromFifo(uint8_t *rxbuf, size_t &numBytes)
Definition isotp.cpp:253
Here is the call graph for this function:

Field Documentation

◆ isComplete

bool CanStreamerState::isComplete {}

Definition at line 158 of file isotp.h.

158{};

Referenced by receiveFrame(), and reset().

◆ rxFifoBuf

fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> CanStreamerState::rxFifoBuf

Definition at line 136 of file isotp.h.

Referenced by getDataFromFifo(), and receiveFrame().

◆ rxTransport

ICanReceiver* CanStreamerState::rxTransport

Definition at line 149 of file isotp.h.

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

◆ txFifoBuf

fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> CanStreamerState::txFifoBuf

Definition at line 137 of file isotp.h.

Referenced by streamAddToTxTimeout(), and streamFlushTx().

◆ waitingForFrameIndex

int CanStreamerState::waitingForFrameIndex = 0

Definition at line 147 of file isotp.h.

Referenced by receiveFrame(), and reset().

◆ waitingForNumBytes

int CanStreamerState::waitingForNumBytes = 0

Definition at line 146 of file isotp.h.

Referenced by receiveFrame(), and reset().


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