23-RTOS 消息缓冲区 API 函数

1- xMessageBufferCreate / xMessageBufferCreateWithCallback

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 源文件包含在构建中即可启用消息缓冲区功能 (因为消息缓冲区使用流缓冲区)。

1.1参数:

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 );

1.2Returns:

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

1.3用法示例:

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. */
    }
}

2 xMessageBufferCreateStatic / xMessageBufferCreateStaticWithCallback

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 源文件包含在构建中即可启用消息缓冲区功能 (因为消息缓冲区使用流缓冲区)。

2.2 参数:

xBufferSizeBytespucMessageBufferStorageArea 参数所指向的缓冲区的大小(单位:字节)。当消息写入消息缓冲区时, 同时也会写入额外的 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 定义的原型,即: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 );

2.3 Returns:

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

2.4 用法示例:

/* 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. */
}

3- xMessageBufferSend()

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 源文件 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

3.1 参数:

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 时间。

3.2 Returns:

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

3.3 用法示例:

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. */
    }
}

4 xMessageBufferSendFromISR()

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 源文件 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

4.1参数:

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。 有关示例,请参阅下面的代码示例。

4.2Returns:

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

4.3用法示例:

/* 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 );
}

5- xMessageBufferReceive()

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 源文件包含在构建中 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

5.1参数:

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时间。

5.2 Returns:

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

5.3 用法示例:

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.... */
    }
}

6- xMessageBufferReceiveFromISR()

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 源文件包含在构建中 来启用消息缓冲区功能(因为消息缓冲区使用流缓冲区)。

6.1 参数:

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

6.2 Returns:

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

6.3 用法示例:

/* 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 );
}

7- vMessageBufferDelete()

message_buffer.h

void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );

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

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

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

7.1 参数:

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

8-xMessageBufferSpacesAvailable()

message_buffer.h

size_t xMessageBufferSpacesAvailable( MessageBufferHandle_t xMessageBuffer );

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

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

8.1 参数:

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

8.2 Returns:

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

9- xMessageBufferReset()

message_buffer.h

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

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

9.1 参数:

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

9.2 Returns:

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

10- xMessageBufferIsEmpty()

message_buffer.h

BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer );

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

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

10.1 参数:

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

10.2 Returns:

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

11- xMessageBufferIsFull()

message_buffer.h

BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer );

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

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

11.1 参数:

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

11.2 Returns:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山府嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值