Add callback overrides for stream buffer and message buffers (#437)

* Let each stream/message can use its own sbSEND_COMPLETED

In FreeRTOS.h, set the default value of configUSE_SB_COMPLETED_CALLBACK
to zero, and add additional space for the function pointer when
the buffer created statically.

In stream_buffer.c, modify the macro of sbSEND_COMPLETED which let
the stream buffer to use its own implementation, and then add an
pointer to the stream buffer's structure, and modify the
implementation of the buffer creating and initializing

Co-authored-by: eddie9712 <qw1562435@gmail.com>
This commit is contained in:
Ravishankar Bhagavandas 2022-06-20 17:48:34 -07:00 committed by GitHub
parent 49cb8e8b28
commit 0b46492740
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 306 additions and 48 deletions

3
.github/lexicon.txt vendored
View File

@ -1693,10 +1693,12 @@ pxqueuesetcontainer
pxramstack
pxreadycoroutinelists
pxreadytaskslists
pxreceivecompletedcallback
pxregions
pxresult
pxrxedmessage
pxsemaphorebuffer
pxsendcompletedcallback
pxstack
pxstackbase
pxstackbuffer
@ -2796,6 +2798,7 @@ xinterruptcontroller
xinterruptdescriptortable
xisfeasable
xisfeasible
xisinsideisr
xismessagebuffer
xisprivileged
xitemvalue

View File

@ -13,6 +13,17 @@ Documentation and download available at https://www.FreeRTOS.org/
are both typedefs of the same struct xLIST_ITEM. This addresses some issues
observed when strict-aliasing and link time optimization are enabled.
To maintain backwards compatibility, configUSE_MINI_LIST_ITEM defaults to 1.
+ Add the ability to override send and receive completed callbacks for each
instance of a stream buffer or message buffer. The feature can be controlled
by setting the configuration option configUSE_SB_COMPLETED_CALLBACK in
FreeRTOSConfig.h. When the option is set to 1, APIs
xStreamBufferCreateWithCallback() or xStreamBufferCreateStaticWithCallback()
(and likewise APIs from message buffer) can be used to create a stream buffer
or message buffer instance with application provided callback overrides. When
the option is set to 0, then the default callbacks as defined by
sbSEND_COMPLETED() and sbRECEIVE_COMPLETED() macros are invoked. To maintain
backwards compatibility, configUSE_SB_COMPLETED_CALLBACK defaults to 0. The
functionaility is currently not supported for MPU enabled ports.
Changes between FreeRTOS V10.4.5 and FreeRTOS V10.4.6 released November 12 2021

View File

@ -890,6 +890,12 @@
#define configUSE_POSIX_ERRNO 0
#endif
#ifndef configUSE_SB_COMPLETED_CALLBACK
/* By default per-instance callbacks are not enabled for stream buffer or message buffer. */
#define configUSE_SB_COMPLETED_CALLBACK 0
#endif
#ifndef portTICK_TYPE_IS_ATOMIC
#define portTICK_TYPE_IS_ATOMIC 0
#endif
@ -1356,6 +1362,9 @@ typedef struct xSTATIC_STREAM_BUFFER
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy4;
#endif
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
void * pvDummy5[ 2 ];
#endif
} StaticStreamBuffer_t;
/* Message buffers are built on stream buffers. */

View File

@ -107,6 +107,18 @@ typedef void * MessageBufferHandle_t;
* 32-bit architecture, so on most 32-bit architectures a 10 byte message will
* take up 14 bytes of message buffer space.
*
* @param pxSendCompletedCallback Callback invoked when a send operation to the
* message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
* is called without the parameter, then it will use the default implementation
* provided by sbSEND_COMPLETED macro. To enable the callback,
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
*
* @param pxReceiveCompletedCallback Callback invoked when a receive operation from
* the message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
* is called without the parameter, it will use the default implementation provided
* by sbRECEIVE_COMPLETED macro. To enable the callback,
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
*
* @return If NULL is returned, then the message buffer cannot be created
* because there is insufficient heap memory available for FreeRTOS to allocate
* the message buffer data structures and storage area. A non-NULL value being
@ -143,7 +155,12 @@ typedef void * MessageBufferHandle_t;
* \ingroup MessageBufferManagement
*/
#define xMessageBufferCreate( xBufferSizeBytes ) \
( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE )
( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE, NULL, NULL )
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
#define xMessageBufferCreateWithCallback( xBufferSizeBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE, pxSendCompletedCallback, pxReceiveCompletedCallback )
#endif
/**
* message_buffer.h
@ -172,6 +189,16 @@ typedef void * MessageBufferHandle_t;
* StaticMessageBuffer_t, which will be used to hold the message buffer's data
* structure.
*
* @param pxSendCompletedCallback Callback invoked when a new message is sent to the message buffer.
* If the parameter is NULL or xMessageBufferCreate() is called without the parameter, then it will use the default
* implementation provided by sbSEND_COMPLETED macro. To enable the callback,
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
*
* @param pxReceiveCompletedCallback Callback invoked when a message is read from a
* message buffer. If the parameter is NULL or xMessageBufferCreate() is called without the parameter, it will
* use the default implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
*
* @return If the message buffer is created successfully then a handle to the
* created message buffer is returned. If either pucMessageBufferStorageArea or
* pxStaticmessageBuffer are NULL then NULL is returned.
@ -210,7 +237,12 @@ typedef void * MessageBufferHandle_t;
* \ingroup MessageBufferManagement
*/
#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \
( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer )
( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer, NULL, NULL )
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
#define xMessageBufferCreateStaticWithCallback( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback )
#endif
/**
* message_buffer.h

View File

@ -248,12 +248,16 @@ BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL;
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t xIsMessageBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) FREERTOS_SYSTEM_CALL;
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL;
StaticStreamBuffer_t * const pxStaticStreamBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) FREERTOS_SYSTEM_CALL;

View File

@ -71,6 +71,12 @@
struct StreamBufferDef_t;
typedef struct StreamBufferDef_t * StreamBufferHandle_t;
/**
* Type used as a stream buffer's optional callback.
*/
typedef void (* StreamBufferCallbackFunction_t)( StreamBufferHandle_t xStreamBuffer,
BaseType_t xIsInsideISR,
BaseType_t * const pxHigherPriorityTaskWoken );
/**
* stream_buffer.h
@ -103,6 +109,16 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
* trigger level of 1 being used. It is not valid to specify a trigger level
* that is greater than the buffer size.
*
* @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to
* trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default
* implementation provided by sbSEND_COMPLETED macro. To enable the callback,
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
*
* @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a
* stream buffer. If the parameter is NULL, it will use the default
* implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
*
* @return If NULL is returned, then the stream buffer cannot be created
* because there is insufficient heap memory available for FreeRTOS to allocate
* the stream buffer data structures and storage area. A non-NULL value being
@ -137,7 +153,14 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
* \defgroup xStreamBufferCreate xStreamBufferCreate
* \ingroup StreamBufferManagement
*/
#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE )
#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) \
xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, NULL, NULL )
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
#define xStreamBufferCreateWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pxSendCompletedCallback, pxReceiveCompletedCallback )
#endif
/**
* stream_buffer.h
@ -179,6 +202,16 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
* StaticStreamBuffer_t, which will be used to hold the stream buffer's data
* structure.
*
* @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to
* trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default
* implementation provided by sbSEND_COMPLETED macro. To enable the callback,
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
*
* @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a
* stream buffer. If the parameter is NULL, it will use the default
* implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
*
* @return If the stream buffer is created successfully then a handle to the
* created stream buffer is returned. If either pucStreamBufferStorageArea or
* pxStaticstreamBuffer are NULL then NULL is returned.
@ -218,8 +251,14 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
* \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic
* \ingroup StreamBufferManagement
*/
#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \
xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer )
xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer, NULL, NULL )
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
#define xStreamBufferCreateStaticWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback )
#endif
/**
* stream_buffer.h
@ -843,13 +882,18 @@ BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuf
/* Functions below here are not part of the public API. */
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION;
BaseType_t xIsMessageBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
StaticStreamBuffer_t * const pxStaticStreamBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;

View File

@ -1429,14 +1429,36 @@
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer ) /* FREERTOS_SYSTEM_CALL */
BaseType_t xIsMessageBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) /* FREERTOS_SYSTEM_CALL */
{
StreamBufferHandle_t xReturn;
BaseType_t xRunningPrivileged;
xPortRaisePrivilege( xRunningPrivileged );
xReturn = xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer );
vPortResetPrivilege( xRunningPrivileged );
/**
* Streambuffer application level callback functionality is disabled for MPU
* enabled ports.
*/
configASSERT( ( pxSendCompletedCallback == NULL ) &&
( pxReceiveCompletedCallback == NULL ) );
if( ( pxSendCompletedCallback == NULL ) &&
( pxReceiveCompletedCallback == NULL ) )
{
xPortRaisePrivilege( xRunningPrivileged );
xReturn = xStreamBufferGenericCreate( xBufferSizeBytes,
xTriggerLevelBytes,
xIsMessageBuffer,
NULL,
NULL );
vPortResetPrivilege( xRunningPrivileged );
}
else
{
traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer );
xReturn = NULL;
}
return xReturn;
}
@ -1448,14 +1470,38 @@
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) /* FREERTOS_SYSTEM_CALL */
StaticStreamBuffer_t * const pxStaticStreamBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) /* FREERTOS_SYSTEM_CALL */
{
StreamBufferHandle_t xReturn;
BaseType_t xRunningPrivileged;
xPortRaisePrivilege( xRunningPrivileged );
xReturn = xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pucStreamBufferStorageArea, pxStaticStreamBuffer );
vPortResetPrivilege( xRunningPrivileged );
/**
* Streambuffer application level callback functionality is disabled for MPU
* enabled ports.
*/
configASSERT( ( pxSendCompletedCallback == NULL ) &&
( pxReceiveCompletedCallback == NULL ) );
if( ( pxSendCompletedCallback == NULL ) &&
( pxReceiveCompletedCallback == NULL ) )
{
xPortRaisePrivilege( xRunningPrivileged );
xReturn = xStreamBufferGenericCreateStatic( xBufferSizeBytes,
xTriggerLevelBytes,
xIsMessageBuffer,
pucStreamBufferStorageArea,
pxStaticStreamBuffer,
NULL,
NULL );
vPortResetPrivilege( xRunningPrivileged );
}
else
{
traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer );
xReturn = NULL;
}
return xReturn;
}

View File

@ -69,6 +69,25 @@
( void ) xTaskResumeAll();
#endif /* sbRECEIVE_COMPLETED */
/* If user has provided a per-instance receive complete callback, then
* invoke the callback else use the receive complete macro which is provided by default for all instances.
*/
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
#define prvRECEIVE_COMPLETED( pxStreamBuffer ) \
{ \
if( pxStreamBuffer->pxReceiveCompletedCallback != NULL ) \
{ \
pxStreamBuffer->pxReceiveCompletedCallback( pxStreamBuffer, pdFALSE, NULL ); \
} \
else \
{ \
sbRECEIVE_COMPLETED( pxStreamBuffer ); \
} \
}
#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
#define prvRECEIVE_COMPLETED( pxStreamBuffer ) sbRECEIVE_COMPLETED( pxStreamBuffer )
#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
#ifndef sbRECEIVE_COMPLETED_FROM_ISR
#define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \
pxHigherPriorityTaskWoken ) \
@ -90,9 +109,28 @@
}
#endif /* sbRECEIVE_COMPLETED_FROM_ISR */
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
#define prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \
pxHigherPriorityTaskWoken ) \
{ \
if( pxStreamBuffer->pxReceiveCompletedCallback != NULL ) \
{ \
pxStreamBuffer->pxReceiveCompletedCallback( pxStreamBuffer, pdTRUE, pxHigherPriorityTaskWoken ); \
} \
else \
{ \
sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); \
} \
}
#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
#define prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken )
#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
/* If the user has not provided an application specific Tx notification macro,
* or #defined the notification macro away, them provide a default implementation
* that uses task notifications. */
* or #defined the notification macro away, then provide a default
* implementation that uses task notifications.
*/
#ifndef sbSEND_COMPLETED
#define sbSEND_COMPLETED( pxStreamBuffer ) \
vTaskSuspendAll(); \
@ -108,6 +146,26 @@
( void ) xTaskResumeAll();
#endif /* sbSEND_COMPLETED */
/* If user has provided a per-instance send completed callback, then
* invoke the callback else use the send complete macro which is provided by default for all instances.
*/
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
#define prvSEND_COMPLETED( pxStreamBuffer ) \
{ \
if( pxStreamBuffer->pxSendCompletedCallback != NULL ) \
{ \
pxStreamBuffer->pxSendCompletedCallback( pxStreamBuffer, pdFALSE, NULL ); \
} \
else \
{ \
sbSEND_COMPLETED( pxStreamBuffer ); \
} \
}
#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
#define prvSEND_COMPLETED( pxStreamBuffer ) sbSEND_COMPLETED( pxStreamBuffer )
#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
#ifndef sbSEND_COMPLETE_FROM_ISR
#define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
{ \
@ -127,6 +185,25 @@
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
}
#endif /* sbSEND_COMPLETE_FROM_ISR */
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
#define prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
{ \
if( pxStreamBuffer->pxSendCompletedCallback != NULL ) \
{ \
pxStreamBuffer->pxSendCompletedCallback( pxStreamBuffer, pdTRUE, pxHigherPriorityTaskWoken ); \
} \
else \
{ \
sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); \
} \
}
#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
#define prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken )
#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
/*lint -restore (9026) */
/* The number of bytes used to hold the length of a message in the buffer. */
@ -153,6 +230,11 @@ typedef struct StreamBufferDef_t /*lint !e9058 Style convention
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */
#endif
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
StreamBufferCallbackFunction_t pxSendCompletedCallback; /* Optional callback called on send complete. sbSEND_COMPLETED is called if this is NULL. */
StreamBufferCallbackFunction_t pxReceiveCompletedCallback; /* Optional callback called on receive complete. sbRECEIVE_COMPLETED is called if this is NULL. */
#endif
} StreamBuffer_t;
/*
@ -226,15 +308,17 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
uint8_t * const pucBuffer,
size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
uint8_t ucFlags ) PRIVILEGED_FUNCTION;
uint8_t ucFlags,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer )
BaseType_t xIsMessageBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
{
uint8_t * pucAllocatedMemory;
uint8_t ucFlags;
@ -289,7 +373,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */
xBufferSizeBytes,
xTriggerLevelBytes,
ucFlags );
ucFlags,
pxSendCompletedCallback,
pxReceiveCompletedCallback );
traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer );
}
@ -300,7 +386,6 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
return ( StreamBufferHandle_t ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
@ -310,7 +395,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer )
StaticStreamBuffer_t * const pxStaticStreamBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
{
StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */
StreamBufferHandle_t xReturn;
@ -360,7 +447,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
pucStreamBufferStorageArea,
xBufferSizeBytes,
xTriggerLevelBytes,
ucFlags );
ucFlags,
pxSendCompletedCallback,
pxReceiveCompletedCallback );
/* Remember this was statically allocated in case it is ever deleted
* again. */
@ -378,7 +467,6 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
return xReturn;
}
#endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
/*-----------------------------------------------------------*/
@ -419,6 +507,7 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
{
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
BaseType_t xReturn = pdFAIL;
StreamBufferCallbackFunction_t pxSendCallback = NULL, pxReceiveCallback = NULL;
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxStreamBufferNumber;
@ -437,25 +526,32 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
/* Can only reset a message buffer if there are no tasks blocked on it. */
taskENTER_CRITICAL();
{
if( pxStreamBuffer->xTaskWaitingToReceive == NULL )
if( ( pxStreamBuffer->xTaskWaitingToReceive == NULL ) && ( pxStreamBuffer->xTaskWaitingToSend == NULL ) )
{
if( pxStreamBuffer->xTaskWaitingToSend == NULL )
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
{
prvInitialiseNewStreamBuffer( pxStreamBuffer,
pxStreamBuffer->pucBuffer,
pxStreamBuffer->xLength,
pxStreamBuffer->xTriggerLevelBytes,
pxStreamBuffer->ucFlags );
xReturn = pdPASS;
#if ( configUSE_TRACE_FACILITY == 1 )
{
pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
}
#endif
traceSTREAM_BUFFER_RESET( xStreamBuffer );
pxSendCallback = pxStreamBuffer->pxSendCompletedCallback;
pxReceiveCallback = pxStreamBuffer->pxReceiveCompletedCallback;
}
#endif
prvInitialiseNewStreamBuffer( pxStreamBuffer,
pxStreamBuffer->pucBuffer,
pxStreamBuffer->xLength,
pxStreamBuffer->xTriggerLevelBytes,
pxStreamBuffer->ucFlags,
pxSendCallback,
pxReceiveCallback );
#if ( configUSE_TRACE_FACILITY == 1 )
{
pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
}
#endif
traceSTREAM_BUFFER_RESET( xStreamBuffer );
xReturn = pdPASS;
}
}
taskEXIT_CRITICAL();
@ -653,7 +749,7 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
/* Was a task waiting for the data? */
if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
{
sbSEND_COMPLETED( pxStreamBuffer );
prvSEND_COMPLETED( pxStreamBuffer );
}
else
{
@ -703,7 +799,7 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
/* Was a task waiting for the data? */
if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
{
sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
}
else
{
@ -858,7 +954,7 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
if( xReceivedLength != ( size_t ) 0 )
{
traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength );
sbRECEIVE_COMPLETED( pxStreamBuffer );
prvRECEIVE_COMPLETED( xStreamBuffer );
}
else
{
@ -954,7 +1050,7 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
/* Was a task waiting for space in the buffer? */
if( xReceivedLength != ( size_t ) 0 )
{
sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
}
else
{
@ -1260,7 +1356,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
uint8_t * const pucBuffer,
size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
uint8_t ucFlags )
uint8_t ucFlags,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
{
/* Assert here is deliberately writing to the entire buffer to ensure it can
* be written to without generating exceptions, and is setting the buffer to a
@ -1280,6 +1378,17 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
pxStreamBuffer->xLength = xBufferSizeBytes;
pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes;
pxStreamBuffer->ucFlags = ucFlags;
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
{
pxStreamBuffer->pxSendCompletedCallback = pxSendCompletedCallback;
pxStreamBuffer->pxReceiveCompletedCallback = pxReceiveCompletedCallback;
}
#else
{
( void ) pxSendCompletedCallback;
( void ) pxReceiveCompletedCallback;
}
#endif
}
#if ( configUSE_TRACE_FACILITY == 1 )