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