diff --git a/.github/lexicon.txt b/.github/lexicon.txt index 85aa17a7f..751013504 100644 --- a/.github/lexicon.txt +++ b/.github/lexicon.txt @@ -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 diff --git a/History.txt b/History.txt index ba456f731..7f57de148 100644 --- a/History.txt +++ b/History.txt @@ -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 diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index c961158d6..5ce4e28b2 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -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. */ diff --git a/include/message_buffer.h b/include/message_buffer.h index b1962fac7..32284c4fb 100644 --- a/include/message_buffer.h +++ b/include/message_buffer.h @@ -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 diff --git a/include/mpu_prototypes.h b/include/mpu_prototypes.h index 2c7b0e39f..1893db844 100644 --- a/include/mpu_prototypes.h +++ b/include/mpu_prototypes.h @@ -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; diff --git a/include/stream_buffer.h b/include/stream_buffer.h index a00fd7cce..a3a263d95 100644 --- a/include/stream_buffer.h +++ b/include/stream_buffer.h @@ -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; diff --git a/portable/Common/mpu_wrappers.c b/portable/Common/mpu_wrappers.c index c9f23f1d0..74990c3da 100644 --- a/portable/Common/mpu_wrappers.c +++ b/portable/Common/mpu_wrappers.c @@ -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; } diff --git a/stream_buffer.c b/stream_buffer.c index fe6e77df9..b9d598e17 100644 --- a/stream_buffer.c +++ b/stream_buffer.c @@ -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 )