📄 can_buffer.c
字号:
/************************************************************************
*
* Freescale Semicondactor
* ALL RIGHTS RESERVED
* (c) Copyright 2004Freescale Semiconductor
*
*************************************************************************
*
* FILE NAME: can_buffer.c
*
* PURPOSE:
*
* AUTHOR(s): Igor Byeda
*
*************************************************************************/
#include "can_buffer.h"
/************************************************************************
* NAME: rb_Create
*
* DESCRIPTION: create and initialize RingBuffer object
*
* PARAMETER(s):
* [in] bufSizeWanted -- maximum size of the ring buffer [in packets]
*
* RETURN: Pointer to the new RingBuffer structure
************************************************************************/
rb_obj_t * rb_Create(uint32 bufSizeWanted)
{
rb_obj_t * rb = NULL;
// trying to create internal structure
rb = (rb_obj_t *) malloc(sizeof(rb_obj_t));
if( rb )
{
// trying to create buffer itself
rb->pBuf = (can_Message_t *) malloc( bufSizeWanted*CAN_MSG_LEN );
if( rb->pBuf )
{
rb->nBufSize = bufSizeWanted;
// init with zeros
rb->pRD = 0;
rb->pWR = 0;
rb->tmp = 0;
memset( rb->pBuf, 0x00, (rb->nBufSize*CAN_MSG_LEN) );
} else
// u-ups...
rb = NULL;
}
return (rb);
}
/************************************************************************
* NAME: rb_Destroy
*
* DESCRIPTION: Destroy Ring Buffer by freeing memory and resetting
* structure variables to zero state
*
* PARAMETER(s):
* [in/out] rb -- pointer to the RingBuffer object (structure)
*
* RETURN: --
************************************************************************/
void rb_Destroy(rb_obj_t * rb)
{
// killing buffer itself
if ( rb->pBuf ) free(rb->pBuf);
rb->pBuf = NULL;
rb->nBufSize = 0;
rb->pRD = 0;
rb->pWR = 0;
// and object structure at the end
if ( rb ) free(rb);
rb = NULL;
}
/************************************************************************
* NAME: rb_get_FreeSpace
*
* DESCRIPTION: Returns the amount of data [in units] available for
* WRiting in buffer
*
* PARAMETER(s):
* [in] rb -- pointer to the RingBuffer object (structure)
*
* RETURN: Amount of data [in units] available for WRiting
************************************************************************/
uint32 rb_get_FreeSpace(rb_obj_t * rb)
{
if( rb->pBuf )
{
if( rb->pRD == rb->pWR )
return (rb->nBufSize);
if( rb->pWR < rb->pRD )
return (rb->pRD - rb->pWR);
if( rb->pWR > rb->pRD )
return ((rb->nBufSize - rb->pWR) + rb->pRD);
}
return (0);
}
/************************************************************************
* NAME: rb_get_DataToReadSize
*
* DESCRIPTION: Returns the amount of data (in units) available for
* ReaDing from the buffer
*
* PARAMETER(s):
* [in] rb -- pointer to the RingBuffer object (structure)
*
* RETURN: Amount of data [in bytes] available for ReaDing
************************************************************************/
uint32 rb_get_DataToReadSize(rb_obj_t * rb)
{
if( rb->pBuf )
{
if( rb->pRD == rb->pWR )
return (0);
if( rb->pRD < rb->pWR )
return (rb->pWR - rb->pRD);
if( rb->pRD > rb->pWR )
return ((rb->nBufSize - rb->pRD) + rb->pWR);
}
return (0);
}
/************************************************************************
* NAME: rb_data_Write
*
* DESCRIPTION: write data into RingBuffer
*
* PARAMETER(s):
* [in] rb -- pointer to the RingBuffer object
* [in] pExtBuf -- Pointer to the external buffer to WR
* [in] nExtLen -- Size of the ext. data to WR [in units]
*
* RETURN: Amount of data were really written in
************************************************************************/
uint32 rb_data_Write(rb_obj_t * rb, can_Message_t * pExtBuf, uint32 nExtLen)
{
// real buffer size is (nBufSize-1) for safety reason ->
// sign '<' instead of '<='
if( nExtLen < rb_get_FreeSpace(rb) )
{
// easy case, no wrapping
if( rb->pWR + nExtLen < rb->nBufSize )
{
memcpy( &(rb->pBuf[rb->pWR]), pExtBuf, nExtLen*CAN_MSG_LEN );
rb->pWR += nExtLen;
}
// harder case we need to wrap around
else
{
rb->tmp = rb->nBufSize - rb->pWR; // First Part size
memcpy( &(rb->pBuf[rb->pWR]), pExtBuf, (rb->tmp)*CAN_MSG_LEN );
memcpy( &(rb->pBuf[0]), &(rb->pBuf[rb->tmp]), (nExtLen - rb->tmp)*CAN_MSG_LEN );
rb->pWR = (nExtLen - rb->tmp);
}
return (nExtLen);
}
return (0);
}
/************************************************************************
* NAME: rb_data_Read
*
* DESCRIPTION: read data from RingBuffer
*
* PARAMETER(s):
* [in] rb -- pointer to the RingBuffer object
* [in/out] pExtBuf -- Pointer to the external buffer to store data
* [in] nExtLen -- Size of the data to read out [in bytes]
*
* RETURN: Amount of data were really extracted
************************************************************************/
uint32 rb_data_Read(rb_obj_t * rb, can_Message_t * pExtBuf, uint32 nExtLen)
{
if( nExtLen <= rb_get_DataToReadSize(rb) )
{
// easy case, no wrapping
if( (rb->pRD + nExtLen) < rb->nBufSize )
{
memcpy( pExtBuf, &(rb->pBuf[rb->pRD]), nExtLen*CAN_MSG_LEN );
rb->pRD += nExtLen;
}
// harder case, buffer wraps around
else
{
rb->tmp = rb->nBufSize - rb->pRD; // First Part size
memcpy( pExtBuf, &(rb->pBuf[rb->pRD]), (rb->tmp)*CAN_MSG_LEN );
memcpy( &(pExtBuf[rb->tmp]), &(rb->pBuf[0]), (nExtLen - rb->tmp)*CAN_MSG_LEN );
rb->pRD = (nExtLen - rb->tmp);
}
return (nExtLen);
}
return (0);
}
/************************************************************************
* NAME: rb_data_WriteOneVirtual
*
* DESCRIPTION: get pointer to the ONE element to virtually write in
* (just fill structure fields). pWR will increase by 1.
* USE IT VERY CAREFULLY!!!
* This function was developed to use only in interrupts.
*
* PARAMETER(s):
* [in] rb -- pointer to the RingBuffer object
*
* RETURN: pointer to the array element to fill up
************************************************************************/
can_Message_t * rb_data_WriteOneVirtual(rb_obj_t * rb)
{
if( rb_get_FreeSpace(rb) > 1)
{
rb->tmp2 = rb->pWR;
// easy case, no wrapping
if( rb->pWR + 1 < rb->nBufSize )
{
rb->pWR += 1;
}
// case we need to wrap around
else
{
rb->pWR = 0;
}
return( &(rb->pBuf[ rb->tmp2 ]) );
}
return (NULL);
}
/************************************************************************
* NAME: rb_data_WriteOneBack
*
* DESCRIPTION: place pWR pointer one position back
* USE IT VERY, VERY CAREFULLY!!!
* This function was developed to use only in interrupts.
*
* PARAMETER(s):
* [in] rb -- pointer to the RingBuffer object
*
* RETURN: 1 - if ok, 0 - in any other case
************************************************************************/
uint32 rb_data_WriteOneBack(rb_obj_t * rb)
{
if( rb_get_FreeSpace(rb) < rb->nBufSize)
{
rb->tmp = rb->pWR;
// easy case, no wrapping
if( rb->tmp > 0 )
{
rb->tmp -= 1;
}
// case we need to wrap around
else
{
rb->tmp = rb->nBufSize - 1;
}
// simple checking for safety reason
if (rb->tmp != rb->tmp2) return (FALSE);
rb->pWR = rb->tmp;
return (TRUE);
}
return (FALSE);
}
/************************************************************************
* NAME: rb_data_ReadOneVirtual
*
* DESCRIPTION: get pointer to the ONE element to virtually read it
* (just read structure fields by pointer). pRD will increase by 1.
* USE IT VERY CAREFULLY!!!
* This function was developed to use only in interrupts.
*
* PARAMETER(s):
* [in] rb -- pointer to the RingBuffer object
*
* RETURN: pointer to the array element to read out
************************************************************************/
can_Message_t * rb_data_ReadOneVirtual(rb_obj_t * rb)
{
if( rb_get_DataToReadSize(rb) >= 1 )
{
rb->tmp = rb->pRD;
// easy case, no wrapping
if( rb->pRD + 1 < rb->nBufSize )
{
rb->pRD += 1;
}
// harder case, buffer wraps around
else
{
rb->pRD = 0;
}
return ( &(rb->pBuf[ rb->tmp ]) );
}
return (NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -