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