1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\r
6 * This source code is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the GNU General Public License version 2 as published by the
\r
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
\r
10 * This program is distributed in the hope that it will be useful, but
\r
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
\r
14 * -------------------------------- Arctic Core ------------------------------*/
\r
17 //lint -esym(960,8.7) PC-Lint misunderstanding of Misra 8.7 for Com_SystenEndianness and endianess_test
\r
22 #include "Com_Arc_Types.h"
\r
24 #include "Com_Internal.h"
\r
25 #include "Com_misc.h"
\r
29 static void Com_ReadDataSegment(uint8 *dest, const uint8 *source, uint8 destByteLength,
\r
30 Com_BitPositionType segmentStartBitOffset, uint8 segmentBitLength, boolean signedOutput);
\r
32 static void Com_WriteDataSegment(uint8 *pdu, uint8 *pduSignalMask, const uint8 *signalDataPtr, uint8 destByteLength,
\r
33 Com_BitPositionType segmentStartBitOffset, uint8 segmentBitLength);
\r
35 void Com_CopySignalGroupDataFromShadowBuffer(const Com_SignalIdType signalGroupId) {
\r
38 const ComSignal_type * Signal = GET_Signal(signalGroupId);
\r
39 const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);
\r
40 uint8 pduSize = IPdu->ComIPduSize;
\r
42 const void* pduDataPtr = 0;
\r
43 if (IPdu->ComIPduSignalProcessing == DEFERRED && IPdu->ComIPduDirection == RECEIVE) {
\r
44 pduDataPtr = IPdu->ComIPduDeferredDataPtr;
\r
46 pduDataPtr = IPdu->ComIPduDataPtr;
\r
52 // Get data, Aligned opaque data -> straight copy
\r
53 memcpy((void *)Signal->Com_Arc_ShadowBuffer, pduDataPtr, pduSize);
\r
58 void Com_ReadSignalDataFromPduBuffer(
\r
59 const uint16 signalId,
\r
60 const boolean isGroupSignal,
\r
62 const void *pduBuffer,
\r
65 Com_SignalType signalType;
\r
66 ComSignalEndianess_type signalEndianess;
\r
68 Com_BitPositionType bitPosition;
\r
71 if (!isGroupSignal) {
\r
72 const ComSignal_type * Signal = GET_Signal(signalId);
\r
73 signalType = Signal->ComSignalType;
\r
74 signalEndianess = Signal->ComSignalEndianess;
\r
75 signalLength = Signal->ComBitSize / 8;
\r
76 bitPosition = Signal->ComBitPosition;
\r
77 bitSize = Signal->ComBitSize;
\r
79 const ComGroupSignal_type *GroupSignal = GET_GroupSignal(signalId);
\r
80 signalType = GroupSignal->ComSignalType;
\r
81 signalEndianess = GroupSignal->ComSignalEndianess;
\r
82 signalLength = GroupSignal->ComBitSize / 8;
\r
83 bitPosition = GroupSignal->ComBitPosition;
\r
84 bitSize = GroupSignal->ComBitSize;
\r
87 uint8 destSize = SignalTypeToSize(signalType, signalLength);
\r
89 // Pointer to a byte of the source and dest respectively.
\r
90 uint8 *signalDataBytes = (uint8 *)signalData;
\r
91 uint8 signalDataBytesArray[8];
\r
92 const uint8 *pduBufferBytes = (const uint8 *)pduBuffer + (bitPosition/8);
\r
93 Com_BitPositionType startBitOffset = 0;
\r
97 if (signalEndianess == COM_OPAQUE || signalType == UINT8_N) {
\r
98 // Aligned opaque data -> straight copy
\r
99 memcpy(signalDataBytes, pduBufferBytes, destSize);
\r
102 // Unaligned data and/or endianness conversion
\r
104 if (signalEndianess == COM_LITTLE_ENDIAN) {
\r
105 // Swap source bytes before reading
\r
106 // TODO: Must adapt to larger PDUs!
\r
107 uint8 pduBufferBytes_swap[8];
\r
108 for (uint8 i = 0; i < 8; ++i) {
\r
109 pduBufferBytes_swap[i] = pduBufferBytes[7 - i];
\r
111 startBitOffset = intelBitNrToPduOffset(bitPosition%8, bitSize, 64);
\r
112 //lint -save -esym(960,12.5) PC-Lint Exception: OK. PC-Lint Wrong interpretation of MISRA rule 12.5.
\r
113 Com_ReadDataSegment(
\r
114 signalDataBytesArray, pduBufferBytes_swap, destSize,
\r
115 startBitOffset, bitSize,
\r
116 SignalTypeSignedness(signalType));
\r
119 startBitOffset = motorolaBitNrToPduOffset(bitPosition%8);
\r
120 Com_ReadDataSegment(
\r
121 signalDataBytesArray, pduBufferBytes, destSize,
\r
122 startBitOffset, bitSize,
\r
123 SignalTypeSignedness(signalType));
\r
126 if (Com_SystemEndianness == COM_BIG_ENDIAN) {
\r
129 for (i = 0; i < destSize; i++) {
\r
130 signalDataBytes[i] = signalDataBytesArray[i];
\r
133 } else if (Com_SystemEndianness == COM_LITTLE_ENDIAN) {
\r
134 // Data copy algorithm creates big-endian output data so we swap
\r
136 for (i = 0; i < destSize; i++) {
\r
137 signalDataBytes[(destSize - 1) - i] = signalDataBytesArray[i];
\r
140 //lint --e(506) PC-Lint exception Misra 13.7, 14.1, Allow boolean to always be false.
\r
144 Irq_Restore(state);
\r
148 void Com_WriteSignalDataToPdu(
\r
149 const Com_SignalIdType signalId,
\r
150 const void *signalData) {
\r
153 const ComSignal_type *Signal = GET_Signal(signalId);
\r
154 const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);
\r
155 const void* pduDataPtr = 0;
\r
157 if (IPdu->ComIPduSignalProcessing == DEFERRED && IPdu->ComIPduDirection == RECEIVE) {
\r
158 pduDataPtr = IPdu->ComIPduDeferredDataPtr;
\r
160 pduDataPtr = IPdu->ComIPduDataPtr;
\r
164 Com_WriteSignalDataToPduBuffer(
\r
169 IPdu->ComIPduSize);
\r
172 void Com_WriteGroupSignalDataToPdu(
\r
173 const Com_SignalIdType parentSignalId,
\r
174 const Com_SignalIdType groupSignalId,
\r
175 const void *signalData) {
\r
178 const ComSignal_type *Signal = GET_Signal(parentSignalId);
\r
179 const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);
\r
182 Com_WriteSignalDataToPduBuffer(
\r
185 signalData + (GET_GroupSignal(groupSignalId)->ComBitPosition / 8), // TODO, can we make sure group signals is on byte boundary
\r
186 (void *)IPdu->ComIPduDataPtr,
\r
187 IPdu->ComIPduSize);
\r
191 void Com_WriteSignalDataToPduBuffer(
\r
192 const uint16 signalId,
\r
193 const boolean isGroupSignal,
\r
194 const void *signalData,
\r
196 const uint8 pduSize) {
\r
197 // TODO: Implement writing little-endian signals
\r
199 Com_SignalType signalType;
\r
200 uint8 signalLength;
\r
201 Com_BitPositionType bitPosition;
\r
203 ComSignalEndianess_type endian;
\r
205 if (!isGroupSignal) {
\r
206 const ComSignal_type * Signal = GET_Signal(signalId);
\r
207 signalType = Signal->ComSignalType;
\r
208 signalLength = Signal->ComBitSize / 8;
\r
209 bitPosition = Signal->ComBitPosition;
\r
210 bitSize = Signal->ComBitSize;
\r
211 endian = Signal->ComSignalEndianess;
\r
213 const ComGroupSignal_type *GroupSignal = GET_GroupSignal(signalId);
\r
214 signalType = GroupSignal->ComSignalType;
\r
215 signalLength = GroupSignal->ComBitSize / 8;
\r
216 bitPosition = GroupSignal->ComBitPosition;
\r
217 bitSize = GroupSignal->ComBitSize;
\r
218 endian = GroupSignal->ComSignalEndianess;
\r
221 uint8 signalBufferSize = SignalTypeToSize(signalType, signalLength);
\r
222 uint8 pduSignalMask[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
\r
224 uint8 signalDataBytesArray[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
\r
225 const uint8 *signalDataBytes = (const uint8 *)signalData;
\r
228 Irq_Save(irq_state);
\r
229 if (endian == COM_OPAQUE || signalType == UINT8_N) {
\r
230 //assert(bitPosition % 8 == 0);
\r
231 //assert(bitSize % 8 == 0);
\r
232 uint8 *pduBufferBytes = (uint8 *)pduBuffer;
\r
233 uint8 startFromPduByte = bitPosition / 8;
\r
234 memcpy(pduBufferBytes + startFromPduByte, signalDataBytes, signalLength);
\r
236 if (Com_SystemEndianness == COM_BIG_ENDIAN) {
\r
239 for (i = 0; i < signalBufferSize; i++) {
\r
240 signalDataBytesArray[i] = signalDataBytes[i];
\r
243 } else if (Com_SystemEndianness == COM_LITTLE_ENDIAN) {
\r
244 // Data copy algorithm assumes big-endian input data so we swap
\r
246 for (i = 0; i < signalBufferSize; i++) {
\r
247 signalDataBytesArray[(signalBufferSize - 1) - i] = signalDataBytes[i];
\r
250 //lint --e(506) PC-Lint exception Misra 13.7, 14.1, Allow boolean to always be false.
\r
254 if (endian == COM_BIG_ENDIAN) {
\r
255 Com_BitPositionType startBitOffset = motorolaBitNrToPduOffset(bitPosition%8);
\r
256 uint8 pduBufferBytesStraight[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
\r
258 Com_WriteDataSegment(pduBufferBytesStraight, pduSignalMask,
\r
259 signalDataBytesArray, signalBufferSize, startBitOffset, bitSize);
\r
261 // Straight copy into real pdu buffer (with mutex)
\r
262 uint8 *pduBufferBytes = ((uint8 *)pduBuffer)+(bitPosition/8);
\r
264 for (i = 0; i < 8; i++) {
\r
265 pduBufferBytes[ i ] &= ~( pduSignalMask[ i ] );
\r
266 pduBufferBytes[ i ] |= pduBufferBytesStraight[ i ];
\r
270 uint8 startBitOffset = intelBitNrToPduOffset(bitPosition%8, bitSize, 64);
\r
271 uint8 pduBufferBytesSwapped[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
\r
273 Com_WriteDataSegment(pduBufferBytesSwapped, pduSignalMask,
\r
274 signalDataBytesArray, signalBufferSize, startBitOffset, bitSize);
\r
276 // Swapped copy into real pdu buffer (with mutex)
\r
277 uint8 *pduBufferBytes = ((uint8 *)pduBuffer)+(bitPosition/8);
\r
279 // actually it is only necessary to iterate through the bytes that are written.
\r
280 for (i = 0; i < 8; i++) {
\r
281 pduBufferBytes[ i ] &= ~( pduSignalMask[ (8 - 1) - i ] );
\r
282 pduBufferBytes[ i ] |= pduBufferBytesSwapped[ (8 - 1) - i ];
\r
286 Irq_Restore(irq_state);
\r
291 * Read an arbitrary signal segment from buffer.
\r
292 * dest: pointer to start of destination buffer
\r
293 * source: pointer to start of source buffer
\r
294 * destByteLength: size of destination buffer in bytes
\r
295 * segmentStartBitOffset: bit offset to signal segment (from first bit in *source data)
\r
296 * segmentBitLength: length in bits of the signal segment to be read
\r
299 * Source data: (ABC... = signal segment)
\r
300 * | -----ABC | DEFGHIJK | LMNOPQ-- |
\r
303 * dest: pointer to 32 bit space (needs to be at least 3 bytes to keep the 17 signal bits)
\r
304 * destByteLength: 4
\r
306 * segmentStartBitOffset: 5
\r
307 * segmentBitLength: 17
\r
311 * | -------- | -------A | BCDEFGHI | JKLMNOPQ |
\r
314 static void Com_ReadDataSegment(uint8 *dest, const uint8 *source, uint8 destByteLength,
\r
315 Com_BitPositionType segmentStartBitOffset, uint8 segmentBitLength, boolean signedOutput) {
\r
317 Com_BitPositionType sourceEndBitOffset = segmentStartBitOffset + segmentBitLength - 1;
\r
318 Com_BitPositionType sourceStartByte = segmentStartBitOffset / 8;
\r
319 uint8 sourceEndByte = (sourceEndBitOffset) / 8;
\r
320 uint8 sourceByteLength = sourceEndByte - sourceStartByte;
\r
322 uint8 segmentStartBitOffsetInsideByte = segmentStartBitOffset % 8;
\r
323 uint16 sourceStartByteMask;
\r
325 uint8 sourceAlignmentShift = 7 - (sourceEndBitOffset % 8);
\r
326 uint8 segmentByteLength = 1 + (segmentBitLength - 1) / 8;
\r
327 uint8 sourceByteNr = 0;
\r
328 uint8 destByteNr = 0;
\r
330 uint16 shiftReg = 0;
\r
334 if ( signedOutput && (*(source + sourceStartByte) & (0x80u >> segmentStartBitOffsetInsideByte)) ) {
\r
336 sourceStartByteMask = (0xFF00u >> segmentStartBitOffsetInsideByte);
\r
337 memset(dest, 0xFF, destByteLength);
\r
340 sourceStartByteMask = (0x00FFu >> segmentStartBitOffsetInsideByte);
\r
341 memset(dest, 0x00u, destByteLength);
\r
344 // setup to point to end (LSB) of buffers
\r
345 source += sourceEndByte;
\r
346 dest += destByteLength - 1;
\r
349 // compiles and writes one destination byte on each iteration
\r
351 shiftReg = *(source - sourceByteNr) | 0xFF00u; // read source byte (already matching "byte space")
\r
352 if (sourceByteNr == sourceByteLength) { // if we are on the last source byte..
\r
353 shiftReg |= sourceStartByteMask; // ..we need to mask out stuff we don't want
\r
355 shiftReg >>= sourceAlignmentShift; // shift down to align
\r
356 *(dest - destByteNr) &= shiftReg | 0xFF00u; // write into destination byte
\r
358 sourceByteNr++; // move to next source byte
\r
359 if ( (sourceAlignmentShift != 0) // do we have more bits for current dest. byte in this source byte?
\r
360 && (sourceByteNr <= sourceByteLength) ) {
\r
361 shiftReg = *(source - sourceByteNr) | 0xFF00u; // read next source byte
\r
362 if (sourceByteNr == sourceByteLength) { // if we are on the last source byte..
\r
363 shiftReg |= sourceStartByteMask; // ..we need to mask out stuff we don't want
\r
365 shiftReg = (uint16)~(shiftReg); // shifting inverted to shift in 1:s
\r
366 shiftReg <<= 8; // shift up (to match destination "byte space")
\r
367 shiftReg = (uint16)~shiftReg;
\r
368 shiftReg >>= sourceAlignmentShift; // shift down to align
\r
369 *(dest - destByteNr) &= shiftReg | 0xFF00u; // write into destination byte
\r
372 } while (destByteNr < segmentByteLength);
\r
373 } else { // positive
\r
375 shiftReg = *(source - sourceByteNr) & 0x00FFu; // read source byte (already matching "byte space")
\r
376 if (sourceByteNr == sourceByteLength) { // if we are on the last source byte..
\r
377 shiftReg &= sourceStartByteMask; // ..we need to mask out stuff we don't want
\r
379 shiftReg >>= sourceAlignmentShift; // shift down to align
\r
380 *(dest - destByteNr) |= shiftReg & 0x00FFu; // write into destination byte
\r
382 sourceByteNr++; // move to next source byte
\r
383 if (sourceAlignmentShift != 0 // do we have more bits for current dest. byte in this source byte?
\r
384 && sourceByteNr <= sourceByteLength) {
\r
385 shiftReg = *(source - sourceByteNr) & 0x00FFu; // read next source byte
\r
386 if (sourceByteNr == sourceByteLength) { // if we are on the last source byte..
\r
387 shiftReg &= sourceStartByteMask; // ..we need to mask out stuff we don't want
\r
389 shiftReg <<= 8; // shift up (to match destination "byte space")
\r
390 shiftReg >>= sourceAlignmentShift; // shift down to align
\r
391 *(dest - destByteNr) |= shiftReg & 0x00FFu; // write into destination byte
\r
394 } while (destByteNr < segmentByteLength);
\r
399 * Copies the <segmentBitLength> least significant bits from <signal> into <pdu>.
\r
400 * The bit segment is placed in <pdu> so that the most significant bit ends up
\r
401 * at <segmentStartBitOffset> from the msb of <pdu>.
\r
402 * <pduSignalMask> is cleared and written to contain a mask with 1´s where the
\r
403 * signal is located in the <pdu>.
\r
405 void Com_WriteDataSegment(uint8 *pdu, uint8 *pduSignalMask, const uint8 *signalDataPtr, uint8 destByteLength,
\r
406 Com_BitPositionType segmentStartBitOffset, uint8 segmentBitLength) {
\r
407 Com_BitPositionType pduEndBitOffset = segmentStartBitOffset + segmentBitLength - 1;
\r
408 uint8 pduStartByte = segmentStartBitOffset / 8;
\r
409 uint8 pduEndByte = (pduEndBitOffset) / 8;
\r
410 uint8 pduByteLength = pduEndByte - pduStartByte;
\r
412 uint8 segmentStartBitOffsetInsideByte = segmentStartBitOffset % 8;
\r
413 uint8 pduStartByteMask = (0xFFu >> segmentStartBitOffsetInsideByte);
\r
415 uint8 pduAlignmentShift = 7 - (pduEndBitOffset % 8);
\r
416 uint8 segmentByteLength = 1 + (segmentBitLength - 1) / 8;
\r
417 uint8 pduByteNr = 0;
\r
418 uint8 signalByteNr = 0;
\r
420 uint16 shiftReg = 0;
\r
421 uint16 clearReg = 0;
\r
423 // clear pduSignalMask all the way from 0
\r
424 memset(pduSignalMask, 0x00, pduEndByte);
\r
426 // setup to point to end (LSB) of buffers
\r
428 pduSignalMask += pduEndByte;
\r
430 signalDataPtr += destByteLength - 1;
\r
432 // splits and writes one source byte on each iteration
\r
434 shiftReg = *(signalDataPtr - signalByteNr) & 0x00FFu;
\r
436 //lint -save -e701 -e734 //PC-Lint Wrong interpretation of MISRA rule 10.5.
\r
437 shiftReg <<= pduAlignmentShift;
\r
438 clearReg <<= pduAlignmentShift;
\r
440 if (pduByteNr == pduByteLength) {
\r
441 shiftReg &= pduStartByteMask;
\r
442 clearReg &= pduStartByteMask;
\r
444 *(pdu - pduByteNr) &= (uint16)~(clearReg & 0x00FFu);
\r
445 *(pduSignalMask - pduByteNr) |= (uint16) (clearReg & 0x00FFu);
\r
446 *(pdu - pduByteNr) |= shiftReg & 0x00FFu;
\r
449 if ( (pduAlignmentShift != 0)
\r
450 && (pduByteNr <= pduByteLength) ) {
\r
451 shiftReg = *(signalDataPtr - signalByteNr) & 0x00FFu;
\r
453 //lint -save -e701 -e734 //PC-Lint Wrong interpretation of MISRA rule 10.5.
\r
454 shiftReg <<= pduAlignmentShift;
\r
455 clearReg <<= pduAlignmentShift;
\r
459 if (pduByteNr == pduByteLength) {
\r
460 shiftReg &= pduStartByteMask;
\r
461 clearReg &= pduStartByteMask;
\r
463 *(pdu - pduByteNr) &= (uint16)~(clearReg & 0x00FFu);
\r
464 *(pduSignalMask - pduByteNr) |= (uint16) (clearReg & 0x00FFu);
\r
465 *(pdu - pduByteNr) |= shiftReg & 0x00FFu;
\r
468 } while (signalByteNr < segmentByteLength);
\r
472 * Converts from motorola CAN bit nr to PDU bit offset
\r
474 * motorolaBitNr: 7 6 5 4 3 2 1 0 15 14 13 12 ...
\r
475 * motorolaBitNrToPduOffset: 0 1 2 3 4 5 6 7 8 9 10 11 ...
\r
477 Com_BitPositionType motorolaBitNrToPduOffset (Com_BitPositionType motorolaBitNr) {
\r
478 uint8 byte = motorolaBitNr / 8;
\r
479 Com_BitPositionType offsetToByteStart = (Com_BitPositionType) (byte * 8u);
\r
480 Com_BitPositionType offsetInsideByte = motorolaBitNr % 8;
\r
481 return (Com_BitPositionType) (offsetToByteStart + (7u - offsetInsideByte));
\r
485 * Converts from intel CAN bit nr to PDU bit offset
\r
488 * intelBitNr (after PDU byte-swap): 39 38 37 36 35 34 33 32 31 ... 3 2 1 0
\r
489 * intelBitNrToPduOffset: 0 1 2 3 4 5 6 7 8 ... 36 37 38 39
\r
491 Com_BitPositionType intelBitNrToPduOffset (Com_BitPositionType intelBitNr, Com_BitPositionType segmentBitLength, Com_BitPositionType pduBitLength) {
\r
492 return pduBitLength - (intelBitNr + segmentBitLength);
\r
495 void Com_RxProcessSignals(const ComIPdu_type *IPdu,Com_Arc_IPdu_type *Arc_IPdu) {
\r
496 const ComSignal_type *comSignal;
\r
497 for (uint8 i = 0; IPdu->ComIPduSignalRef[i] != NULL; i++) {
\r
498 comSignal = IPdu->ComIPduSignalRef[i];
\r
499 Com_Arc_Signal_type * Arc_Signal = GET_ArcSignal(comSignal->ComHandleId);
\r
501 // If this signal uses an update bit, then it is only considered if this bit is set.
\r
502 if ( (!comSignal->ComSignalArcUseUpdateBit) ||
\r
503 ( (comSignal->ComSignalArcUseUpdateBit) && (TESTBIT(IPdu->ComIPduDataPtr, comSignal->ComUpdateBitPosition)) ) ) {
\r
505 if (comSignal->ComTimeoutFactor > 0) { // If reception deadline monitoring is used.
\r
506 // Reset the deadline monitoring timer.
\r
507 Arc_Signal->Com_Arc_DeadlineCounter = comSignal->ComTimeoutFactor;
\r
510 // Check the signal processing mode.
\r
511 if (IPdu->ComIPduSignalProcessing == IMMEDIATE) {
\r
512 // If signal processing mode is IMMEDIATE, notify the signal callback.
\r
513 if (IPdu->ComIPduSignalRef[i]->ComNotification != NULL) {
\r
514 IPdu->ComIPduSignalRef[i]->ComNotification();
\r
518 // Signal processing mode is DEFERRED, mark the signal as updated.
\r
519 Arc_Signal->ComSignalUpdated = 1;
\r
523 DEBUG(DEBUG_LOW, "Com_RxIndication: Ignored signal %d of I-PD %d since its update bit was not set\n", comSignal->ComHandleId, ComRxPduId);
\r
527 void UnlockTpBuffer(PduIdType PduId) {
\r
528 Com_BufferPduState[PduId].locked = false;
\r
529 Com_BufferPduState[PduId].currentPosition = 0;
\r
532 boolean isPduBufferLocked(PduIdType id) {
\r
535 boolean bufferLocked = Com_BufferPduState[id].locked;
\r
536 Irq_Restore(state);
\r
537 if (bufferLocked) {
\r
543 PduIdType getPduId(const ComIPdu_type* IPdu) {
\r
544 return (PduIdType)(IPdu - (ComConfig->ComIPdu));
\r