📄 jbuffer.c
字号:
switch(buffselect)
{
case RX_BUFF:
for(loop=0; loop<stPGNBuffer.RxElms; loop++) /* for all elements in the buffer */
{
if((stPGNBuffer.RxPGN[loop].Used)
&& pg->mPDUF == stPGNBuffer.RxPGN[loop].ptPGN->mPDUF
&& pg->mPDUS == stPGNBuffer.RxPGN[loop].ptPGN->mPDUS
&& pg->mSource == stPGNBuffer.RxPGN[loop].ptPGN->mSource)
{
stPGNBuffer.RxPGN[loop].ptPGN = NULL; /* release the indexed PG */
stPGNBuffer.RxPGN[loop].Used = 0;
/* order the list to prevent spaces */
for(loop2=loop; loop2<stPGNBuffer.RxElms-1 && stPGNBuffer.RxElms>1;loop2++)
{
stPGNBuffer.RxPGN[loop2].ptPGN = stPGNBuffer.RxPGN[loop2+1].ptPGN;
stPGNBuffer.RxPGN[loop2].Used = stPGNBuffer.RxPGN[loop2+1].Used;
stPGNBuffer.RxPGN[loop2].Overrun = stPGNBuffer.RxPGN[loop2+1].Overrun;
stPGNBuffer.RxPGN[loop2].Requested = stPGNBuffer.RxPGN[loop2+1].Requested;
} /* for */
if(loop2>loop) /* clear last element */
{
stPGNBuffer.RxPGN[loop2].ptPGN = NULL;
stPGNBuffer.RxPGN[loop2].Used = 0;
stPGNBuffer.RxPGN[loop2].Overrun = 0;
stPGNBuffer.RxPGN[loop2].Requested = 0;
}
stPGNBuffer.RxElms--;
return stPGNBuffer.RxElms;
} /* if */
} /* for */
break;
default:
/* do nothing */
break;
} /* switch */
} /* if */
#endif /* USE_HASHTABLE */
return INVAL_BUFFER;
} /* gCB_ReleaseBuffer() */
/*!
\brief occupy a free buffer and return the buffer handler
This function is called from the protocol stack to allocate an
Rx or a Tx PGN in the buffer. Only registrered PGN in the buffer will
executed
*/
/*!
Allocate a PGN into the buffer
\param pg is the PG to store into the Buffer
\param buff is the select flag in which buffer the PG shall be stored RX|TX
\return a handler to the buffer
\retval 0...MAX_{RX|TX}_BUFF the PGN was allocated
\retval 0xFF buffer full, no registration
*/
unsigned char gCB_AllocBuffer(VJ1939PGN* pg, unsigned char buffselect)
{
#if (USE_HASHTABLE == 1)
unsigned short PDUindex;
unsigned short traverser;
/* we don't register System PG's */
if(!IsSysPG(pg))
{
/* in which buffer shall the PG register */
switch(buffselect)
{
case RX_BUFF:
if(stPGNBuffer.RxElms<MAX_RX_ELMS) /* is the free space in table? */
{
PDUindex = ((((unsigned short)pg->mPDUF)<<8) | pg->mPDUS); /* generate the Table index */
PDUindex %= RX_MODULATOR;
if(stPGNBuffer.PDURxIndex[PDUindex] == INVAL_RX_INX/*INVAL_INX*/) /* is elm the first element */
{
stPGNBuffer.PDURxIndex[PDUindex] = stPGNBuffer.mPDURxFree; /* get the next free element */
/* set PGN into table */
stPGNBuffer.mPDURxTable[stPGNBuffer.PDURxIndex[PDUindex]].mElement = (unsigned short)((((unsigned short)pg->mPDUF)<<8) | pg->mPDUS);
stPGNBuffer.mPDURxTable[stPGNBuffer.PDURxIndex[PDUindex]].mIndex = (VJ1939PGN*) pg;
/* set pointers of the new element */
stPGNBuffer.mPDURxFree = stPGNBuffer.mPDURxTable[stPGNBuffer.PDURxIndex[PDUindex]].mNext;
stPGNBuffer.mPDURxTable[stPGNBuffer.PDURxIndex[PDUindex]].mNext = INVAL_RX_INX/*INVAL_INX*/;
}
else
{
traverser = stPGNBuffer.PDURxIndex[PDUindex];
while(stPGNBuffer.mPDURxTable[traverser].mNext != INVAL_RX_INX/*INVAL_INX*/)
{
traverser = stPGNBuffer.mPDURxTable[traverser].mNext; /* search for the last element */
} /* while */
/* set free pointer ans set PGN to table */
stPGNBuffer.mPDURxTable[traverser].mNext = stPGNBuffer.mPDURxFree;
stPGNBuffer.mPDURxTable[stPGNBuffer.mPDURxTable[traverser].mNext].mElement = (unsigned short)((((unsigned short)pg->mPDUF)<<8) | pg->mPDUS);
stPGNBuffer.mPDURxTable[stPGNBuffer.mPDURxTable[traverser].mNext].mIndex = (VJ1939PGN*) pg;
/* set pointer of the new element */
stPGNBuffer.mPDURxFree = stPGNBuffer.mPDURxTable[stPGNBuffer.mPDURxFree].mNext;
stPGNBuffer.mPDURxTable[stPGNBuffer.mPDURxTable[traverser].mNext].mNext = INVAL_RX_INX/*INVAL_INX*/;
} /* else */
stPGNBuffer.RxElms++; /* increment element counter */
return stPGNBuffer.RxElms;
} /* if */
break;
default:
/* do nothing */
break;
}/* switch */
}
#else
if(!IsSysPG(pg))
{
switch(buffselect) /* select a buffer */
{
case RX_BUFF:
/* if the buffer ist free */
if(!stPGNBuffer.RxPGN[stPGNBuffer.RxElms].Used && stPGNBuffer.RxElms < MAX_RX_ELMS)
{
/* register the element */
stPGNBuffer.RxPGN[stPGNBuffer.RxElms].ptPGN = pg;
stPGNBuffer.RxPGN[stPGNBuffer.RxElms].Requested = 0;
stPGNBuffer.RxPGN[stPGNBuffer.RxElms].Used = 1;
stPGNBuffer.RxElms++;
return (stPGNBuffer.RxElms);
}
break;
default:
/* do nothing */
break;
}/* switch */
} /* if */
#endif /* USE_HASHTABLE */
return INVAL_BUFFER; /* return a default value */
}/* gCB_AllocBuffer() */
/*!
\brief Reset the buffer structure
This function must be called on each startup routine
*/
void gCB_Init(void)
{
unsigned short loop;
unsigned char i;
stPGNBuffer.RxElms = 0;
stPGNBuffer.mCurrRxPG = INVAL_INDEX/*INVAL_INX*/;
/* resetting the queue pointers */
stPGNBuffer.mRxQueueReadPtr = 0;
stPGNBuffer.mRxQueueWritePtr = 0;
/* reseting the RX Sys PGN Queue */
for(loop=0; loop<MAX_RX_QUEUESIZE; loop++)
{
stPGNBuffer.RxSysPGNQueue[loop].mPGN.mEnable = 0;
stPGNBuffer.RxSysPGNQueue[loop].mPGN.mPGState = PG_RX_FREE;
stPGNBuffer.RxSysPGNQueue[loop].mPGN.mDataLength = 0;
stPGNBuffer.RxSysPGNQueue[loop].Used = 0;
stPGNBuffer.RxSysPGNQueue[loop].Overrun = 0;
for(i=0; i<8; i++)
{
stPGNBuffer.RxSysPGNQueue[loop].mPGNData[i] = 0;
}
stPGNBuffer.RxSysPGNQueue[loop].mPGN.mData = /* QUEUE PGN shall point to a data field */
(unsigned char*)stPGNBuffer.RxSysPGNQueue[loop].mPGNData;
}/* for */
#if (USE_HASHTABLE == 1)
stPGNBuffer.mPDURxFree = 0;
stPGNBuffer.mPDUTxFree = 0;
/* reseting the TX Sys PGN structure */
stPGNBuffer.TxPGN.Overrun = 0;
stPGNBuffer.TxPGN.ptPGN = NULL;
stPGNBuffer.TxPGN.Requested = 0;
stPGNBuffer.TxPGN.Used = 0;
/* resetting the RX PGN buffer */
for(loop=0; loop<MAX_RX_ELMS; loop++)
{
stPGNBuffer.PDURxIndex[loop] = INVAL_RX_INX/*INVAL_INX*/;
stPGNBuffer.mPDURxTable[loop].mElement = 0xFFFF;
stPGNBuffer.mPDURxTable[loop].mIndex = NULL;
if(loop == (MAX_RX_ELMS-1))
stPGNBuffer.mPDURxTable[loop].mNext = 0;
else
stPGNBuffer.mPDURxTable[loop].mNext = loop+1;
}/* for */
#else
stPGNBuffer.PGType = INVAL_BUFFER;
stPGNBuffer.reqPGN = INVAL_INDEX;
/* resetting the tx sys pgn structure */
stPGNBuffer.TxPGNBuff.Overrun = 0;
stPGNBuffer.TxPGNBuff.ptPGN = NULL;
stPGNBuffer.TxPGNBuff.Requested = 0;
stPGNBuffer.TxPGNBuff.Used = 0;
/* resetting the Rx buffer */
for(loop=0; loop<MAX_RX_ELMS; loop++)
{
stPGNBuffer.RxPGN[loop].Overrun = 0;
stPGNBuffer.RxPGN[loop].ptPGN = NULL;
stPGNBuffer.RxPGN[loop].Requested = 0;
stPGNBuffer.RxPGN[loop].Used = 0;
} /* for */
#endif /* USE_HASTABLE */
} /* gCB_Init */
void gCB_ClearIdFilter(BYTE bManager)
{
/* TBD */
} /* gCB_ClearIdFilter */
/*!
\brief Quick extended identifier checking.
Check if an identifier has an assigned manager.
\param wId any CAN identifier
\retval TRUE - manager exist
\retval FALSE - manager does not exist
*/
BYTE gCB_PreCheckXtdId(DWORD wId)
{
unsigned short tblIndex;
if((((wId&0x00FF0000)>>16)==0xEE)||(((wId&0x00FF0000)>>16)==0xEA)||(((wId&0x00FF0000)>>16)==0xEC)
||(((wId&0x00FF0000)>>16)==0xEB)||(((wId&0x00FF0000)>>16)==0xE8))
{
stPGNBuffer.PGType = RX_SYS_BUFF;
return 1;
}
tblIndex = lCB_LookUp(wId,RX_BUFF); /* look if PG is registrated in table */
if((tblIndex != INVAL_INDEX/*INVAL_INX*/) && (stPGNBuffer.mCurrRxPG == INVAL_INDEX/*INVAL_INX*/))
{
stPGNBuffer.PGType = RX_BUFF;
stPGNBuffer.mCurrRxPG = tblIndex;
return TRUE;
}
return FALSE;
} /* gCB_PreCheckXtdId */
/*!
\brief Quick standard identifier checking.
Check if an identifier has an assigned manager.
\param wId any CAN identifier
\retval TRUE - manager exist
\retval FALSE - manager does not exist
*/
BYTE gCB_PreCheckStdId(WORD wId)
{
return 0; /* TBD in next Version we don't use standard CAN frames at J1939 yet*/
} /* gCB_PreCheckStdId */
/*!
If a message was received correctly, it will be put into a related
buffer or queue.
This function will be called from the CAN interrupt service routine.
\param ptMsg - Pointer to message (is invalid after routine execution).
\retval TRUE - message could be written to buffer.
\retval FALSE - message not buffered.
*/
BYTE gCB_CanBufferMsg(const CAN_MSG *ptMsg)
{
/* system PG shall be buffered in a Queue */
if(stPGNBuffer.PGType == RX_SYS_BUFF)
{
/* Queue Handling !! */
stPGNBuffer.mCurrRxPG = INVAL_INDEX/*INVAL_INX*/;
stPGNBuffer.PGType = INVAL_BUFFER;
if(gCB_EnqueueElm(ptMsg))
return 1;
}
else if(stPGNBuffer.PGType == RX_BUFF)
{
# if (USE_HASHTABLE == 1)
/* check the reception of a PG */
if(stPGNBuffer.mCurrRxPG != INVAL_INDEX
&& ((VJ1939PGN*)stPGNBuffer.mPDURxTable[stPGNBuffer.mCurrRxPG].mIndex)->mPGState != PG_RX_FULL)
{
/* sign the stack the receiption of a PG */
((VJ1939PGN*)stPGNBuffer.mPDURxTable[stPGNBuffer.mCurrRxPG].mIndex)->mPGState = PG_RX_FULL;
/* refresh the elements in goal buffer */
memcpy((char*)(((VJ1939PGN*)stPGNBuffer.mPDURxTable[stPGNBuffer.mCurrRxPG].mIndex)->mData),
(char*)ptMsg->bDb,
ptMsg->Dlc);
/* clear handler */
stPGNBuffer.mCurrRxPG = INVAL_INDEX/*INVAL_INX*/;
stPGNBuffer.PGType = INVAL_BUFFER;
return 1;
} /* if */
# else
if(stPGNBuffer.mCurrRxPG != INVAL_INDEX
&& stPGNBuffer.RxPGN[stPGNBuffer.mCurrRxPG].ptPGN->mPGState != PG_RX_FULL)
{
/* sign the stack the receiption of a PG */
stPGNBuffer.RxPGN[stPGNBuffer.mCurrRxPG].ptPGN->mPGState = PG_RX_FULL;
/* refresh the elements in goal buffer */
memcpy((char*)stPGNBuffer.RxPGN[stPGNBuffer.mCurrRxPG].ptPGN->mData,
(char*)ptMsg->bDb,
ptMsg->Dlc);
/* clear handler */
stPGNBuffer.mCurrRxPG = INVAL_INDEX/*INVAL_INX*/;
stPGNBuffer.PGType = INVAL_BUFFER;
return 1;
}
# endif /* USE_HASHTABLE */
}
return 0;
}
/*--------------------------------------------------------------------*/
/* documentation */
/*--------------------------------------------------------------------*/
/*!
\file
\brief Basic routines to filter and store CAN messages
for the J1939 protocol stack.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -