📄 jbuffer.c
字号:
/*--------------------------------------------------------------------
jBUFFER.C
--------------------------------------------------------------------
Copyright (C) 2004 Vector Informatik GmbH, Stuttgart
Function: Basic routines to filter and store CAN messages
for the J1939 protocol stack.
--------------------------------------------------------------------
* Comments:
*
*
* Version Date Author Comments
* ------- ---------- -------------- ------------------------------
* 0.1 15.05.2001 Ma Create
* 0.2 28.01.2001 Ma changed PDUS handling in lookup
* table
* 0.3 22.05.2003 Ma minor changes - save RX buffer access
* 0.4 10.07.2003 Ma changed memory qualifier
* 1.0 24.06.2004 Ma removed TX lookup handling
* 1.1 28.06.2004 Ma changed comments and removed unused vars
*/
/*--------------------------------------------------------------------*/
/* include files */
/*--------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Includes.h"
#ifdef BENCHMARK
#ifdef _TSK_166
# include <reg167.h>
#endif /* _TSK_166_ */
#endif /* BENCHMARK */
#include "J1939.h"
#include "PortAB.h"
#include "Types.h"
#include "JCanCntrl.h"
#include "J1939PGN.h"
#include "JBuffer.h"
#include "J1939cfg.h"
/*--------------------------------------------------------------------*/
/* external data */
/*--------------------------------------------------------------------*/
/*! External dependencies */
extern VJ1939PGN gRxPGTable[NR_OF_RX_PG]; /*!< the PG RxTable */
extern unsigned char gDeviceAddress; /*!< the device address for special handling */
/*--------------------------------------------------------------------*/
/* private data */
/*--------------------------------------------------------------------*/
VJ1939PGNBuffer stPGNBuffer; /* PG buffer structure */
/* ########################## PERFORMANCE MEASSUREMENT ####################### */
/* ################################### BEGIN ################################## */
#if BENCHMARK == 1
#ifdef _TSK_166_
#define START_TIM 0x0040
void configBenchTimer(void)
{
T4CON = 0x0002;
T4 = 0x0000;
}
void startBenchTimer(void)
{
T4CON |= START_TIM;
}
void stopBenchTimer(void)
{
T4CON &= ~START_TIM;
}
void resetBenchTimer(void)
{
T4 = 0x0000;
}
#endif /* _TSK_166_ */
#endif /* BENCHMARK */
/* #################################### END ################################## */
/* ########################## PERFORMANCE MEASSUREMENT ###################### */
/*--------------------------------------------------------------------*/
/* private functions */
/*--------------------------------------------------------------------*/
/*!
\brief Look up for a PG in the Hash Table
This function is called from the buffer module to look up if a PG is
registrated in the hash table
*/
/*!
\param pg ptr to the PG for which we have to look up
\retval INVAL_INDEX if PG was not registrated
\retval A value >= 0 and < INVAL_INDEX if PG was registrated */
unsigned short lCB_LookUp(unsigned long id, unsigned char buffselect) REENTRANT
{
unsigned char lHoldPDUS;
unsigned char lPDUF = (id&0x00FF0000)>>16;
unsigned char lPDUS = (id&0x0000FF00)>>8;
unsigned char lSource = (id&0x000000FF);
unsigned char lAddress = J1939NULLADDRESS;
# if (USE_HASHTABLE == 1)
unsigned short traverser;
unsigned short PGindex = ((((unsigned short)lPDUF)<<8) | lPDUS); /* generate the index for hash table */;
#else
unsigned short loop;
#endif /* USE_HASHTABLE */
/* remember the PG's PDUS */
lHoldPDUS = lPDUS;
/* check the PDU format - it is neccessary for both methods */
if(lPDUF<240) /* slect the PDU format if it ist Format I */
{
lAddress = lPDUS; /* set PDUS to "0" and remember the destination address */
lPDUS = 0x00;
}
else
{
lAddress = J1939GLOBALADDRESS; /* if it is Format II, Address is the global address */
}
#if (USE_HASHTABLE == 1)
# if BENCHMARK == 1
configBenchTimer();
startBenchTimer();
#endif /* BENCHMARK */
switch(buffselect) /* in which buffer we have to look up */
{
/* the RX Buffer was selected */
case RX_BUFF:
PGindex %= RX_MODULATOR;
if((stPGNBuffer.PDURxIndex[PGindex] != INVAL_RX_INX/*INVAL_INX*/)
&& ((lAddress==J1939GLOBALADDRESS)||(lAddress==gDeviceAddress))) /* is a path into the table? */
{
traverser = stPGNBuffer.PDURxIndex[PGindex]; /* geth the traverser root */
/* walking through the path */
while(traverser != INVAL_RX_INX/*INVAL_INX*/)
{
/* check the PG's on this path */
if((lPDUF == (unsigned char)((stPGNBuffer.mPDURxTable[traverser].mElement&0xFF00)>>8))
&&(lHoldPDUS == (unsigned char) stPGNBuffer.mPDURxTable[traverser].mElement&0x00FF)
&& (((VJ1939PGN*)stPGNBuffer.mPDURxTable[traverser].mIndex)->mSource == lSource))
{
return traverser; /* bingo, we hit the PG */
} /* if */
traverser = stPGNBuffer.mPDURxTable[traverser].mNext; /* PG doesn't hit - continue the path */
} /* while */
} /* if */
break;
default:
/* do nothing */
break;
} /* switch */
return INVAL_INDEX /* INVAL_INX */;
# else
# if BENCHMARK == 1
configBenchTimer();
startBenchTimer();
# endif /* BENCHMARK */
switch(buffselect) /* in which buffer we have to look up */
{
case RX_BUFF:
for(loop=0; loop<stPGNBuffer.RxElms; loop++) /* loop for all list elements */
{
if((stPGNBuffer.RxPGN[loop].Used)
&& (stPGNBuffer.RxPGN[loop].ptPGN->mPDUF == lPDUF /* compare the PGN */
&& stPGNBuffer.RxPGN[loop].ptPGN->mPDUS == lHoldPDUS
&& stPGNBuffer.RxPGN[loop].ptPGN->mSource == lSource)
&& ((lAddress==J1939GLOBALADDRESS)||(lAddress==gDeviceAddress)))
{
return loop; /* return the index of the PG */
} /* if */
} /* for */
break;
default:
/* do nothing */
break;
} /* switch */
return INVAL_INDEX /*INVAL_INX*/;
#endif /* USE_HASHTABLE */
} /* lCB_LookUp */
/*!
\brief Generates a CAN Message from a PG
This function is called from the buffer module to generate a CAN Message
form a PG - no fragmentation is allowed. This function is used in L2
level. TP is one level higher in use!
*/
/*!
\param pg ptr to the PG from which an Message shall be generated
\param msg ptr to the message which shall be created
\return the result of the function
\retval 1 if message was generated
\retval 0 if a problem occurs */
unsigned char lCB_GenMessage(VJ1939PGN* pg, CAN_MSG *msg)
{
msg->qbId.dw = SetId(pg); /* generating the CAN identifier */
msg->Rtr = 0; /* inizializing the message params */
msg->Dlc = pg->mDataLength;
msg->Ext = 1;
msg->RxOk = 0;
msg->TxOk = 0;
if(memcpy((char*)msg->bDb,(char*)pg->mData,pg->mDataLength)) /* copy data */
return 0;
return 1;
} /* lCB_GenMessage */
/*!
\brief Generates a PGN from a CAN Message
This function is called from the buffer module to generate a PGN
form a CAN Message - no fragmentation is allowed. This function is used in L2
level. TP is one level higher in use!
*/
/*!
\param pg ptr to the PG which shall be created
\param msg ptr to the message from which pg should be created
\return the result of the function
\retval 0 if pg was generated
\retval 1 if there was a problem */
unsigned char lCB_GenPGN(VJ1939PGN* pg, const CAN_MSG* msg)
{
pg->mPGState = PG_RX_FULL;
pg->mEnable = 1;
pg->mDataLength = msg->Dlc;
pg->mPriority = GetPrio(msg); /*x !!!!!!!!!!!!!*/
pg->mPDUF = GetPDUF(msg);
pg->mPDUS = GetPDUS(msg);
pg->mSource = GetSource(msg);
if(memcpy((char*)pg->mData, (char*)msg->bDb,msg->Dlc))
return 0;
return 1;
} /* lCB_GenPGN */
/*--------------------------------------------------------------------*/
/* public functions */
/*--------------------------------------------------------------------*/
/*!
Checks if the current SYS PG was successful sent
\param -
\retval 1 if PG was successful sent
\retval 0 if PG could not sent
*/
unsigned char gCB_CheckSysPGSend(void)
{
# if (USE_HASHTABLE == 1)
if((stPGNBuffer.TxPGN.Requested == 0)
&& (stPGNBuffer.TxPGN.ptPGN == NULL)
&& (stPGNBuffer.TxPGN.Used == 0))
{
return 1;
}
# else
if((stPGNBuffer.TxPGNBuff.Requested == 0)
&& (stPGNBuffer.TxPGNBuff.Used == 0))
{
return 1;
}
#endif /* USE_HASHTABLE */
return 0;
}
/*!
\brief Dequeues a Message from the RX System PG Queue
This function is called from the buffer module to generate a PG from the
a Message.
*/
/*!
\param msg ptr to a message from which the PG has to be generated
\retval 1 if PG was generated an Enqueued
\retval 0 if PG could't genearted or Queue was full */
unsigned char gCB_DequeueElm(void)
{
/* if queue is not empty */
if(stPGNBuffer.mRxQueueReadPtr != stPGNBuffer.mRxQueueWritePtr)
{
switch(stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mPDUF)
{
case 0xEE: /* Address Claimed PGN */
gRxPGTable[RX_PGN_ADDRESS_CLAIMED].mPGState = PG_RX_FULL;
gRxPGTable[RX_PGN_ADDRESS_CLAIMED].mDataLength =
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mDataLength;
gRxPGTable[RX_PGN_ADDRESS_CLAIMED].mPDUF =
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mPDUF;
gRxPGTable[RX_PGN_ADDRESS_CLAIMED].mPDUS =
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mPDUS;
gRxPGTable[RX_PGN_ADDRESS_CLAIMED].mSource =
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mSource;
memcpy((char*)gRxPGTable[RX_PGN_ADDRESS_CLAIMED].mData,
(char*)stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mData,
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mDataLength);
break;
case 0xEA: /* Request PGN */
gRxPGTable[RX_PGN_REQ].mPGState = PG_RX_FULL;
gRxPGTable[RX_PGN_REQ].mDataLength =
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mDataLength;
gRxPGTable[RX_PGN_REQ].mPDUF =
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mPDUF;
gRxPGTable[RX_PGN_REQ].mPDUS =
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mPDUS;
gRxPGTable[RX_PGN_REQ].mSource =
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mSource;
memcpy((char*)gRxPGTable[RX_PGN_REQ].mData,
(char*)stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mData,
stPGNBuffer.RxSysPGNQueue[stPGNBuffer.mRxQueueReadPtr].mPGN.mDataLength);
break;
case 0xEC: /* TPCM PGN */
gRxPGTable[RX_PGN_TPCM].mPGState = PG_RX_FULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -