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

#include <serial_can.h>

Collaboration diagram for CanStreamerState:
Collaboration graph
[legend]

Public Member Functions

 CanStreamerState (ICanStreamer *s)
 
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
 
uint8_t tmpRxBuf [13]
 
int waitingForNumBytes = 0
 
int waitingForFrameIndex = 0
 
ICanStreamerstreamer
 

Detailed Description

Definition at line 64 of file serial_can.h.

Constructor & Destructor Documentation

◆ CanStreamerState()

CanStreamerState::CanStreamerState ( ICanStreamer s)
inline

Definition at line 81 of file serial_can.h.

81: streamer(s) {}
ICanStreamer * streamer
Definition serial_can.h:78

Member Function Documentation

◆ getDataFromFifo()

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

Definition at line 262 of file serial_can.cpp.

262 {
263 if (rxFifoBuf.isEmpty())
264 return 0;
265 int numReadFromFifo = minI(numBytes, rxFifoBuf.getCount());
266 // move bytes from the FIFO buffer
267 int i;
268 for (i = 0; !rxFifoBuf.isEmpty() && i < numReadFromFifo; i++) {
269 rxbuf[i] = rxFifoBuf.get();
270 numBytes--;
271 }
272 return i;
273}
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > rxFifoBuf
Definition serial_can.h:66

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 
)

Definition at line 92 of file serial_can.cpp.

92 {
93 if (rxmsg == nullptr || rxmsg->DLC < 1)
94 return 0;
96 int frameType = (rxmsg->data8[0] >> 4) & 0xf;
97 int numBytesAvailable, frameIdx;
98 uint8_t *srcBuf = rxmsg->data8;
99 switch (frameType) {
101 numBytesAvailable = rxmsg->data8[0] & 0xf;
102 srcBuf = rxmsg->data8 + 1;
103 this->waitingForNumBytes = -1;
104 break;
106 this->waitingForNumBytes = ((rxmsg->data8[0] & 0xf) << 8) | rxmsg->data8[1];
107 this->waitingForFrameIndex = 1;
108 numBytesAvailable = minI(this->waitingForNumBytes, 6);
109 srcBuf = rxmsg->data8 + 2;
110 break;
112 frameIdx = rxmsg->data8[0] & 0xf;
113 if (this->waitingForNumBytes < 0 || this->waitingForFrameIndex != frameIdx) {
114 // todo: that's an abnormal situation, and we probably should react?
115 return 0;
116 }
117 numBytesAvailable = minI(this->waitingForNumBytes, 7);
118 srcBuf = rxmsg->data8 + 1;
119 this->waitingForFrameIndex = (this->waitingForFrameIndex + 1) & 0xf;
120 break;
122 // todo: currently we just ignore the FC frame
123 return 0;
124 default:
125 // bad frame type
126 return 0;
127 }
128
129#if defined(TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME)
130 if (frameType == ISO_TP_FRAME_SINGLE) {
131 // restore the CRC on the whole packet
132 uint32_t crc = crc32((void *) srcBuf, numBytesAvailable);
133 // we need a separate buffer for crc because srcBuf may not be word-aligned for direct copy
134 uint8_t crcBuffer[sizeof(uint32_t)];
135 *(uint32_t *) (crcBuffer) = SWAP_UINT32(crc);
136
137 // now set the packet size
138 *(uint16_t *) tmpRxBuf = SWAP_UINT16(numBytesAvailable);
139 // copy the data
140 if (numBytesAvailable > 0)
141 memcpy(tmpRxBuf + sizeof(uint16_t), srcBuf, numBytesAvailable);
142 // copy the crc to the end
143 memcpy(tmpRxBuf + sizeof(uint16_t) + numBytesAvailable, crcBuffer, sizeof(crcBuffer));
144
145 // use the reconstructed tmp buffer as a source buffer
146 srcBuf = tmpRxBuf;
147 // we added the 16-bit size & 32-bit crc bytes
148 numBytesAvailable += sizeof(uint16_t) + sizeof(crcBuffer);
149 }
150#endif /* TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME */
151
152 int numBytesToCopy = minI(num, numBytesAvailable);
153 if (buf != nullptr) {
154 memcpy(buf, srcBuf, numBytesToCopy);
155 }
156 srcBuf += numBytesToCopy;
157 waitingForNumBytes -= numBytesAvailable;
158 numBytesAvailable -= numBytesToCopy;
159 // if there are some more bytes left, we save them for the next time
160 for (int i = 0; i < numBytesAvailable; i++) {
161 rxFifoBuf.put(srcBuf[i]);
162 }
163
164 // according to the specs, we need to acknowledge the received multi-frame start frame
165 if (frameType == ISO_TP_FRAME_FIRST) {
166 IsoTpFrameHeader header;
168 header.fcFlag = 0; // = "continue to send"
169 header.blockSize = 0; // = the remaining "frames" to be sent without flow control or delay
170 header.separationTime = 0; // = wait 0 milliseconds, send immediately
171 sendFrame(header, nullptr, 0, timeout);
172 }
173
174 return numBytesToCopy;
175}
int sendFrame(const IsoTpFrameHeader &header, const uint8_t *data, int num, can_sysinterval_t timeout)
uint8_t tmpRxBuf[13]
Definition serial_can.h:71
bool pauseCANdueToSerial
Definition engine.h:123
IsoTpFrameType frameType
Definition serial_can.h:45
uint32_t SWAP_UINT32(uint32_t x)
Definition efilib.h:27
uint16_t SWAP_UINT16(uint16_t x)
Definition efilib.h:22
static EngineAccessor engine
Definition engine.h:413
@ ISO_TP_FRAME_CONSECUTIVE
Definition serial_can.h:39
@ ISO_TP_FRAME_FIRST
Definition serial_can.h:38
@ ISO_TP_FRAME_FLOW_CONTROL
Definition serial_can.h:40
@ ISO_TP_FRAME_SINGLE
Definition serial_can.h:37
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 177 of file serial_can.cpp.

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

Definition at line 40 of file serial_can.cpp.

40 {
41 int dlc = 8; // standard 8 bytes
42 CanTxMessage txmsg(CanCategory::SERIAL, CAN_ECU_SERIAL_TX_ID, dlc, /*bus*/0, IS_EXT_RANGE_ID(CAN_ECU_SERIAL_TX_ID));
43
44 // fill the frame data according to the CAN-TP protocol (ISO 15765-2)
45 txmsg[0] = (uint8_t)((header.frameType & 0xf) << 4);
46 int offset, maxNumBytes;
47 switch (header.frameType) {
49 offset = 1;
50 maxNumBytes = minI(header.numBytes, dlc - offset);
51 txmsg[0] |= maxNumBytes;
52 break;
54 txmsg[0] |= (header.numBytes >> 8) & 0xf;
55 txmsg[1] = (uint8_t)(header.numBytes & 0xff);
56 offset = 2;
57 maxNumBytes = minI(header.numBytes, dlc - offset);
58 break;
60 txmsg[0] |= header.index & 0xf;
61 offset = 1;
62 // todo: is it correct?
63 maxNumBytes = dlc - offset;
64 break;
66 txmsg[0] |= header.fcFlag & 0xf;
67 txmsg[1] = (uint8_t)(header.blockSize);
68 txmsg[2] = (uint8_t)(header.separationTime);
69 offset = 3;
70 maxNumBytes = 0; // no data is sent with 'flow control' frame
71 break;
72 default:
73 // bad frame type
74 return 0;
75 }
76
77 int numBytes = minI(maxNumBytes, num);
78 // copy the contents
79 if (data != nullptr) {
80 for (int i = 0; i < numBytes; i++) {
81 txmsg[i + offset] = data[i];
82 }
83 }
84
85 // send the frame!
86 if (streamer->transmit(CAN_ANY_MAILBOX, &txmsg, timeout) == CAN_MSG_OK)
87 return numBytes;
88 return 0;
89}
virtual can_msg_t transmit(canmbx_t mailbox, 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 275 of file serial_can.cpp.

275 {
276 int numBytes = *np;
277 int offset = 0;
278
280 PRINT("*** INFO: streamAddToTxTimeout adding %d, in buffer %d" PRINT_EOL, numBytes, txFifoBuf.getCount());
281 }
282
283 // we send here only if the TX FIFO buffer is getting overflowed
284 while (numBytes >= txFifoBuf.getSize() - txFifoBuf.getCount()) {
285 int numBytesToAdd = txFifoBuf.getSize() - txFifoBuf.getCount();
286 txFifoBuf.put(txbuf + offset, numBytesToAdd);
287 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
288
290 PRINT("*** INFO: streamAddToTxTimeout numBytesToAdd %d / numSent %d / numBytes %d" PRINT_EOL, numBytesToAdd, numSent, numBytes);
291 }
292
293 if (numSent < 1)
294 break;
295 txFifoBuf.clear();
296 offset += numBytesToAdd;
297 numBytes -= numBytesToAdd;
298 }
299
301 PRINT("*** INFO: streamAddToTxTimeout remaining goes to buffer %d" PRINT_EOL, numBytes);
302 }
303
304 // now we put the rest on hold
305 txFifoBuf.put(txbuf + offset, numBytes);
306
307
309 PRINT("*** INFO: in buffer %d" PRINT_EOL, txFifoBuf.getCount());
310 }
311
312 return CAN_MSG_OK;
313}
fifo_buffer< uint8_t, CAN_FIFO_BUF_SIZE > txFifoBuf
Definition serial_can.h:67
int sendDataTimeout(const uint8_t *txbuf, int numBytes, can_sysinterval_t timeout)
Here is the call graph for this function:

◆ streamFlushTx()

can_msg_t CanStreamerState::streamFlushTx ( can_sysinterval_t  timeout)

Definition at line 315 of file serial_can.cpp.

315 {
316 int numSent = sendDataTimeout((const uint8_t *)txFifoBuf.getElements(), txFifoBuf.getCount(), timeout);
317 if (numSent != txFifoBuf.getCount()) {
318 //warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN sendDataTimeout() problems");
319 }
320 txFifoBuf.clear();
321
322 return CAN_MSG_OK;
323}
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 325 of file serial_can.cpp.

325 {
326 size_t availableBufferSpace = *np;
327
328 // first, fill the data from the stored buffer (saved from the previous CAN frame)
329 int receivedSoFar = getDataFromFifo(rxbuf, availableBufferSpace);
330
331 // if even more data is needed, then we receive more CAN frames
332 while (availableBufferSpace > 0) {
333 CANRxFrame rxmsg;
334 if (streamer->receive(CAN_ANY_MAILBOX, &rxmsg, timeout) == CAN_MSG_OK) {
335 int numReceived = receiveFrame(&rxmsg, rxbuf + receivedSoFar, availableBufferSpace, timeout);
336
337 if (numReceived < 1)
338 break;
339 availableBufferSpace -= numReceived;
340 receivedSoFar += numReceived;
341 } else {
342 break;
343 }
344 }
345 *np -= availableBufferSpace;
346
347#ifdef SERIAL_CAN_DEBUG
348 efiPrintf("* ret: %d %d (%d)", i, *np, availableBufferSpace);
349 for (int j = 0; j < receivedSoFar; j++) {
350 efiPrintf("* [%d]: %02x", j, rxbuf[j]);
351 }
352#endif /* SERIAL_CAN_DEBUG */
353
354 return CAN_MSG_OK;
355}
int getDataFromFifo(uint8_t *rxbuf, size_t &numBytes)
Here is the call graph for this function:

Field Documentation

◆ rxFifoBuf

fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> CanStreamerState::rxFifoBuf

Definition at line 66 of file serial_can.h.

Referenced by getDataFromFifo(), and receiveFrame().

◆ streamer

ICanStreamer* CanStreamerState::streamer

Definition at line 78 of file serial_can.h.

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

◆ tmpRxBuf

uint8_t CanStreamerState::tmpRxBuf[13]

Definition at line 71 of file serial_can.h.

Referenced by receiveFrame().

◆ txFifoBuf

fifo_buffer<uint8_t, CAN_FIFO_BUF_SIZE> CanStreamerState::txFifoBuf

Definition at line 67 of file serial_can.h.

Referenced by streamAddToTxTimeout(), and streamFlushTx().

◆ waitingForFrameIndex

int CanStreamerState::waitingForFrameIndex = 0

Definition at line 76 of file serial_can.h.

Referenced by receiveFrame().

◆ waitingForNumBytes

int CanStreamerState::waitingForNumBytes = 0

Definition at line 75 of file serial_can.h.

Referenced by receiveFrame().


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