FreeRTOS学习笔记-消息缓冲区(FreeRTOS中文官网)

2023-05-16

RTOS消息缓冲区
[API]

RTOS 消息缓冲区 API 函数:

  • xMessageBufferCreate()
  • xMessageBufferCreateStatic()
  • xMessageBufferSend()
  • xMessageBufferSendFromISR()
  • xMessageBufferReceive()
  • xMessageBufferReceiveFromISR()
  • vMessageBufferDelete()
  • xMessageBufferSpacesAvailable()
  • xMessageBufferReset()
  • xMessageBufferIsEmpty()
  • xMessageBufferIsFull()

xMessageBufferCreate / xMessageBufferCreateWithCallback
[RTOS 消息缓冲区 API]


message_buffer.h


MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );

MessageBufferHandle_t xMessageBufferCreateWithCallback( 
                          size_t xBufferSizeBytes,
                          StreamBufferCallbackFunction_t pxSendCompletedCallback,
                          StreamBufferCallbackFunction_t pxReceiveCompletedCallback );
  

使用动态分配的内存新建消息缓冲区。 消息缓冲区会在每次发送和接收操作完成后执行回调。使用 xMessageBufferCreate() API 创建的消息缓冲区共享相同的发送和接收完成回调函数,这些回调函数通过 sbSEND_COMPLETED() 和 sbRECEIVE_COMPLETED() 宏定义。使用 xMessageBufferCreateWithCallback() API 创建的消息缓冲区 可以有自己唯一的发送和接收完成回调函数。请参阅 xMessageBufferCreateStatic() and xMessageBufferCreateStaticWithCallback() 获取使用静态分配内存(在编译时分配的内存)的相应版本。

configSUPPORT_DYNAMIC_ALLOCATION 必须在 FreeRTOSConfig.h 中设置为 1 或未定义,xMessageBufferCreate() 才可用。此外,configUSE_SB_COMPLETED_CALLBACK 必须在 FreeRTOSConfig.h 中设置为 1,xMessageBufferCreateWithCallback() 才可用。

将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中即可启用消息缓冲区功能 (因为消息缓冲区使用流缓冲区)。

参数:

xBufferSizeBytes

消息缓冲区在任何时候能够容纳的字节(而非消息)总数。当消息写入消息缓冲区时, 同时也会写入额外的 sizeof( size_t ) 字节以存储消息的长度。 sizeof( size_t ) 在 32 位架构上的大小通常是 4 个字节,因此在大多数 32 位架构中,10 字节的消息将占用 14 字节的 消息缓冲区空间。

pxSendCompletedCallback

消息写入消息缓冲区时调用的回调函数。如果参数为 NULL, 则使用 sbSEND_COMPLETED 宏所提供的默认实现。发送完成回调函数必须 具有 StreamBufferCallbackFunction_t 定义的原型,即

void vSendCallbackFunction( MessageBufferHandle_t xMessageBuffer,
                            BaseType_t xIsInsideISR,
                            BaseType_t * const pxHigherPriorityTaskWoken );

pxReceiveCompletedCallback

从消息缓冲区读取消息时调用的回调函数。如果参数为 NULL, 则使用 sbRECEIVE_COMPLETED 宏所提供的默认实现。接收完成回调函数必须 具有 StreamBufferCallbackFunction_t 定义的原型,即

void vReceiveCallbackFunction( MessageBufferHandle_t xMessageBuffer,
                               BaseType_t xIsInsideISR,
                               BaseType_t * const pxHigherPriorityTaskWoken );

Returns:

如果返回 NULL,则说明因为没有足够的堆内存可供 FreeRTOS 分配消息缓冲区的数据结构体和存储区域,所以无法创建消息缓冲区。如果返回非 NULL 值,则表示消息 缓冲区已成功创建,返回值应该作为所创建消息缓冲区的句柄来存储。

用法示例:

void vSendCallbackFunction( MessageBufferHandle_t xMessageBuffer,
                            BaseType_t xIsInsideISR,
                            BaseType_t * const pxHigherPriorityTaskWoken )
{
    /* Insert code here which is invoked when a message is written to
     * the message buffer.
     * This is useful when a message buffer is used to pass messages between
     * cores on a multicore processor. In that scenario, this callback
     * can be implemented to generate an interrupt in the other CPU core,
     * and the interrupt's service routine can then use the
     * xMessageBufferSendCompletedFromISR() API function to check, and if
     * necessary unblock, a task that was waiting for message. */
}

void vReceiveCallbackFunction( MessageBufferHandle_t xMessageBuffer,
                               BaseType_t xIsInsideISR,
                               BaseType_t * const pxHigherPriorityTaskWoken )
{
    /* Insert code here which is invoked when a message is read from a message
     * buffer.
     * This is useful when a message buffer is used to pass messages between
     * cores on a multicore processor. In that scenario, this callback
     * can be implemented to generate an interrupt in the other CPU core,
     * and the interrupt's service routine can then use the
     * xMessageBufferReceiveCompletedFromISR() API function to check, and if
     * necessary unblock, a task that was waiting to send message. */
}

void vAFunction( void )
{
MessageBufferHandle_t xMessageBuffer, xMessageBufferWithCallback;
const size_t xMessageBufferSizeBytes = 100;

    /* Create a message buffer that can hold 100 bytes and uses the
     * functions defined using the sbSEND_COMPLETED() and
     * sbRECEIVE_COMPLETED() macros as send and receive completed
     * callback functions. The memory used to hold both the message
     * buffer structure and the data in the message buffer is
     * allocated dynamically. */
    xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
    
    if( xMessageBuffer == NULL )
    {
        /* There was not enough heap memory space available to create the
         * message buffer. */
    }
    else
    {
        /* The message buffer was created successfully and can now be used. */
    }
    
    /* Create a message buffer that can hold 100 bytes and uses the
     * functions vSendCallbackFunction and vReceiveCallbackFunction
     * as send and receive completed callback functions. The memory
     * used to hold both the message buffer structure and the data
     * in the message buffer is allocated dynamically. */
    xMessageBufferWithCallback = xMessageBufferCreateWithCallback( 
                                     xMessageBufferSizeBytes,
                                     vSendCallbackFunction,
                                     vReceiveCallbackFunction );
    if( xMessageBufferWithCallback == NULL )
    {
        /* There was not enough heap memory space available to create the
         * message buffer. */
    }
    else
    {
        /* The message buffer was created successfully and can now be used. */
    }
}

xMessageBufferCreateStatic / xMessageBufferCreateStaticWithCallback
[RTOS 消息缓冲区 API]


message_buffer.h


MessageBufferHandle_t xMessageBufferCreateStatic(
                          size_t xBufferSizeBytes,
                          uint8_t *pucMessageBufferStorageArea,
                          StaticMessageBuffer_t *pxStaticMessageBuffer );

MessageBufferHandle_t xMessageBufferCreateStaticWithCallback(
                          size_t xBufferSizeBytes,
                          uint8_t *pucMessageBufferStorageArea,
                          StaticMessageBuffer_t *pxStaticMessageBuffer,
                          StreamBufferCallbackFunction_t pxSendCompletedCallback,
                          StreamBufferCallbackFunction_t pxReceiveCompletedCallback );
  

使用静态分配的内存创建新的消息缓冲区。消息缓冲区 在完成每个发送和接收操作时执行回调。使用 xMessageBufferCreateStatic()API 创建的消息缓冲区共享相同的发送和接收完成回调函数,这些函数是用 sbSEND_COMPLETED() 和 sbRECEIVE_COMPLETED() 宏定义的。 使用 xMessageBufferCreateStaticWithCallback() API 创建的消息缓冲区可以有各自独特的发送和接收完成 回调函数。请参阅 xMessageBufferCreate() and xMessageBufferCreateWithCallback() 了解使用动态分配内存的对应版本。

configSUPPORT_STATIC_ALLOCATION 必须在 FreeRTOSConfig.h 中设置为 1, 才能使用 xMessageBufferCreateStatic()。此外,configUSE_SB_COMPLETED_CALLBACK 必须在 FreeRTOSConfig.h 中设置为 1, xMessageBufferCreateStaticWithCallback() 才可用。

将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中即可启用消息缓冲区功能 (因为消息缓冲区使用流缓冲区)。

参数:

void vSendCallbackFunction( MessageBufferHandle_t xMessageBuffer,
                            BaseType_t xIsInsideISR,
                            BaseType_t * const pxHigherPriorityTaskWoken );
void vReceiveCallbackFunction( MessageBufferHandle_t xMessageBuffer,
                               BaseType_t xIsInsideISR,
                               BaseType_t * const pxHigherPriorityTaskWoken );

xBufferSizeBytes

pucMessageBufferStorageArea 参数所指向的缓冲区的大小(单位:字节)。当消息写入消息缓冲区时, 同时也会写入额外的 sizeof(size_t)字节以存储消息的长度。 sizeof( size_t ) 在 32 位架构上的大小通常是 4 个字节,因此在大多数 32 位架构中,10 字节的消息将占用 14 字节的 消息缓冲区空间。可以存储在消息缓冲区的最大字节数实际上是 (xBufferSizeBytes - 1)。

pucMessageBufferStorageArea

必须指向一个大小至少为 xBufferSizeBytes + 1 的 uint8_t 数组。将消息写入消息缓冲区时, 实际上是将消息复制到这个数组。

pxStaticMessageBuffer

必须指向一个 StaticMessageBuffer_t 类型的变量,它将用于保存消息缓冲区的数据结构体。

pxSendCompletedCallback

当一条消息被写入消息缓冲区时调用的回调函数。如果参数为 NULL,则使用 sbSEND_COMPLETED 宏所提供的默认实现。发送完成回调函数必须具有 StreamBufferCallbackFunction_t 定义的原型,即:

pxReceiveCompletedCallback

当从消息缓冲区读取消息时 调用的回调函数。如果参数为 NULL,则使用 sbRECEIVE_COMPLETED 宏所提供的默认实现。接收完成回调函数必须具有 StreamBufferCallbackFunction_t 定义的原型,即:

Returns:

如果成功创建了消息缓冲区,那么将返回一个所创建消息缓冲区的句柄。如果 pucMessageBufferStorageArea 或 pxStaticMessageBuffer 为 NULL,则返回 NULL。

用法示例:

/* Used to dimension the array used to hold the messages. The available
 * space will actually be one less than this, so 999. */
#define STORAGE_SIZE_BYTES 1000

/* Defines the memory that will actually hold the messages within the message
 * buffer. Should be one more than the value passed in the xBufferSizeBytes
 * parameter. */
static uint8_t ucMessageBufferStorage[ STORAGE_SIZE_BYTES ];
static uint8_t ucMessageBufferWithCallbackStorage[ STORAGE_SIZE_BYTES ];

[/code-comment]/* The variable used to hold the message buffer structure. */[/code-comment]
StaticMessageBuffer_t xMessageBufferStruct;
StaticMessageBuffer_t xMessageBufferWithCallbackStruct;

void vSendCallbackFunction( MessageBufferHandle_t xMessageBuffer,
                            BaseType_t xIsInsideISR,
                            BaseType_t * const pxHigherPriorityTaskWoken )
{
    /* Insert code here which is invoked when a message is written to
     * the message buffer.
     * This is useful when a message buffer is used to pass messages between
     * cores on a multicore processor. In that scenario, this callback
     * can be implemented to generate an interrupt in the other CPU core,
     * and the interrupt's service routine can then use the
     * xMessageBufferSendCompletedFromISR() API function to check, and if
     * necessary unblock, a task that was waiting for message. */
}

void vReceiveCallbackFunction( MessageBufferHandle_t xMessageBuffer,
                               BaseType_t xIsInsideISR,
                               BaseType_t * const pxHigherPriorityTaskWoken )
{
    /* Insert code here which is invoked when a message is read from a message
     * buffer.
     * This is useful when a message buffer is used to pass messages between
     * cores on a multicore processor. In that scenario, this callback
     * can be implemented to generate an interrupt in the other CPU core,
     * and the interrupt's service routine can then use the
     * xMessageBufferReceiveCompletedFromISR() API function to check, and if
     * necessary unblock, a task that was waiting to send message. */
}

void MyFunction( void )
{
MessageBufferHandle_t xMessageBuffer, xMessageBufferWithCallback;

    /* Create a message buffer that uses the functions defined
     * using the sbSEND_COMPLETED() and sbRECEIVE_COMPLETED()
     * macros as send and receive completed callback functions. */
    xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucMessageBufferStorage ),
                                                 ucMessageBufferStorage,
                                                 &xMessageBufferStruct );
                                                 
    /* Create a message buffer that uses the functions
     * vSendCallbackFunction and vReceiveCallbackFunction as send
     * and receive completed callback functions. */
    xMessageBufferWithCallback = xMessageBufferCreateStaticWithCallback( 
                                     sizeof( ucMessageBufferWithCallbackStorage ),
                                     ucMessageBufferWithCallbackStorage,
                                     &xMessageBufferWithCallbackStruct,
                                     vSendCallbackFunction,
                                     vReceiveCallbackFunction );
    
    /* As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
     * parameters were NULL, xMessageBuffer and xMessageBufferWithCallback
     * will not be NULL, and can be used to reference the created message
     * buffers in other message buffer API calls. */
    
    /* Other code that uses the message buffers can go here. */
}

xMessageBufferSend()
[RTOS 消息缓冲区 API]


message_buffer.h


size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
                           const void *pvTxData,
                           size_t xDataLengthBytes,
                           TickType_t xTicksToWait );
  

将离散消息发送到消息缓冲区。 消息可以是 适合缓冲区可用空间的任意长度,并复制到缓冲区中 。

注意: 在 FreeRTOS 对象中唯一的流缓冲区实现 (消息缓冲区实现也是如此,因为消息缓冲区构建在 假定只有一个任务或中断会写到 缓冲区(写入器),而且只有一个任务或中断会从 缓冲区(读取器)读取。 写入器和读取器为不同的任务或中断是安全的, 或中断,但与其他 FreeRTOS 对象不同, 拥有多个不同的编写器或多个不同的读取器是不安全的。 如果有 多个不同的编写器,则应用程序编写者必须将每次调用 在临界区内写入 API 函数(如 xMessageBufferSend()),并使用发送阻塞时间 0。 同样,如果有多个不同的读取器,则应用程序 编写者必须将每次调用读取 API 函数(如 xMessageBufferRead()) 放在临界区中,并使用接收阻塞时间 0。

使用 xMessageBufferSend() 从任务写入消息缓冲区。 使用 xMessageBufferSendFromISR() 从中断服务程序 (ISR) 写入 消息缓冲区。

通过在构建中包含 FreeRTOS/source/stream_buffer.c 源文件 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  消息发送到的消息缓冲区 的句柄。
pvTxData  指向要复制到 消息缓冲区中的消息的指针。
xDataLengthBytes 消息长度, 即 从pvTxData复制到消息缓冲区的字节数。 当消息 写入消息缓冲区时,还会额外写入 sizeof( size_t ) 字节 用来存储消息的长度。 sizeof( size_t ) 在 32 位架构上通常为 4 字节, 因此在大多数 32 位架构上, xDataLengthBytes设置为20时,会将消息缓冲区中的可用空间减少24个字节 字节(20 字节的消息数据和 4 字节用来保存消息长度)。
xTicksToWait  如果调用 xMessageBufferSend() 时消息缓冲区 没有足够的空间,则 xTicksToWait 调用任务应保持 已阻塞状态的最长时间, 以等待消息缓冲区中有足够的空间可用。 如果 xTicksToWait 为零,则调用任务永远不会阻塞。 阻塞时间以滴答周期为单位,因此 它代表的绝对时间取决于滴答频率。 宏 pdMS_TO_TICKS() 可用于将以毫秒为单位的时间转换为 以滴答为单位的时间。 将 xTicksToWait 设置为 portMAX_DELAY 将导致 任务无限期等待(无超时),前提是 INCLUDE_vTaskSuspend 在 FreeRTOSConfig.h 中设置为 1。 任务在处于阻塞状态时 在处于已阻塞状态时不使用任何 CPU 时间。

Returns:

写入消息缓冲区的字节数。 如果调用 xMessageBufferSend() 在有足够的空间将消息写入消息缓冲区之前超时, 则返回零。 如果调用未 超时,则返回 xDataLength 字节。


用法示例:


void vAFunction( MessageBufferHandle_t xMessageBuffer )
{
size_t xBytesSent;
uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
char *pcStringToSend = "String to send";
const TickType_t x100ms = pdMS_TO_TICKS( 100 );

    /* Send an array to the message buffer, blocking for a maximum of 100ms to
    wait for enough space to be available in the message buffer. */
    xBytesSent = xMessageBufferSend( xMessageBuffer,
                                     ( void * ) ucArrayToSend,
                                     sizeof( ucArrayToSend ),
                                     x100ms );

    if( xBytesSent != sizeof( ucArrayToSend ) )
    {
        /* The call to xMessageBufferSend() times out before there was enough
        space in the buffer for the data to be written. */
    }

    /* Send the string to the message buffer.  Return immediately if there is
    not enough space in the buffer. */
    xBytesSent = xMessageBufferSend( xMessageBuffer,
                                    ( void * ) pcStringToSend,
                                    strlen( pcStringToSend ), 0 );

    if( xBytesSent != strlen( pcStringToSend ) )
    {
        /* The string could not be added to the message buffer because there was
        not enough free space in the buffer. */
    }
}  

xMessageBufferSendFromISR()
[RTOS 消息缓冲区 API]


message_buffer.h


size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
                                  const void *pvTxData,
                                  size_t xDataLengthBytes,
                                  BaseType_t *pxHigherPriorityTaskWoken );
  

中断安全版本的 API 函数, 用于向消息缓冲区发送离散消息。 消息长度只要满足缓冲区可用空间即可, 消息会被复制到缓冲区中。

注意: 与其他 FreeRTOS 对象都不同的是,流缓冲区的实现 (消息缓冲区的实现也是如此,因为消息缓冲区是建立在流缓冲区之上的) 流缓冲区的实现假定只有一个任务或中断将写入缓冲区(写入程序), 缓冲区(写入器),只有一个任务或中断会从 (读取程序)。 写入和读取 不同的任务或中断是安全的,但与其他FreeRTOS对象不同, 有多个不同的写入或多个不同的读取是不安全的。 如果 必须有多个不同的写入,那么应用程序编写者必须 将每个调用放置到临界区中的一个写入 API 函数(如 xStreamBufferSend())中, 并将发送阻塞时间设置为0。 同样,如果有多个不同的读取器, 那么应用程序编写者必须将每个调用放置到临界区中的读取API函数(如xStreamBufferRead())中, 并使用阻塞时间 0。

使用 xMessageBufferSend() 往任务的消息缓冲区写入消息。 xMessageBufferSendFromISR()用于 往中断服务程序 (ISR) 的消息缓冲区写入 数据。

通过在构建中包含 FreeRTOS/source/stream_buffer.c 源文件 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  消息发送到的消息缓冲区 的句柄。
pvTxData  要复制到消息缓冲区中的消息 的指针。
xDataLengthBytes  消息长度, 即 从pvTxData复制到消息缓冲区的字节数。 当消息 写入消息缓冲区时,还会额外写入 sizeof( size_t ) 字节 用来存储消息的长度。 sizeof( size_t ) 在 32 位架构上通常为 4 字节, 因此在大多数 32 位架构上, xDataLengthBytes设置为20时,会将消息缓冲区中的可用空间减少24个字节 (其中消息数据占20个字节,4个字节用来保存消息长度)。
pxHigherPriorityTaskWoken (这是一个可选参数,可以设置为 NULL。) 消息缓冲区可能会 阻塞任务等待数据。 调用 xMessageBufferSendFromSISR() 可以使数据可用,从而使 正在等待数据的任务离开阻塞状态。 如果调用 xMessageBufferSendFromSISR() 使任务离开阻止状态,同时 未阻塞任务的优先级高于当前正在执行的任务 (被中断的任务),那么在内部,xMessageBufferSendFromISR() 将* 把pxHigherPriorityTaskWoken设置为pdTRUE。 如果 xMessageBufferSendFromSISR() 将此值设置为 pdTRUE , 那么通常应在退出中断之前执行上下文切换。 这将 确保中断直接返回到最高优先级的“就绪” 状态任务。 * pxHigherPriorityTaskWoken在传递给函数之前 应该设置为pdFALSE。 有关示例,请参阅下面的代码示例。

Returns:

实际写入消息缓冲区的字节数。 如果 消息缓冲区可用空间不足,无法存储消息, 则返回 0,否则返回 xDataLengthBytes。


用法示例:


/* A message buffer that has already been created. */
MessageBufferHandle_t xMessageBuffer;

void vAnInterruptServiceRoutine( void )
{
size_t xBytesSent;
char *pcStringToSend = "String to send";
BaseType_t xHigherPriorityTaskWoken = pdFALSE; /* Initialised to pdFALSE. */

    /* Attempt to send the string to the message buffer. */
    xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
                                            ( void * ) pcStringToSend,
                                            strlen( pcStringToSend ),
                                            &xHigherPriorityTaskWoken );

    if( xBytesSent != strlen( pcStringToSend ) )
    {
        /* The string could not be added to the message buffer because there was
        not enough free space in the buffer. */
    }

    /* If xHigherPriorityTaskWoken was set to pdTRUE inside
    xMessageBufferSendFromISR() then a task that has a priority above the
    priority of the currently executing task was unblocked and a context
    switch should be performed to ensure the ISR returns to the unblocked
    task.  In most FreeRTOS ports this is done by simply passing
    xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
    variables value, and perform the context switch if necessary.  Check the
    documentation for the port in use for port specific instructions. */
    taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}  

xMessageBufferReceive()
[RTOS 消息缓冲区 API]


message_buffer.h


size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
                              void *pvRxData,
                              size_t xBufferLengthBytes,
                              TickType_t xTicksToWait );
  

从RTOS 消息缓冲区接收离散消息。 消息长度可变, 并且从缓冲区中复制出来。

注意: 与其他 FreeRTOS 对象都不同的是,流缓冲区的实现 (消息缓冲区的实现也是如此,因为消息缓冲区是建立在流缓冲区之上的) 流缓冲区的实现假定只有一个任务或中断将写入缓冲区(写入程序), 缓冲区(写入器),只有一个任务或中断会从 (读取程序)。 写入和读取 不同的任务或中断是安全的,但与其他FreeRTOS对象不同, 有多个不同的写入或多个不同的读取是不安全的。 如果 必须有多个不同的写入,那么应用程序编写者必须 将每个调用放置到临界区中的一个写入 API 函数(如 xStreamBufferSend())中, 并将发送阻塞时间设置为0。 同样,如果有多个不同的读取器, 那么应用程序编写者必须将每个调用放置到临界区中的读取API函数(如xStreamBufferRead())中, 并使用接收阻塞时间 0。

使用 xMessageBufferReceive () 从任务中的消息缓冲区读取数据。 使用 xMessageBufferReceiveFromISR() 从 中断服务程序 (ISR) 中的消息缓冲区读取数据。

消息缓冲区的功能是通过将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  正在接收消息来自的消息缓冲区 的句柄。
pvRxData  指向缓冲区的指针,收到的信息 将被复制到该缓冲区。
xBufferLengthBytes 由 pvRxData 参数指向的缓冲区的 长度。 这将设置可以接收的消息的最大长度。 如果 xBufferLengthBytes 空间不足,无法保存下一条消息,那么消息 将保留在消息缓冲区中,并且将返回 0。
xTicksToWait  调用xMessageBufferReceive()时, 如果消息缓冲区为空, 则调用任务保持在阻塞状态等待消息的最长时间。 如果 xTicksToWait 为零并且消息缓冲区为空,将立即返回。 阻塞时间在滴答周期中指定,因此 它所表示的绝对时间取决于滴答频率。 宏pdMS_TO_TICKS()可以用来将以毫秒为单位的时间转换成以刻度为单位的时间。 宏pdMS_TO_TICKS()可以用来将以毫秒为单位的时间 转换为以 tick 为单位的时间。 将xTicksToWait设置为portMAX_DELAY会 导致任务无限期地等待(没有超时),前提是 在FreeRTOSConfig.h中将INCLUDE_vTaskSuspend设置为1。 任务在处于阻塞状态时 不使用任何CPU时间。

Returns:

从消息缓冲区读取的消息的长度(以字节为单位) (如有)。 如果在消息写入之前,xMessageBufferSend() 调用超时, 则返回零。 如果消息长度大于 xBufferLengthBytes,则消息将保留在消息缓冲区中, 同时返回零。


用法示例:


void vAFunction( MessageBuffer_t xMessageBuffer )
{
uint8_t ucRxData[ 20 ];
size_t xReceivedBytes;
const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );

    /* Receive the next message from the message buffer.  Wait in the Blocked
    state (so not using any CPU processing time) for a maximum of 100ms for
    a message to become available. */
    xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
                                            ( void * ) ucRxData,
                                            sizeof( ucRxData ),
                                            xBlockTime );

    if( xReceivedBytes > 0 )
    {
        /* A ucRxData contains a message that is xReceivedBytes long.  Process
        the message here.... */
    }
}  

xMessageBufferReceiveFromISR()
[RTOS 消息缓冲区 API]


message_buffer.h


size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
                                     void *pvRxData,
                                     size_t xBufferLengthBytes,
                                     BaseType_t *pxHigherPriorityTaskWoken );
  

中断安全版本的 API 函数,用于 从消息缓冲区接收离散消息。 消息长度可变, 从缓冲区中复制出来。

注意: 与其他 FreeRTOS 对象都不同的是,流缓冲区的实现 (消息缓冲区的实现也是如此,因为消息缓冲区是建立在流缓冲区之上的) 流缓冲区的实现假定只有一个任务或中断将写入缓冲区(写入程序), 缓冲区(写入器),只有一个任务或中断会从 (读取程序)。 写入和读取 不同的任务或中断是安全的,但与其他FreeRTOS对象不同, 有多个不同的写入或多个不同的读取是不安全的。 如果 必须有多个不同的写入,那么应用程序编写者必须 将每个调用放置到临界区中的一个写入 API 函数(如 xStreamBufferSend())中, 并将发送阻塞时间设置为0。 同样,如果有多个不同的读取器, 那么应用程序编写者必须将每个调用放置到临界区中的读取API函数(如xStreamBufferRead())中, 并将接收阻塞时间设置为0。

使用 xMessageBufferReceive() 从任务的消息缓冲区读取数据。 使用 xMessageBufferReceiveFromISR () 从中断服务程序 (ISR) 的消息缓冲区 读取数据。

消息缓冲区的功能是通过将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  消息缓冲区的句柄,正在接收的信息来自该消息缓存区。
pvRxData  一个指向缓冲区的指针,收到的信息将 被复制到该缓冲区。
xBufferLengthBytes  由 pvRxData 参数指向的缓冲区的 长度。 这将设置可以接收的消息的最大长度。 如果 xBufferLengthBytes 空间不足,无法保存下一条消息,那么消息 将保留在消息缓冲区中,并且将返回 0。
pxHigherPriorityTaskWoken (此为可选参数,可以设置为 NULL。) 消息缓冲区可能会 阻塞任务,等待可用空间。 调用 xMessageBufferReceiveFromISR () 可以使空间可用,从而使等待空间的任务 结束阻塞状态。 如果调用 xMessageBufferReceiveFromISR () 导致任务结束阻塞状态,并且 未阻塞任务的优先级高于当前正在执行的任务 (被中断的任务),那么在内部, xMessageBufferReceiveFromISR() 将* pxHigherPriorityTaskWoken 设置为 pdTRUE。 如果 xMessageBufferReceiveFromISR() 将此值设置为 pdTRUE, 那么通常应在退出中断之前执行上下文切换。 这将 确保中断直接返回到最高优先级的就绪状态 任务。 * pxHigherPriorityTaskWoken在传递给函数之前 应该设置为pdFALSE。 有关示例,请参阅下面的代码示例。

Returns:

从消息缓冲区读取的消息的长度(以字节为单位) (如有)。


用法示例:


/* A message buffer that has already been created. */
MessageBuffer_t xMessageBuffer;

void vAnInterruptServiceRoutine( void )
{
uint8_t ucRxData[ 20 ];
size_t xReceivedBytes;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;  /* Initialised to pdFALSE. */

    /* Receive the next message from the message buffer. */
    xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
                                                  ( void * ) ucRxData,
                                                  sizeof( ucRxData ),
                                                  &xHigherPriorityTaskWoken );

    if( xReceivedBytes > 0 )
    {
        /* A ucRxData contains a message that is xReceivedBytes long.  Process
        the message here.... */
    }

    /* If xHigherPriorityTaskWoken was set to pdTRUE inside
    xMessageBufferReceiveFromISR() then a task that has a priority above the
    priority of the currently executing task was unblocked and a context
    switch should be performed to ensure the ISR returns to the unblocked
    task.  In most FreeRTOS ports this is done by simply passing
    xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
    variables value, and perform the context switch if necessary.  Check the
    documentation for the port in use for port specific instructions. */
    taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}  

vMessageBufferDelete()
[RTOS 消息缓冲区 API]


message_buffer.h


void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
  

删除之前创建的消息缓冲区 (通过调用 xMessageBufferCreate() 或 xMessageBufferCreateStatic() 创建)。 如果使用动态内存(即由 xMessageBufferCreate())创建消息缓冲区, 则会释放分配的内存。

删除消息缓冲区后,不得使用消息缓冲区 句柄。

通过在构建中包含 FreeRTOS/source/stream_buffer.c 源文件, 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  要删除的消息缓冲区的句柄。

xMessageBufferSpacesAvailable()
[RTOS 消息缓冲区 API]


message_buffer.h


size_t xMessageBufferSpacesAvailable( MessageBufferHandle_t xMessageBuffer );
  

查询一个消息缓冲区,以查看它包含多少空闲空间, 这等于在消息缓冲区满之前可以 向它发送的数据量。 返回的值比可发送到消息缓冲区的 最大消息大小多了 4 个字节。

通过将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  正在查询的消息缓冲区的句柄。

Returns:

在消息缓冲区满之前,可以写入消息缓冲区的 字节数。 当消息被 写入消息缓冲区时,还会额外写入 sizeof( size_t ) 字节 用来存储消息的长度。 在 32 位的架构上,sizeof( size_t ) 通常为 4 个字节, 因此如果 xMessageBufferSpacesAvailable() 返回 10, 则可以写入消息缓冲区的最大消息的大小 为 6 字节。

xMessageBufferReset()
[RTOS 消息缓冲区 API]


message_buffer.h


BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
  

将消息缓冲区重置为其初始空状态。 任何在消息缓冲区的数据 都被丢弃。 只有没有任务处于阻塞态以等待向消息缓冲区发送或从消息缓冲区接收时, 消息缓冲区才能被重置 。

通过在构建中包含 FreeRTOS/source/stream_buffer.c 源文件 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  正在重置的消息缓冲区的句柄。

Returns:

如果重置消息缓冲区,则返回 pdPASS。 如果有 一个任务处于阻塞态,等待向消息缓冲区发送或从消息缓冲区读取, 则消息缓冲区将不会被重置,并返回 pdFAIL。

xMessageBufferIsEmpty()
[RTOS 消息缓冲区 API]


message_buffer.h


BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer );
  

查询消息缓冲区是否为空。 如果消息缓冲区不包含任何消息,则为空。

将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中即可 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  正在查询的消息缓冲区的句柄。

Returns:

若消息缓冲区为空,则返回 pdTRUE。 否则 返回 pdFALSE。

xMessageBufferIsFull()
[RTOS 消息缓冲区 API]


message_buffer.h


BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer );
  

查询消息缓冲区以查看其是否已满。 如果消息缓冲区无法再接受任何大小的消息,则消息缓冲区已满, 直到通过从消息缓冲区中删除消息来提供空间为止。

通过将 FreeRTOS/source/stream_buffer.c 源文件包含在构建(消息缓冲区使用流缓冲区)中 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

参数:

xMessageBuffer  正在查询的消息缓冲区的句柄。

Returns:

如果消息缓冲区已满,则返回 pdTRUE。 否则 返回 pdFALSE。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS学习笔记-消息缓冲区(FreeRTOS中文官网) 的相关文章

  • ubuntu16.04下ROS Kinetic详细安装过程

    参考网址 xff1a 点击打开链接 参考文献 xff1a ROS机器人编程 配置环境 xff1a ubuntu 16 04 LTS 43 ROS Kinetic 一 安装ROS 1 设置镜像源 为了保证安装速度 xff0c 需要选择国内的镜
  • vscode环境中配置git

    1 建立project空目录用于存放electron基本环境这个环境中得文件不能加入git项目中否则每次更新文件太大github不支持大于100M得文件上传 2 使用vscode打开project目录 3 打开终端运行npm install
  • idea 主题 代码颜色 代码区背景 行号背景 注释颜色修改

    最近写代码眼睛总是看的不舒服 xff0c 想着换一个主题 xff0c 但是换了主题 xff0c 代码的颜色显示和之前又不一样了 xff0c 接下来就是修改主题 xff0c 但是代码颜色仍然保持 Darcula 主题的颜色 目录 1 修改主题
  • RTT之SysTick做了什么

    经过好几天的摸索 xff0c 终于正常驱动了一个串口设备 xff0c 并成功移植到雅特力的板子上 xff01 当然 xff0c 还得继续努力把RTT的内核搞清楚 xff0c 这样才会构建整个项目程序 xff0c 毕竟项目是有时间限制的 因为
  • realSense 安装 经验整理

    安装 RealSense SDK 以ros 参考1 参考二 主要看参考三 标定 标定 以上内容安装失败 Realense sdk和ros对应关系 jetson jetson 一键安装sdk 官方安装 jetson4 4 xavier nx
  • 吴恩达machine learning yearning读书笔记1

    在 setting up development set and test set 这一章中 xff0c 作者提到了一个很重要的问题 训练集和测试集分布不一致导致的机器学习模型泛化能力有限 xff1a 在训练集上表现比较好 xff0c 但是
  • 图像畸变与去畸变

    本文主要介绍图像畸变产生的原因 xff0c 广角镜头的一般畸变模型和去畸变的方法 1 图像畸变 图像畸变是由于透镜制造精度以及组装工艺的偏差会引入畸变 xff0c 导致原始图像失真 镜头的畸变分为径向畸变和切向畸变两类 1 1 径向畸变与畸
  • Linux C编程问题:symbol lookup error: xxx undefined symbol xxx

    程序代码在编译的时候没问题 xff0c 但是在运行的时候报错 xff1a bin symbol lookup error bin undefined symbol xxx 百度了一下 xff0c 貌似是程序运行时使用的动态库和编译时make
  • Docker自动从Harbor下更新镜像

    JAVA开发Docker容器下自动更新镜像仓库的工具 前段时间在做一套分布式多租户系统 xff0c 它包括控制平台和应用服务器两部分 xff0c 应用服务器为企业客户服务 xff0c 系统会为每家企业建立一个应用服务器实例 xff0c 它存
  • C++中的exit函数

    描述 xff1a 用来立即中止当前程序的执行 xff0c 并将一个整数返回给系统 xff0c 该整数的作用与 由mian函数返回的整数 相同 xff0c 如果是0表示程序正常退出 xff1b 如果非0表示程序异常退出 头文件 span cl
  • 将uint8_t类型的16进制字符转化转换为string字符串

    碰到一个需求 xff0c 需要把硬件读到的uint8 t类型的16进制数据转化为string类型的字符串 例如 xff0c 如果读到到的数据是一个uint8 t类型的数组uint8 t code 61 5 61 0XAA 0X01 0XE3
  • C++解析json文件

    文章目录 1 JSON文件简介 1 1 1 JSON文件的语法规则1 2 JSON值的类型 2 JSON文件解析 1 JSON文件简介 1 一个项目在设计时会存在很多参数 xff0c 比如data文件路径 外设名称与相关参数 文件储存路径等
  • YOLO-YOLOV5算法原理及网络结构整理

    文章目录 零 参考链接一 前言1 1 YOLO vs Faster R CNN 二 YOLOv1 xff08 448 448 xff09 2 1实现方法2 2 损失函数2 3 leak RELU激活函数2 4总结 三 YOLOV23 1 Y
  • ubuntu 20.04.5安装python3.9缺少ffi.h文件问题

    ubuntu 20 04 5安装python3 9缺少ffi h文件问题 OK 解决
  • 视觉SLAM基础

    文章目录 零 参考链接一 视觉SLAM面试相关问题1 李群与李代数的映射关系2 李群与李代数的扰动模型3 SIFT与SURF特征的区别4 相似变换 仿射变换 射影变换的区别5 Homograph Essential Fundamental
  • 在ubuntu18.04系统上使用ROS跑ORB-SLAM3时遇到的问题总结

    1 跑TUM VI数据集dataset corridor4 512时 xff0c 从tum vi example sh中复制对应的运行命令 xff0c 输入命令后提示找不到对应的TUM 512 yaml文件 xff0c 查找对应路径发现只有
  • ubuntu1804系统安装Realsense SDK驱动和ROS Wrapper

    文章目录 1 软件安装1 1 安装realsense SDK1 2 安装Ros Wrapper 2 打开双目的开关3关闭结构光方法1 xff1a 通过可视窗口关闭方法2 xff1a 通过修改launch文件关闭 4查看相机参数 说明 xff
  • 在使用evo进行orb-slam2轨迹评估时提示时间戳没有对齐的问题

    最近使用一个orb slam2修改版跑euroc数据集 在使用evo评估绝对轨迹误差时出现下面的报错 found no matching timestamps between CameraTrajectory txt and gt MH01
  • ORB-SLAM2论文翻译

    文章转载至泡泡机器人 转载链接 链接 摘要 ORB SLAM2是基于单目 xff0c 双目和RGB D相机的一套完整的SLAM方案 它能够实现地图重用 xff0c 回环检测和重新定位的功能 无论是在室内的小型手持设备 xff0c 还是到工厂
  • ROS使用命令行查看图像消息的宽和高

    备忘 xff1a ROS在终端使用命令行查看图像消息的宽和高 span class token comment 查看图像的宽 span rostopic span class token builtin class name echo sp

随机推荐