xref: /Kernel-v10.6.2/include/message_buffer.h (revision ef7b253b56c9788077f5ecd6c9deb4021923d646)
1 /*
2  * FreeRTOS Kernel V10.6.2
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28 
29 
30 /*
31  * Message buffers build functionality on top of FreeRTOS stream buffers.
32  * Whereas stream buffers are used to send a continuous stream of data from one
33  * task or interrupt to another, message buffers are used to send variable
34  * length discrete messages from one task or interrupt to another.  Their
35  * implementation is light weight, making them particularly suited for interrupt
36  * to task and core to core communication scenarios.
37  *
38  * ***NOTE***:  Uniquely among FreeRTOS objects, the stream buffer
39  * implementation (so also the message buffer implementation, as message buffers
40  * are built on top of stream buffers) assumes there is only one task or
41  * interrupt that will write to the buffer (the writer), and only one task or
42  * interrupt that will read from the buffer (the reader).  It is safe for the
43  * writer and reader to be different tasks or interrupts, but, unlike other
44  * FreeRTOS objects, it is not safe to have multiple different writers or
45  * multiple different readers.  If there are to be multiple different writers
46  * then the application writer must place each call to a writing API function
47  * (such as xMessageBufferSend()) inside a critical section and set the send
48  * block time to 0.  Likewise, if there are to be multiple different readers
49  * then the application writer must place each call to a reading API function
50  * (such as xMessageBufferRead()) inside a critical section and set the receive
51  * timeout to 0.
52  *
53  * Message buffers hold variable length messages.  To enable that, when a
54  * message is written to the message buffer an additional sizeof( size_t ) bytes
55  * are also written to store the message's length (that happens internally, with
56  * the API function).  sizeof( size_t ) is typically 4 bytes on a 32-bit
57  * architecture, so writing a 10 byte message to a message buffer on a 32-bit
58  * architecture will actually reduce the available space in the message buffer
59  * by 14 bytes (10 byte are used by the message, and 4 bytes to hold the length
60  * of the message).
61  */
62 
63 #ifndef FREERTOS_MESSAGE_BUFFER_H
64 #define FREERTOS_MESSAGE_BUFFER_H
65 
66 #ifndef INC_FREERTOS_H
67     #error "include FreeRTOS.h must appear in source files before include message_buffer.h"
68 #endif
69 
70 /* Message buffers are built onto of stream buffers. */
71 #include "stream_buffer.h"
72 
73 /* *INDENT-OFF* */
74 #if defined( __cplusplus )
75     extern "C" {
76 #endif
77 /* *INDENT-ON* */
78 
79 /**
80  * Type by which message buffers are referenced.  For example, a call to
81  * xMessageBufferCreate() returns an MessageBufferHandle_t variable that can
82  * then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(),
83  * etc. Message buffer is essentially built as a stream buffer hence its handle
84  * is also set to same type as a stream buffer handle.
85  */
86 typedef StreamBufferHandle_t MessageBufferHandle_t;
87 
88 /*-----------------------------------------------------------*/
89 
90 /**
91  * message_buffer.h
92  *
93  * @code{c}
94  * MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
95  * @endcode
96  *
97  * Creates a new message buffer using dynamically allocated memory.  See
98  * xMessageBufferCreateStatic() for a version that uses statically allocated
99  * memory (memory that is allocated at compile time).
100  *
101  * configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
102  * FreeRTOSConfig.h for xMessageBufferCreate() to be available.
103  *
104  * @param xBufferSizeBytes The total number of bytes (not messages) the message
105  * buffer will be able to hold at any one time.  When a message is written to
106  * the message buffer an additional sizeof( size_t ) bytes are also written to
107  * store the message's length.  sizeof( size_t ) is typically 4 bytes on a
108  * 32-bit architecture, so on most 32-bit architectures a 10 byte message will
109  * take up 14 bytes of message buffer space.
110  *
111  * @param pxSendCompletedCallback Callback invoked when a send operation to the
112  * message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
113  * is called without the parameter, then it will use the default implementation
114  * provided by sbSEND_COMPLETED macro. To enable the callback,
115  * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
116  *
117  * @param pxReceiveCompletedCallback Callback invoked when a receive operation from
118  * the message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
119  * is called without the parameter, it will use the default implementation provided
120  * by sbRECEIVE_COMPLETED macro. To enable the callback,
121  * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
122  *
123  * @return If NULL is returned, then the message buffer cannot be created
124  * because there is insufficient heap memory available for FreeRTOS to allocate
125  * the message buffer data structures and storage area.  A non-NULL value being
126  * returned indicates that the message buffer has been created successfully -
127  * the returned value should be stored as the handle to the created message
128  * buffer.
129  *
130  * Example use:
131  * @code{c}
132  *
133  * void vAFunction( void )
134  * {
135  * MessageBufferHandle_t xMessageBuffer;
136  * const size_t xMessageBufferSizeBytes = 100;
137  *
138  *  // Create a message buffer that can hold 100 bytes.  The memory used to hold
139  *  // both the message buffer structure and the messages themselves is allocated
140  *  // dynamically.  Each message added to the buffer consumes an additional 4
141  *  // bytes which are used to hold the length of the message.
142  *  xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
143  *
144  *  if( xMessageBuffer == NULL )
145  *  {
146  *      // There was not enough heap memory space available to create the
147  *      // message buffer.
148  *  }
149  *  else
150  *  {
151  *      // The message buffer was created successfully and can now be used.
152  *  }
153  *
154  * @endcode
155  * \defgroup xMessageBufferCreate xMessageBufferCreate
156  * \ingroup MessageBufferManagement
157  */
158 #define xMessageBufferCreate( xBufferSizeBytes ) \
159     xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, pdTRUE, NULL, NULL )
160 
161 #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
162     #define xMessageBufferCreateWithCallback( xBufferSizeBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
163     xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, pdTRUE, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
164 #endif
165 
166 /**
167  * message_buffer.h
168  *
169  * @code{c}
170  * MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
171  *                                                uint8_t *pucMessageBufferStorageArea,
172  *                                                StaticMessageBuffer_t *pxStaticMessageBuffer );
173  * @endcode
174  * Creates a new message buffer using statically allocated memory.  See
175  * xMessageBufferCreate() for a version that uses dynamically allocated memory.
176  *
177  * @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
178  * pucMessageBufferStorageArea parameter.  When a message is written to the
179  * message buffer an additional sizeof( size_t ) bytes are also written to store
180  * the message's length.  sizeof( size_t ) is typically 4 bytes on a 32-bit
181  * architecture, so on most 32-bit architecture a 10 byte message will take up
182  * 14 bytes of message buffer space.  The maximum number of bytes that can be
183  * stored in the message buffer is actually (xBufferSizeBytes - 1).
184  *
185  * @param pucMessageBufferStorageArea Must point to a uint8_t array that is at
186  * least xBufferSizeBytes big.  This is the array to which messages are
187  * copied when they are written to the message buffer.
188  *
189  * @param pxStaticMessageBuffer Must point to a variable of type
190  * StaticMessageBuffer_t, which will be used to hold the message buffer's data
191  * structure.
192  *
193  * @param pxSendCompletedCallback Callback invoked when a new message is sent to the message buffer.
194  * If the parameter is NULL or xMessageBufferCreate() is called without the parameter, then it will use the default
195  * implementation provided by sbSEND_COMPLETED macro. To enable the callback,
196  * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
197  *
198  * @param pxReceiveCompletedCallback Callback invoked when a message is read from a
199  * message buffer. If the parameter is NULL or xMessageBufferCreate() is called without the parameter, it will
200  * use the default implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
201  * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
202  *
203  * @return If the message buffer is created successfully then a handle to the
204  * created message buffer is returned. If either pucMessageBufferStorageArea or
205  * pxStaticmessageBuffer are NULL then NULL is returned.
206  *
207  * Example use:
208  * @code{c}
209  *
210  * // Used to dimension the array used to hold the messages.  The available space
211  * // will actually be one less than this, so 999.
212  #define STORAGE_SIZE_BYTES 1000
213  *
214  * // Defines the memory that will actually hold the messages within the message
215  * // buffer.
216  * static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
217  *
218  * // The variable used to hold the message buffer structure.
219  * StaticMessageBuffer_t xMessageBufferStruct;
220  *
221  * void MyFunction( void )
222  * {
223  * MessageBufferHandle_t xMessageBuffer;
224  *
225  *  xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucStorageBuffer ),
226  *                                               ucStorageBuffer,
227  *                                               &xMessageBufferStruct );
228  *
229  *  // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
230  *  // parameters were NULL, xMessageBuffer will not be NULL, and can be used to
231  *  // reference the created message buffer in other message buffer API calls.
232  *
233  *  // Other code that uses the message buffer can go here.
234  * }
235  *
236  * @endcode
237  * \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic
238  * \ingroup MessageBufferManagement
239  */
240 #define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \
241     xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, pdTRUE, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), NULL, NULL )
242 
243 #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
244     #define xMessageBufferCreateStaticWithCallback( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
245     xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, pdTRUE, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
246 #endif
247 
248 /**
249  * message_buffer.h
250  *
251  * @code{c}
252  * BaseType_t xMessageBufferGetStaticBuffers( MessageBufferHandle_t xMessageBuffer,
253  *                                            uint8_t ** ppucMessageBufferStorageArea,
254  *                                            StaticMessageBuffer_t ** ppxStaticMessageBuffer );
255  * @endcode
256  *
257  * Retrieve pointers to a statically created message buffer's data structure
258  * buffer and storage area buffer. These are the same buffers that are supplied
259  * at the time of creation.
260  *
261  * @param xMessageBuffer The message buffer for which to retrieve the buffers.
262  *
263  * @param ppucMessageBufferStorageArea Used to return a pointer to the
264  * message buffer's storage area buffer.
265  *
266  * @param ppxStaticMessageBuffer Used to return a pointer to the message
267  * buffer's data structure buffer.
268  *
269  * @return pdTRUE if buffers were retrieved, pdFALSE otherwise..
270  *
271  * \defgroup xMessageBufferGetStaticBuffers xMessageBufferGetStaticBuffers
272  * \ingroup MessageBufferManagement
273  */
274 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
275     #define xMessageBufferGetStaticBuffers( xMessageBuffer, ppucMessageBufferStorageArea, ppxStaticMessageBuffer ) \
276     xStreamBufferGetStaticBuffers( ( xMessageBuffer ), ( ppucMessageBufferStorageArea ), ( ppxStaticMessageBuffer ) )
277 #endif /* configSUPPORT_STATIC_ALLOCATION */
278 
279 /**
280  * message_buffer.h
281  *
282  * @code{c}
283  * size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
284  *                         const void *pvTxData,
285  *                         size_t xDataLengthBytes,
286  *                         TickType_t xTicksToWait );
287  * @endcode
288  *
289  * Sends a discrete message to the message buffer.  The message can be any
290  * length that fits within the buffer's free space, and is copied into the
291  * buffer.
292  *
293  * ***NOTE***:  Uniquely among FreeRTOS objects, the stream buffer
294  * implementation (so also the message buffer implementation, as message buffers
295  * are built on top of stream buffers) assumes there is only one task or
296  * interrupt that will write to the buffer (the writer), and only one task or
297  * interrupt that will read from the buffer (the reader).  It is safe for the
298  * writer and reader to be different tasks or interrupts, but, unlike other
299  * FreeRTOS objects, it is not safe to have multiple different writers or
300  * multiple different readers.  If there are to be multiple different writers
301  * then the application writer must place each call to a writing API function
302  * (such as xMessageBufferSend()) inside a critical section and set the send
303  * block time to 0.  Likewise, if there are to be multiple different readers
304  * then the application writer must place each call to a reading API function
305  * (such as xMessageBufferRead()) inside a critical section and set the receive
306  * block time to 0.
307  *
308  * Use xMessageBufferSend() to write to a message buffer from a task.  Use
309  * xMessageBufferSendFromISR() to write to a message buffer from an interrupt
310  * service routine (ISR).
311  *
312  * @param xMessageBuffer The handle of the message buffer to which a message is
313  * being sent.
314  *
315  * @param pvTxData A pointer to the message that is to be copied into the
316  * message buffer.
317  *
318  * @param xDataLengthBytes The length of the message.  That is, the number of
319  * bytes to copy from pvTxData into the message buffer.  When a message is
320  * written to the message buffer an additional sizeof( size_t ) bytes are also
321  * written to store the message's length.  sizeof( size_t ) is typically 4 bytes
322  * on a 32-bit architecture, so on most 32-bit architecture setting
323  * xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
324  * bytes (20 bytes of message data and 4 bytes to hold the message length).
325  *
326  * @param xTicksToWait The maximum amount of time the calling task should remain
327  * in the Blocked state to wait for enough space to become available in the
328  * message buffer, should the message buffer have insufficient space when
329  * xMessageBufferSend() is called.  The calling task will never block if
330  * xTicksToWait is zero.  The block time is specified in tick periods, so the
331  * absolute time it represents is dependent on the tick frequency.  The macro
332  * pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into
333  * a time specified in ticks.  Setting xTicksToWait to portMAX_DELAY will cause
334  * the task to wait indefinitely (without timing out), provided
335  * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h.  Tasks do not use any
336  * CPU time when they are in the Blocked state.
337  *
338  * @return The number of bytes written to the message buffer.  If the call to
339  * xMessageBufferSend() times out before there was enough space to write the
340  * message into the message buffer then zero is returned.  If the call did not
341  * time out then xDataLengthBytes is returned.
342  *
343  * Example use:
344  * @code{c}
345  * void vAFunction( MessageBufferHandle_t xMessageBuffer )
346  * {
347  * size_t xBytesSent;
348  * uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
349  * char *pcStringToSend = "String to send";
350  * const TickType_t x100ms = pdMS_TO_TICKS( 100 );
351  *
352  *  // Send an array to the message buffer, blocking for a maximum of 100ms to
353  *  // wait for enough space to be available in the message buffer.
354  *  xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
355  *
356  *  if( xBytesSent != sizeof( ucArrayToSend ) )
357  *  {
358  *      // The call to xMessageBufferSend() times out before there was enough
359  *      // space in the buffer for the data to be written.
360  *  }
361  *
362  *  // Send the string to the message buffer.  Return immediately if there is
363  *  // not enough space in the buffer.
364  *  xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
365  *
366  *  if( xBytesSent != strlen( pcStringToSend ) )
367  *  {
368  *      // The string could not be added to the message buffer because there was
369  *      // not enough free space in the buffer.
370  *  }
371  * }
372  * @endcode
373  * \defgroup xMessageBufferSend xMessageBufferSend
374  * \ingroup MessageBufferManagement
375  */
376 #define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) \
377     xStreamBufferSend( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( xTicksToWait ) )
378 
379 /**
380  * message_buffer.h
381  *
382  * @code{c}
383  * size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
384  *                                const void *pvTxData,
385  *                                size_t xDataLengthBytes,
386  *                                BaseType_t *pxHigherPriorityTaskWoken );
387  * @endcode
388  *
389  * Interrupt safe version of the API function that sends a discrete message to
390  * the message buffer.  The message can be any length that fits within the
391  * buffer's free space, and is copied into the buffer.
392  *
393  * ***NOTE***:  Uniquely among FreeRTOS objects, the stream buffer
394  * implementation (so also the message buffer implementation, as message buffers
395  * are built on top of stream buffers) assumes there is only one task or
396  * interrupt that will write to the buffer (the writer), and only one task or
397  * interrupt that will read from the buffer (the reader).  It is safe for the
398  * writer and reader to be different tasks or interrupts, but, unlike other
399  * FreeRTOS objects, it is not safe to have multiple different writers or
400  * multiple different readers.  If there are to be multiple different writers
401  * then the application writer must place each call to a writing API function
402  * (such as xMessageBufferSend()) inside a critical section and set the send
403  * block time to 0.  Likewise, if there are to be multiple different readers
404  * then the application writer must place each call to a reading API function
405  * (such as xMessageBufferRead()) inside a critical section and set the receive
406  * block time to 0.
407  *
408  * Use xMessageBufferSend() to write to a message buffer from a task.  Use
409  * xMessageBufferSendFromISR() to write to a message buffer from an interrupt
410  * service routine (ISR).
411  *
412  * @param xMessageBuffer The handle of the message buffer to which a message is
413  * being sent.
414  *
415  * @param pvTxData A pointer to the message that is to be copied into the
416  * message buffer.
417  *
418  * @param xDataLengthBytes The length of the message.  That is, the number of
419  * bytes to copy from pvTxData into the message buffer.  When a message is
420  * written to the message buffer an additional sizeof( size_t ) bytes are also
421  * written to store the message's length.  sizeof( size_t ) is typically 4 bytes
422  * on a 32-bit architecture, so on most 32-bit architecture setting
423  * xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
424  * bytes (20 bytes of message data and 4 bytes to hold the message length).
425  *
426  * @param pxHigherPriorityTaskWoken  It is possible that a message buffer will
427  * have a task blocked on it waiting for data.  Calling
428  * xMessageBufferSendFromISR() can make data available, and so cause a task that
429  * was waiting for data to leave the Blocked state.  If calling
430  * xMessageBufferSendFromISR() causes a task to leave the Blocked state, and the
431  * unblocked task has a priority higher than the currently executing task (the
432  * task that was interrupted), then, internally, xMessageBufferSendFromISR()
433  * will set *pxHigherPriorityTaskWoken to pdTRUE.  If
434  * xMessageBufferSendFromISR() sets this value to pdTRUE, then normally a
435  * context switch should be performed before the interrupt is exited.  This will
436  * ensure that the interrupt returns directly to the highest priority Ready
437  * state task.  *pxHigherPriorityTaskWoken should be set to pdFALSE before it
438  * is passed into the function.  See the code example below for an example.
439  *
440  * @return The number of bytes actually written to the message buffer.  If the
441  * message buffer didn't have enough free space for the message to be stored
442  * then 0 is returned, otherwise xDataLengthBytes is returned.
443  *
444  * Example use:
445  * @code{c}
446  * // A message buffer that has already been created.
447  * MessageBufferHandle_t xMessageBuffer;
448  *
449  * void vAnInterruptServiceRoutine( void )
450  * {
451  * size_t xBytesSent;
452  * char *pcStringToSend = "String to send";
453  * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
454  *
455  *  // Attempt to send the string to the message buffer.
456  *  xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
457  *                                          ( void * ) pcStringToSend,
458  *                                          strlen( pcStringToSend ),
459  *                                          &xHigherPriorityTaskWoken );
460  *
461  *  if( xBytesSent != strlen( pcStringToSend ) )
462  *  {
463  *      // The string could not be added to the message buffer because there was
464  *      // not enough free space in the buffer.
465  *  }
466  *
467  *  // If xHigherPriorityTaskWoken was set to pdTRUE inside
468  *  // xMessageBufferSendFromISR() then a task that has a priority above the
469  *  // priority of the currently executing task was unblocked and a context
470  *  // switch should be performed to ensure the ISR returns to the unblocked
471  *  // task.  In most FreeRTOS ports this is done by simply passing
472  *  // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
473  *  // variables value, and perform the context switch if necessary.  Check the
474  *  // documentation for the port in use for port specific instructions.
475  *  portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
476  * }
477  * @endcode
478  * \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
479  * \ingroup MessageBufferManagement
480  */
481 #define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) \
482     xStreamBufferSendFromISR( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( pxHigherPriorityTaskWoken ) )
483 
484 /**
485  * message_buffer.h
486  *
487  * @code{c}
488  * size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
489  *                            void *pvRxData,
490  *                            size_t xBufferLengthBytes,
491  *                            TickType_t xTicksToWait );
492  * @endcode
493  *
494  * Receives a discrete message from a message buffer.  Messages can be of
495  * variable length and are copied out of the buffer.
496  *
497  * ***NOTE***:  Uniquely among FreeRTOS objects, the stream buffer
498  * implementation (so also the message buffer implementation, as message buffers
499  * are built on top of stream buffers) assumes there is only one task or
500  * interrupt that will write to the buffer (the writer), and only one task or
501  * interrupt that will read from the buffer (the reader).  It is safe for the
502  * writer and reader to be different tasks or interrupts, but, unlike other
503  * FreeRTOS objects, it is not safe to have multiple different writers or
504  * multiple different readers.  If there are to be multiple different writers
505  * then the application writer must place each call to a writing API function
506  * (such as xMessageBufferSend()) inside a critical section and set the send
507  * block time to 0.  Likewise, if there are to be multiple different readers
508  * then the application writer must place each call to a reading API function
509  * (such as xMessageBufferRead()) inside a critical section and set the receive
510  * block time to 0.
511  *
512  * Use xMessageBufferReceive() to read from a message buffer from a task.  Use
513  * xMessageBufferReceiveFromISR() to read from a message buffer from an
514  * interrupt service routine (ISR).
515  *
516  * @param xMessageBuffer The handle of the message buffer from which a message
517  * is being received.
518  *
519  * @param pvRxData A pointer to the buffer into which the received message is
520  * to be copied.
521  *
522  * @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
523  * parameter.  This sets the maximum length of the message that can be received.
524  * If xBufferLengthBytes is too small to hold the next message then the message
525  * will be left in the message buffer and 0 will be returned.
526  *
527  * @param xTicksToWait The maximum amount of time the task should remain in the
528  * Blocked state to wait for a message, should the message buffer be empty.
529  * xMessageBufferReceive() will return immediately if xTicksToWait is zero and
530  * the message buffer is empty.  The block time is specified in tick periods, so
531  * the absolute time it represents is dependent on the tick frequency.  The
532  * macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
533  * into a time specified in ticks.  Setting xTicksToWait to portMAX_DELAY will
534  * cause the task to wait indefinitely (without timing out), provided
535  * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h.  Tasks do not use any
536  * CPU time when they are in the Blocked state.
537  *
538  * @return The length, in bytes, of the message read from the message buffer, if
539  * any.  If xMessageBufferReceive() times out before a message became available
540  * then zero is returned.  If the length of the message is greater than
541  * xBufferLengthBytes then the message will be left in the message buffer and
542  * zero is returned.
543  *
544  * Example use:
545  * @code{c}
546  * void vAFunction( MessageBuffer_t xMessageBuffer )
547  * {
548  * uint8_t ucRxData[ 20 ];
549  * size_t xReceivedBytes;
550  * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
551  *
552  *  // Receive the next message from the message buffer.  Wait in the Blocked
553  *  // state (so not using any CPU processing time) for a maximum of 100ms for
554  *  // a message to become available.
555  *  xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
556  *                                          ( void * ) ucRxData,
557  *                                          sizeof( ucRxData ),
558  *                                          xBlockTime );
559  *
560  *  if( xReceivedBytes > 0 )
561  *  {
562  *      // A ucRxData contains a message that is xReceivedBytes long.  Process
563  *      // the message here....
564  *  }
565  * }
566  * @endcode
567  * \defgroup xMessageBufferReceive xMessageBufferReceive
568  * \ingroup MessageBufferManagement
569  */
570 #define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) \
571     xStreamBufferReceive( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( xTicksToWait ) )
572 
573 
574 /**
575  * message_buffer.h
576  *
577  * @code{c}
578  * size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
579  *                                   void *pvRxData,
580  *                                   size_t xBufferLengthBytes,
581  *                                   BaseType_t *pxHigherPriorityTaskWoken );
582  * @endcode
583  *
584  * An interrupt safe version of the API function that receives a discrete
585  * message from a message buffer.  Messages can be of variable length and are
586  * copied out of the buffer.
587  *
588  * ***NOTE***:  Uniquely among FreeRTOS objects, the stream buffer
589  * implementation (so also the message buffer implementation, as message buffers
590  * are built on top of stream buffers) assumes there is only one task or
591  * interrupt that will write to the buffer (the writer), and only one task or
592  * interrupt that will read from the buffer (the reader).  It is safe for the
593  * writer and reader to be different tasks or interrupts, but, unlike other
594  * FreeRTOS objects, it is not safe to have multiple different writers or
595  * multiple different readers.  If there are to be multiple different writers
596  * then the application writer must place each call to a writing API function
597  * (such as xMessageBufferSend()) inside a critical section and set the send
598  * block time to 0.  Likewise, if there are to be multiple different readers
599  * then the application writer must place each call to a reading API function
600  * (such as xMessageBufferRead()) inside a critical section and set the receive
601  * block time to 0.
602  *
603  * Use xMessageBufferReceive() to read from a message buffer from a task.  Use
604  * xMessageBufferReceiveFromISR() to read from a message buffer from an
605  * interrupt service routine (ISR).
606  *
607  * @param xMessageBuffer The handle of the message buffer from which a message
608  * is being received.
609  *
610  * @param pvRxData A pointer to the buffer into which the received message is
611  * to be copied.
612  *
613  * @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
614  * parameter.  This sets the maximum length of the message that can be received.
615  * If xBufferLengthBytes is too small to hold the next message then the message
616  * will be left in the message buffer and 0 will be returned.
617  *
618  * @param pxHigherPriorityTaskWoken  It is possible that a message buffer will
619  * have a task blocked on it waiting for space to become available.  Calling
620  * xMessageBufferReceiveFromISR() can make space available, and so cause a task
621  * that is waiting for space to leave the Blocked state.  If calling
622  * xMessageBufferReceiveFromISR() causes a task to leave the Blocked state, and
623  * the unblocked task has a priority higher than the currently executing task
624  * (the task that was interrupted), then, internally,
625  * xMessageBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
626  * If xMessageBufferReceiveFromISR() sets this value to pdTRUE, then normally a
627  * context switch should be performed before the interrupt is exited.  That will
628  * ensure the interrupt returns directly to the highest priority Ready state
629  * task.  *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
630  * passed into the function.  See the code example below for an example.
631  *
632  * @return The length, in bytes, of the message read from the message buffer, if
633  * any.
634  *
635  * Example use:
636  * @code{c}
637  * // A message buffer that has already been created.
638  * MessageBuffer_t xMessageBuffer;
639  *
640  * void vAnInterruptServiceRoutine( void )
641  * {
642  * uint8_t ucRxData[ 20 ];
643  * size_t xReceivedBytes;
644  * BaseType_t xHigherPriorityTaskWoken = pdFALSE;  // Initialised to pdFALSE.
645  *
646  *  // Receive the next message from the message buffer.
647  *  xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
648  *                                                ( void * ) ucRxData,
649  *                                                sizeof( ucRxData ),
650  *                                                &xHigherPriorityTaskWoken );
651  *
652  *  if( xReceivedBytes > 0 )
653  *  {
654  *      // A ucRxData contains a message that is xReceivedBytes long.  Process
655  *      // the message here....
656  *  }
657  *
658  *  // If xHigherPriorityTaskWoken was set to pdTRUE inside
659  *  // xMessageBufferReceiveFromISR() then a task that has a priority above the
660  *  // priority of the currently executing task was unblocked and a context
661  *  // switch should be performed to ensure the ISR returns to the unblocked
662  *  // task.  In most FreeRTOS ports this is done by simply passing
663  *  // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
664  *  // variables value, and perform the context switch if necessary.  Check the
665  *  // documentation for the port in use for port specific instructions.
666  *  portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
667  * }
668  * @endcode
669  * \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
670  * \ingroup MessageBufferManagement
671  */
672 #define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) \
673     xStreamBufferReceiveFromISR( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( pxHigherPriorityTaskWoken ) )
674 
675 /**
676  * message_buffer.h
677  *
678  * @code{c}
679  * void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
680  * @endcode
681  *
682  * Deletes a message buffer that was previously created using a call to
683  * xMessageBufferCreate() or xMessageBufferCreateStatic().  If the message
684  * buffer was created using dynamic memory (that is, by xMessageBufferCreate()),
685  * then the allocated memory is freed.
686  *
687  * A message buffer handle must not be used after the message buffer has been
688  * deleted.
689  *
690  * @param xMessageBuffer The handle of the message buffer to be deleted.
691  *
692  */
693 #define vMessageBufferDelete( xMessageBuffer ) \
694     vStreamBufferDelete( xMessageBuffer )
695 
696 /**
697  * message_buffer.h
698  * @code{c}
699  * BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer );
700  * @endcode
701  *
702  * Tests to see if a message buffer is full.  A message buffer is full if it
703  * cannot accept any more messages, of any size, until space is made available
704  * by a message being removed from the message buffer.
705  *
706  * @param xMessageBuffer The handle of the message buffer being queried.
707  *
708  * @return If the message buffer referenced by xMessageBuffer is full then
709  * pdTRUE is returned.  Otherwise pdFALSE is returned.
710  */
711 #define xMessageBufferIsFull( xMessageBuffer ) \
712     xStreamBufferIsFull( xMessageBuffer )
713 
714 /**
715  * message_buffer.h
716  * @code{c}
717  * BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer );
718  * @endcode
719  *
720  * Tests to see if a message buffer is empty (does not contain any messages).
721  *
722  * @param xMessageBuffer The handle of the message buffer being queried.
723  *
724  * @return If the message buffer referenced by xMessageBuffer is empty then
725  * pdTRUE is returned.  Otherwise pdFALSE is returned.
726  *
727  */
728 #define xMessageBufferIsEmpty( xMessageBuffer ) \
729     xStreamBufferIsEmpty( xMessageBuffer )
730 
731 /**
732  * message_buffer.h
733  * @code{c}
734  * BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
735  * @endcode
736  *
737  * Resets a message buffer to its initial empty state, discarding any message it
738  * contained.
739  *
740  * A message buffer can only be reset if there are no tasks blocked on it.
741  *
742  * @param xMessageBuffer The handle of the message buffer being reset.
743  *
744  * @return If the message buffer was reset then pdPASS is returned.  If the
745  * message buffer could not be reset because either there was a task blocked on
746  * the message queue to wait for space to become available, or to wait for a
747  * a message to be available, then pdFAIL is returned.
748  *
749  * \defgroup xMessageBufferReset xMessageBufferReset
750  * \ingroup MessageBufferManagement
751  */
752 #define xMessageBufferReset( xMessageBuffer ) \
753     xStreamBufferReset( xMessageBuffer )
754 
755 
756 /**
757  * message_buffer.h
758  * @code{c}
759  * size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer );
760  * @endcode
761  * Returns the number of bytes of free space in the message buffer.
762  *
763  * @param xMessageBuffer The handle of the message buffer being queried.
764  *
765  * @return The number of bytes that can be written to the message buffer before
766  * the message buffer would be full.  When a message is written to the message
767  * buffer an additional sizeof( size_t ) bytes are also written to store the
768  * message's length.  sizeof( size_t ) is typically 4 bytes on a 32-bit
769  * architecture, so if xMessageBufferSpacesAvailable() returns 10, then the size
770  * of the largest message that can be written to the message buffer is 6 bytes.
771  *
772  * \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable
773  * \ingroup MessageBufferManagement
774  */
775 #define xMessageBufferSpaceAvailable( xMessageBuffer ) \
776     xStreamBufferSpacesAvailable( xMessageBuffer )
777 #define xMessageBufferSpacesAvailable( xMessageBuffer ) \
778     xStreamBufferSpacesAvailable( xMessageBuffer ) /* Corrects typo in original macro name. */
779 
780 /**
781  * message_buffer.h
782  * @code{c}
783  * size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer );
784  * @endcode
785  * Returns the length (in bytes) of the next message in a message buffer.
786  * Useful if xMessageBufferReceive() returned 0 because the size of the buffer
787  * passed into xMessageBufferReceive() was too small to hold the next message.
788  *
789  * @param xMessageBuffer The handle of the message buffer being queried.
790  *
791  * @return The length (in bytes) of the next message in the message buffer, or 0
792  * if the message buffer is empty.
793  *
794  * \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes
795  * \ingroup MessageBufferManagement
796  */
797 #define xMessageBufferNextLengthBytes( xMessageBuffer ) \
798     xStreamBufferNextMessageLengthBytes( xMessageBuffer ) PRIVILEGED_FUNCTION;
799 
800 /**
801  * message_buffer.h
802  *
803  * @code{c}
804  * BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken );
805  * @endcode
806  *
807  * For advanced users only.
808  *
809  * The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
810  * data is sent to a message buffer or stream buffer.  If there was a task that
811  * was blocked on the message or stream buffer waiting for data to arrive then
812  * the sbSEND_COMPLETED() macro sends a notification to the task to remove it
813  * from the Blocked state.  xMessageBufferSendCompletedFromISR() does the same
814  * thing.  It is provided to enable application writers to implement their own
815  * version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
816  *
817  * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
818  * additional information.
819  *
820  * @param xMessageBuffer The handle of the stream buffer to which data was
821  * written.
822  *
823  * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
824  * initialised to pdFALSE before it is passed into
825  * xMessageBufferSendCompletedFromISR().  If calling
826  * xMessageBufferSendCompletedFromISR() removes a task from the Blocked state,
827  * and the task has a priority above the priority of the currently running task,
828  * then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
829  * context switch should be performed before exiting the ISR.
830  *
831  * @return If a task was removed from the Blocked state then pdTRUE is returned.
832  * Otherwise pdFALSE is returned.
833  *
834  * \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR
835  * \ingroup StreamBufferManagement
836  */
837 #define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
838     xStreamBufferSendCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) )
839 
840 /**
841  * message_buffer.h
842  *
843  * @code{c}
844  * BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken );
845  * @endcode
846  *
847  * For advanced users only.
848  *
849  * The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
850  * data is read out of a message buffer or stream buffer.  If there was a task
851  * that was blocked on the message or stream buffer waiting for data to arrive
852  * then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
853  * remove it from the Blocked state.  xMessageBufferReceiveCompletedFromISR()
854  * does the same thing.  It is provided to enable application writers to
855  * implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
856  * ANY OTHER TIME.
857  *
858  * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
859  * additional information.
860  *
861  * @param xMessageBuffer The handle of the stream buffer from which data was
862  * read.
863  *
864  * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
865  * initialised to pdFALSE before it is passed into
866  * xMessageBufferReceiveCompletedFromISR().  If calling
867  * xMessageBufferReceiveCompletedFromISR() removes a task from the Blocked state,
868  * and the task has a priority above the priority of the currently running task,
869  * then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
870  * context switch should be performed before exiting the ISR.
871  *
872  * @return If a task was removed from the Blocked state then pdTRUE is returned.
873  * Otherwise pdFALSE is returned.
874  *
875  * \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR
876  * \ingroup StreamBufferManagement
877  */
878 #define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
879     xStreamBufferReceiveCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) )
880 
881 /* *INDENT-OFF* */
882 #if defined( __cplusplus )
883     } /* extern "C" */
884 #endif
885 /* *INDENT-ON* */
886 
887 #endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */
888