//*****************************************************************************
// (C) Automotive Lighting Reutlingen GmbH
// Tuebinger Strasse 123, 72762 Reutlingen, Germany
//
// Automotive Lighting Reutlingen GmbH owns all the rights to this work.
// This work shall not be copied, reproduced, used, modified, transferred
// or its information shall not be disclosed without the prior written
// authorization of Automotive Lighting Reutlingen GmbH.
//*****************************************************************************
//-----------------------------------------------------------------------------
/// \file ISO15765.c
///
/// \brief
///
/// \descr
///
/// Additional information can be found in the design description (Link:
/// MDDD)
///
/// \author Ramona-Andreea Bolboaca (f33613c)
/// mailTo:ramona-andreea.bolboaca(at)magnetimarelli.com
//-----------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#if ((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD)
#include
#elif ((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CAN) == CFG_ISO15765_COM_TYPE_CAN)
#ifndef CFG_TYP_PRJ2
#include
#elif (CFG_TYP_PRJ2 != CFG_Prj_LED_6_2)
#include
#endif
#endif
/////////////////////////////////////////////////////////////////////
STATIC_AL uint8 arCF_Frame[CF_MAX_FRAME_SIZE]; // frame buffer
STATIC_AL uint8 uCF_SN; // frame sequence number
STATIC_AL uint16 uCF_DL; // complete data length
STATIC_AL uint16 uCF_Size; // actual data length
STATIC_AL uint8 uCF_STmin; // own STmin parameter, send to peer
STATIC_AL uint8 uCF_BS; // own BS parameter, send to peer
STATIC_AL uint8 uCF_BScnt; // own BS counter, internal
STATIC_AL uint8 uFC_STmin; // STmin parameter, received by FC frame
STATIC_AL uint8 uFC_FS; // FS parameter, received by FC frame
#if (((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CAN) == CFG_ISO15765_COM_TYPE_CAN) || \
((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD))
STATIC_AL uint8 uFC_BS; // BS parameter, received by FC frame
#else
STATIC_AL boolean boCFNeeded = FALSE;
#endif
#ifndef PADDING_BYTE
#define PADDING_BYTE 0xFFU
#endif
#ifdef UNIT_TEST
boolean boUtRetVal = TRUE;
#endif
//////////////////////////////////////////////////////////////////////////
// timer functions
typedef struct
{
uint16 uID;
TIMER tTimer;
void (*fnc)(void);
} TTIMER;
STATIC_AL TTIMER arTimers[MAX_TIMERS];
#if (((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CAN) == CFG_ISO15765_COM_TYPE_CAN) || \
((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD))
STATIC_AL void ISO15765TimerTX_FC(void);
#endif
STATIC_AL void ISO15765TimerTX_CF(void);
STATIC_AL void ISO15765TimerRX_CF(void);
STATIC_AL boolean ISO15765TimerStart(uint16 ID, uint16 Period, void(*fnc)(void));
STATIC_AL boolean ISO15765TimerStop (uint8 ID);
STATIC_AL boolean LowerSend (uint8* data, uint16 length);
STATIC_AL boolean UpperSend (uint8* data, volatile uint16 length);
STATIC_AL void UpperError(uint8 error);
// timer IDs
#define TX_CF 1U
#define TX_FC 2U
#define RX_CF 3U
//////////////////////////////////////////////////////////////////////////
// protocol definitions
#define NPCI_SINGLE_FRAME 0x00U
#define NPCI_FIRST_FRAME 0x10U
#define NPCI_CONSECUTIVE_FRAME 0x20U
#define NPCI_FLOW_CONTROL 0x30U
#define NPCI_ERROR_FRAME 0x40U
// CAN-FD - maximum payload 64 bytes
#if ((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD)
#define BUFFER_SIZE 64U
#if defined(EXT_ADR)
// extended addressing
#define SF_DATALENGTH 61U
#define SF_DATALENGTH_SHORT 6U
#define FF_DATALENGTH 61U
#define CF_DATALENGTH 62U
#define FC_DATALENGTH 3U
#define EXT_STARTBYTE 1U
#define N_SA 0U
#else
// normal addressing
#define SF_DATALENGTH 62U
#define SF_DATALENGTH_SHORT 7U
#define FF_DATALENGTH 62U
#define CF_DATALENGTH 63U
#define FC_DATALENGTH 3U
#define EXT_STARTBYTE 0U
#endif
// CAN - maximum payload 8 bytes
#else
#define BUFFER_SIZE 8U
#if defined(EXT_ADR)
// extended addressing
#define SF_DATALENGTH 6U
#define FF_DATALENGTH 5U
#define CF_DATALENGTH 6U
#define FC_DATALENGTH 3U
#define EXT_STARTBYTE 1U
#define N_SA 0U
#else
// normal addressing
#define SF_DATALENGTH 7U
#define FF_DATALENGTH 6U
#define CF_DATALENGTH 7U
#define FC_DATALENGTH 3U
#define EXT_STARTBYTE 0U
#endif
#endif
// timing
#define N_As 1000U
#define N_Ar 1000U
#define N_Bs 1000U
#define N_Cr 1000U
//-----------------------------------------------------------------------------
/// \brief ISO15765Init
///
/// \descr
///
/// \param -
///
/// \return void
//-----------------------------------------------------------------------------
void ISO15765Init(void)
{
uCF_DL = 0;
uCF_STmin = STmin;
uCF_BS = BS;
// init timer
(void)memset(arTimers, 0, sizeof(TTIMER) * MAX_TIMERS);
}
//-----------------------------------------------------------------------------
/// \brief ISO15765Send
///
/// \descr
///
/// \param -
///
/// \return boolean
//-----------------------------------------------------------------------------
// transmit data to lower layer
boolean ISO15765Send(uint8* data, uint16 length)
{
boolean boRet;
#if ((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_LIN) == CFG_ISO15765_COM_TYPE_LIN)
boCFNeeded = FALSE;
#endif
if (length > 4095U)
{ // TP protocol can handle max 4095 bytes
// data size too big
boRet = FALSE;
}
else if (length <= SF_DATALENGTH)
{
// send SF
#if ((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD)
arCF_Frame[0] = NPCI_SINGLE_FRAME;
arCF_Frame[1] = (uint8)length & 0xFFU;
(void)memcpy(&arCF_Frame[2], data, length);
boRet = LOWER_TRANSMIT(arCF_Frame, length + 2);
#else
arCF_Frame[0] = (NPCI_SINGLE_FRAME | ((uint8)length & 0x0FU));
(void)memcpy(&arCF_Frame[1], data, length);
boRet = LOWER_TRANSMIT(arCF_Frame, length + 1U);
#endif
}
else
{
// send FF
uint8 buf[CF_DATALENGTH + 1U];
buf[0] = (NPCI_FIRST_FRAME | ((uint8)(length >> 8U) & 0x0FU));
buf[1] = (uint8)length;
(void)memcpy(&buf[2], data, FF_DATALENGTH);
(void)memcpy(&arCF_Frame[0], data, length);
uCF_SN = 1U; // init sequence number
uCF_DL = FF_DATALENGTH; // FF data length
uCF_BScnt = 0U; // init block counter
uCF_Size = length; // init length
if ((LOWER_TRANSMIT(buf, FF_DATALENGTH + 2U)) == TRUE)
{
// sending to lower layer was successful
// start timer for FC reception check
#if (((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CAN) == CFG_ISO15765_COM_TYPE_CAN) || \
((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD))
(void)ISO15765TimerStart(TX_FC, N_Bs, ISO15765TimerTX_FC);
#else
boCFNeeded = TRUE;
#endif
boRet = TRUE;
}
#ifndef UNIT_TEST
else
{
// FF could not be send
uCF_DL = 0;
boRet = FALSE;
}
#endif // !UNIT_TEST
}
return boRet;
}
//-----------------------------------------------------------------------------
/// \brief ISO15765SendCF
///
/// \descr
///
/// \param -
///
/// \return boolean
//-----------------------------------------------------------------------------
STATIC_AL boolean ISO15765SendCF(void)
{
boolean boRet = FALSE;
uint8 buf[CF_DATALENGTH + 1U];
#if ((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_LIN) == CFG_ISO15765_COM_TYPE_LIN)
boCFNeeded= FALSE;
#endif
buf[0] = (NPCI_CONSECUTIVE_FRAME | (uCF_SN++ & 0x0FU));
(void)memcpy(&buf[1], &arCF_Frame[uCF_DL], CF_DATALENGTH);
const uint16 unTransmitSize =
((uint16)(uCF_Size - uCF_DL) >= (uint16)CF_DATALENGTH)
? (uint16)(CF_DATALENGTH + 1U)
: (uint16)((uint32)((uint32)uCF_Size + 1U) - (uint32)uCF_DL);
if ((LOWER_TRANSMIT(buf, unTransmitSize)) == TRUE)
{
// sending to lower layer was successful
uCF_DL += CF_DATALENGTH;
// check if frame is complete
if (uCF_DL >= uCF_Size)
{
// frame completely sent
uCF_DL = 0;
}
else
{
#if (((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CAN) == CFG_ISO15765_COM_TYPE_CAN) || \
((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD))
// check BS
if ((uCF_BScnt++ >= uFC_BS) && (uFC_BS != 0U))
{
// block completely sent - wait for FC from receiver
// trigger timer for next FC reception
(void)ISO15765TimerStart(TX_FC, N_Bs, ISO15765TimerTX_FC);
}
else
{
// trigger timer for next CF frame
(void)ISO15765TimerStart(TX_CF, uFC_STmin, ISO15765TimerTX_CF);
}
#else
boCFNeeded = TRUE;
#endif
}
boRet = TRUE;
}
#ifndef UNIT_TEST
else
{
// transmission error on lower layer - abort
uCF_DL = 0;
// inform upper layer
UPPER_ERROR(ERROR_TX);
boRet = FALSE;
}
#endif // !UNIT_TEST
return boRet;
}
//-----------------------------------------------------------------------------
/// \brief ISO15765SendCFAbort
///
/// \descr
///
/// \param -
///
/// \return void
//-----------------------------------------------------------------------------
STATIC_AL void ISO15765SendCFAbort(void)
{
uCF_DL = 0;
// inform upper layer
UPPER_ERROR(ERROR_TX);
}
//-----------------------------------------------------------------------------
/// \brief ISO15765SendFC
///
/// \descr
///
/// \param -
///
/// \return boolean
//-----------------------------------------------------------------------------
STATIC_AL boolean ISO15765SendFC(uint8 FS)
{
uint8 data[3];
data[0] = (NPCI_FLOW_CONTROL | (FS & 0x0FU));
data[1] = uCF_BS;
data[2] = uCF_STmin;
return LOWER_TRANSMIT(data, 3);
}
//-----------------------------------------------------------------------------
/// \brief ISO15765Receive
///
/// \descr
///
/// \param -
///
/// \return void
//-----------------------------------------------------------------------------
// receive function for data from lower layer
void ISO15765Receive(uint8* data, volatile uint16 length)
{
#if defined(EXT_ADR)
// use extended addressing
if (data[N_SA] != (uint8)EXT_ADR_SRC)
{
// ignore invalid source address
return;
}
#endif
// check the NPCI type
switch(data[EXT_STARTBYTE] & 0xF0U)
{
case NPCI_SINGLE_FRAME :
{
// single frame received - just check length and pass to upper layer
uint8 SF_DL = data[EXT_STARTBYTE] & 0x0FU;
uCF_DL = 0;
#if ((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD)
if (SF_DL != 0u)
{
// CANFD_DL<=8
if ((SF_DL > SF_DATALENGTH_SHORT) || (length <= SF_DL))
{
// error - frame length wrong, discard frame
}
else
{
// frame is okay
(void)UPPER_TRANSMIT(&data[EXT_STARTBYTE + 1], SF_DL); // strip NPCI
}
}
else
{
// CANFD_DL > 8
uint8 SF_DL_FD = data[2] & 0xFFU;
if ((SF_DL_FD > SF_DATALENGTH) || (length <= SF_DL_FD))
{
// error - frame length wrong, discard frame
}
else
{
// frame is okay
(void)UPPER_TRANSMIT(&data[EXT_STARTBYTE + 2], SF_DL_FD); // strip NPCI
}
}
#else
// PRQA S 3415 1 // operation performed correctly
if ((SF_DL > SF_DATALENGTH) || (length <= SF_DL))
{
// error - frame length wrong, discard frame
}
else
{
// frame is okay
(void)UPPER_TRANSMIT(&data[EXT_STARTBYTE + 1U], SF_DL); // strip NPCI
}
#endif
break;
}
case NPCI_FIRST_FRAME :
{
// first frame received
uCF_DL = (uint16)(((uint16)data[EXT_STARTBYTE] & 0x0FU) << 8U) + (uint16)(data[EXT_STARTBYTE + 1U]);
if ((uCF_DL < (SF_DATALENGTH + 1U))) {
// error - frame length too small, discard frame
uCF_DL = 0;
break;
}
// frame is okay - copy to buffer
(void)memcpy(arCF_Frame, &data[EXT_STARTBYTE + 2U], FF_DATALENGTH); // strip NPCI
uCF_Size = FF_DATALENGTH; // init size
uCF_SN = 1; // init SN (next expected seq number)
uCF_BScnt = 0; // init block counter
// send FC
(void)ISO15765SendFC(0U);
// trigger timeout for next CF frame reception
(void)ISO15765TimerStart(RX_CF, N_Cr, ISO15765TimerRX_CF);
break;
}
case NPCI_CONSECUTIVE_FRAME :
{
// consecutive frame received
uint8 SN;
// kill timer
(void)ISO15765TimerStop(RX_CF);
if (uCF_DL == 0U)
{
// no CF expected
break;
}
// check sequence number
SN = data[EXT_STARTBYTE] & 0x0FU;
#ifdef WORKAROUND_SAME_CAN_TWICE
if (SN != uCF_SN) {
if ((SN == uCF_SN - 1)
|| (SN == 0xF) && (uCF_SN == 0x0)){
//ignore that case to prevent hangs
break;
}
else {
// error - wrong sequence number, discard frame and cancel reception
uCF_DL = 0U;
UPPER_ERROR(ERROR_RX);
break;
}
}
else {
// generate next SN
uCF_SN = ((uCF_SN+1U) & 0x0FU);
}
#else
if (SN != uCF_SN)
{
// error - wrong sequence number, discard frame and cancel reception
uCF_DL = 0U;
UPPER_ERROR(ERROR_RX);
break;
}
else
{
// generate next SN
uCF_SN = ((uCF_SN+1U) & 0x0FU); //++uCF_SN & 0x0FU;
}
#endif
// frame is okay
// check buffer space
if (uCF_Size + length < CF_MAX_FRAME_SIZE)
{
// append new data to buffer
(void)memcpy(&arCF_Frame[uCF_Size], &data[EXT_STARTBYTE + 1U], length < CF_DATALENGTH ? length : CF_DATALENGTH); // strip NPCI
uCF_Size += (length < CF_DATALENGTH ? length : CF_DATALENGTH);
}
else
{
// buffer overflow - the CF is accepted, but silently discarded but the upper layer should get informed
UPPER_ERROR(ERROR_OVERFLOW);
}
// frame done?
if (uCF_Size >= uCF_DL)
{
// frame complete - send frame to upper layer
(void)UPPER_TRANSMIT(arCF_Frame, uCF_DL);
uCF_DL = 0;
}
else
{
if (uFC_BS != 0U)
{
if (++uCF_BScnt >= uCF_BS)
{
// complete block received, send FC
uCF_BScnt = 0;
(void)ISO15765SendFC(0U);
}
}
// restart timer
(void)ISO15765TimerStart(RX_CF, N_Cr, ISO15765TimerRX_CF);
}
break;
}
case NPCI_FLOW_CONTROL :
{
// flow control frame received
// kill surveillance timer
(void)ISO15765TimerStop(TX_FC);
// FC frame is too short || FS format error - abort
if ((length < FC_DATALENGTH) || ((data[EXT_STARTBYTE + 0U] & 0x0FU) > 1U))
{
break;
}
// frame is okay - store values
#if defined (UNIT_TEST)
uFC_FS = data[EXT_STARTBYTE + 1U] & 0x01U; // 0 = CTS (ContinueToSend), 1 = WT (Wait)
#else
uFC_FS = data[EXT_STARTBYTE + 0U] & 0x01U; // 0 = CTS (ContinueToSend), 1 = WT (Wait)
#endif // UNIT_TEST
#if (((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CAN) == CFG_ISO15765_COM_TYPE_CAN) || \
((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD))
uFC_BS = data[EXT_STARTBYTE + 1U];
#endif
uFC_STmin = data[EXT_STARTBYTE + 2U];
uCF_BScnt = 0U; // reset block counter
if (uFC_FS == 0U)
{
// CTS set - send next consecutive frame
(void)ISO15765TimerStart(TX_CF, uFC_STmin, ISO15765TimerTX_CF);
}
break;
}
default :
// unknown N_PCI type
break;
}
// PRQA S 5330 3 // Program architecture and readability
// PRQA S 5310 2 // Program architecture and readability
// PRQA S 5316 1 // Program architecture and readability
}
#if ((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_LIN) == CFG_ISO15765_COM_TYPE_LIN)
//-----------------------------------------------------------------------------
/// \brief ISO15765_PrepareConsecutiveFrame
///
/// \descr
///
/// \param -
///
/// \return boolean
//-----------------------------------------------------------------------------
boolean ISO15765_PrepareConsecutiveFrame(void)
{
boolean boRes;
if (boCFNeeded == TRUE)
{
boRes = TRUE;
(void) ISO15765SendCF();
}
else
{
boRes = FALSE;
}
return boRes;
}
#endif
//-----------------------------------------------------------------------------
/// \brief ISO15765TimerTX_CF
///
/// \descr
///
/// \param -
///
/// \return void
//-----------------------------------------------------------------------------
STATIC_AL void ISO15765TimerTX_CF(void)
{
// STmin expired, send next consecutive frame
(void) ISO15765SendCF();
}
#if (((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CAN) == CFG_ISO15765_COM_TYPE_CAN) || \
((ISO15765_COM_TYPE & CFG_ISO15765_COM_TYPE_CANFD) == CFG_ISO15765_COM_TYPE_CANFD))
//-----------------------------------------------------------------------------
/// \brief ISO15765TimerTX_FC
///
/// \descr
///
/// \param -
///
/// \return void
//-----------------------------------------------------------------------------
STATIC_AL void ISO15765TimerTX_FC(void)
{
// waiting for FC frame expired, this is an error condition
// the upper layer needs to be informed that the receiver didn't answer
UPPER_ERROR(ERROR_TX);
ISO15765SendCFAbort();
}
#endif
//-----------------------------------------------------------------------------
/// \brief ISO15765TimerRX_CF
///
/// \descr
///
/// \param -
///
/// \return void
//-----------------------------------------------------------------------------
STATIC_AL void ISO15765TimerRX_CF(void)
{
// waiting for next CF frame from sender expired, this is an error condition
// the upper layer needs to be informed that the sender has a timeout
UPPER_ERROR(ERROR_RX);
ISO15765SendCFAbort();
}
///////////////////////////////////////////////////////////////////////////////
//
// T I M E R S E C T I O N
//
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
/// \brief ISO15765TimerStart
///
/// \descr
///
/// \param -
///
/// \return boolean
//-----------------------------------------------------------------------------
STATIC_AL boolean ISO15765TimerStart(uint16 ID, uint16 Period, void(*fnc)(void))
{
// check if timer is already running
boolean boRet = FALSE;
uint8 i;
for (i = 0; i < MAX_TIMERS; i++)
{
if (arTimers[i].uID == ID)
{
// yes, timer is running - restart
arTimers[i].tTimer = TimerStart(UTILTIME_MSEC(Period));
boRet = TRUE;
break;
}
}
if(boRet == FALSE) // timer not created yet - find next free slot
{
for (i = 0; i < MAX_TIMERS; i++)
{
if (arTimers[i].uID == 0U)
{
// found empty slot
arTimers[i].tTimer = TimerStart(UTILTIME_MSEC(Period));
arTimers[i].fnc = fnc;
arTimers[i].uID = ID; // set ID last to ensure that all other params are valid
boRet = TRUE;
break;
}
}
}
// if no empty slot found return FALSE
return boRet;
}
//-----------------------------------------------------------------------------
/// \brief ISO15765TimerStop
///
/// \descr
///
/// \param -
///
/// \return boolean
//-----------------------------------------------------------------------------
STATIC_AL boolean ISO15765TimerStop(uint8 ID)
{
boolean boRet = FALSE;
uint8 i;
for (i = 0; i < MAX_TIMERS; i++)
{
if (arTimers[i].uID == ID)
{
// remove timer
arTimers[i].uID = 0;
boRet = TRUE;
break;
}
}
// return FALSE if ID not found
return boRet;
}
//-----------------------------------------------------------------------------
/// \brief ISO15765TimerService
///
/// \descr
///
/// \param -
///
/// \return void
//-----------------------------------------------------------------------------
// this must be called every ms
void ISO15765TimerService(void)
{
// check Timers and trigger according callback
uint8 i;
for (i = 0; i < MAX_TIMERS; i++)
{
if (arTimers[i].uID != 0U)
{
if((TimerTimeout(arTimers[i].tTimer)) == TRUE) {
// timer is elapsed - execute callback
arTimers[i].uID = 0; // kill timer before function call - may be restarted in fnc
arTimers[i].fnc();
}
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// WRAPPER
//
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
/// \brief LowerSend
///
/// \descr
///
/// \param -
///
/// \return boolean
//-----------------------------------------------------------------------------
STATIC_AL boolean LowerSend(uint8* data, uint16 length)
{
uint8 buf[BUFFER_SIZE] = { 0 };
#ifdef PADDING
// clear buffer
// padding is useless here
//(void)memset(buf, (int)PADDING_BYTE, BUFFER_SIZE);
#endif
#if defined(EXT_ADR)
// use extended addressing
buf[0] = EXT_ADR_TRG;
(void)memcpy(&buf[1], data, length);
length++;
#else
// normal addressing
(void)memcpy(buf, data, length);
#endif
SEND_OVER_COMMUNICATION_BUS(buf, length);
#ifdef UNIT_TEST
return boUtRetVal;
#else
return TRUE;
#endif
}
//-----------------------------------------------------------------------------
/// \brief UpperSend
///
/// \descr
///
/// \param -
///
/// \return boolean
//-----------------------------------------------------------------------------
STATIC_AL boolean UpperSend(uint8* data, volatile uint16 length)
{
// get buffer
PduInfoType* PduInfoPtr;
(void)ComBuf_RxProvide(ISO15765_USED_COMBUF_ID, &PduInfoPtr);
if (PduInfoPtr->SduLength >= length)
{
(void)memcpy(PduInfoPtr->SduDataPtr, data, length);
PduInfoPtr->SduLength = length;
}
ComBuf_RxIndication(ISO15765_USED_COMBUF_ID, NTFRSLT_OK);
return TRUE;
}
//-----------------------------------------------------------------------------
/// \brief UpperError
///
/// \descr
///
/// \param -
///
/// \return void
//-----------------------------------------------------------------------------
STATIC_AL void UpperError(uint8 error)
{
// PRQA S 3112 1 // parameter not used at the moment
(void) error; // not used
ComBuf_RxIndication(ISO15765_USED_COMBUF_ID, NTFRSLT_E_NOT_OK);
}