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