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