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

2023-05-16

https://www.freertos.org/zh-cn-cmn-s/RTOS-stream-buffer-API.html

RTOS 流缓冲区
[API]

RTOS 流缓冲区 API 函数:

  • xStreamBufferCreate()
  • xStreamBufferCreateStatic()
  • xStreamBufferSend()
  • xStreamBufferSendFromISR()
  • xStreamBufferReceive()
  • xStreamBufferReceiveFromISR()
  • vStreamBufferDelete()
  • xStreamBufferBytesAvailable()
  • xStreamBufferSpacesAvailable()
  • xStreamBufferSetTriggerLevel()
  • xStreamBufferReset()
  • xStreamBufferIsEmpty()
  • xStreamBufferIsFull()

xStreamBufferCreate/xStreamBufferCreateWithCallback 
[RTOS 流缓冲区 API]


stream_buffer.h


StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes,
                                           size_t xTriggerLevelBytes );

StreamBufferHandle_t xStreamBufferCreateWithCallback( 
                         size_t xBufferSizeBytes,
                         size_t xTriggerLevelBytes
                         StreamBufferCallbackFunction_t pxSendCompletedCallback,
                         StreamBufferCallbackFunction_t pxReceiveCompletedCallback );
  

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

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

将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中即可启用流缓冲区功能。

参数:

xBufferSizeBytes

流缓冲区在任何时候能够容纳的总字节数。

xTriggerLevelBytes

在流缓冲区中被阻塞以等待数据的任务离开阻塞状态之前, 流缓冲区中必须包含的字节数。例如,如果一个任务在读取触发等级为 1 的空流缓冲区时被阻塞, 那么当单个字节写入缓冲区或该任务的阻塞时间结束时,该任务将被解除阻塞。 另一个例子是,如果一个任务在读取触发等级为 10 的空流缓冲区时被阻塞, 那么直到流缓冲区至少包含 10 个字节或该任务的阻塞时间结束之前,该任务将不会被解除阻塞。如果 读任务的阻塞时间在达到触发等级之前过期,那么该任务仍将接收实际可用的字节数 。将触发等级设置为 0 将导致使用触发等级 1。指定 一个大于缓冲区大小的触发等级是无效的。

pxSendCompletedCallback

当对流缓冲区的数据写入导致缓冲区的字节数超过触发等级时调用的回调函数 。如果参数为 NULL,则使用 sbSEND_COMPLETED 宏所提供的默认实现 。发送完成的回调函数必须具有 StreamBufferCallbackFunction_t 定义的原型,即:

void vSendCallbackFunction( StreamBufferHandle_t xStreamBuffer,
                            BaseType_t xIsInsideISR,
                            BaseType_t * const pxHigherPriorityTaskWoken );

pxReceiveCompletedCallback

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

void vReceiveCallbackFunction( StreamBufferHandle_t xStreamBuffer,
                               BaseType_t xIsInsideISR,
                               BaseType_t * const pxHigherPriorityTaskWoken );

Returns:

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

用法示例:

void vSendCallbackFunction( StreamBufferHandle_t xStreamBuffer,
                            BaseType_t xIsInsideISR,
                            BaseType_t * const pxHigherPriorityTaskWoken )
{
    /* Insert code here which is invoked when a data write operation
     * to the stream buffer causes the number of bytes in the buffer
     * to be more then the trigger level.
     * This is useful when a stream buffer is used to pass data 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
     * xStreamBufferSendCompletedFromISR() API function to check, and if
     * necessary unblock, a task that was waiting for the data. */
}

void vReceiveCallbackFunction( StreamBufferHandle_t xStreamBuffer,
                               BaseType_t xIsInsideISR,
                               BaseType_t * const pxHigherPriorityTaskWoken )
{
    /* Insert code here which is invoked when data is read from a stream
     * buffer.
     * This is useful when a stream buffer is used to pass data 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
     * xStreamBufferReceiveCompletedFromISR() API function to check, and if
     * necessary unblock, a task that was waiting to send the data. */
}

void vAFunction( void )
{
StreamBufferHandle_t xStreamBuffer, xStreamBufferWithCallback;
const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10;

    /* Create a stream 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 stream
     * buffer structure and the data in the stream buffer is
     * allocated dynamically. */
    xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes,
                                         xTriggerLevel );
    if( xStreamBuffer == NULL )
    {
        /* There was not enough heap memory space available to create the
        stream buffer. */
    }
    else
    {
        /* The stream buffer was created successfully and can now be used. */
    }
    
    /* Create a stream 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 stream buffer structure and the data
     * in the stream buffer is allocated dynamically. */
    xStreamBufferWithCallback = xStreamBufferCreateWithCallback( 
                                    xStreamBufferSizeBytes,
                                    xTriggerLevel,
                                    vSendCallbackFunction,
                                    vReceiveCallbackFunction );
    if( xStreamBufferWithCallback == NULL )
    {
        /* There was not enough heap memory space available to create the
         * stream buffer. */
    }
    else
    {
        /* The stream buffer was created successfully and can now be used. */
    }
}

xStreamBufferCreateStatic / xStreamBufferCreateStaticWithCallback
[RTOS 流缓冲区 API]


stream_buffer.h


StreamBufferHandle_t xStreamBufferCreateStatic(
                                    size_t xBufferSizeBytes,
                                    size_t xTriggerLevelBytes,
                                    uint8_t *pucStreamBufferStorageArea,
                                    StaticStreamBuffer_t *pxStaticStreamBuffer );

StreamBufferHandle_t xStreamBufferCreateStaticWithCallback(
                                    size_t xBufferSizeBytes,
                                    size_t xTriggerLevelBytes,
                                    uint8_t *pucStreamBufferStorageArea,
                                    StaticStreamBuffer_t *pxStaticStreamBuffer,
                                    StreamBufferCallbackFunction_t pxSendCompletedCallback,
                                    StreamBufferCallbackFunction_t pxReceiveCompletedCallback );
  

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

configSUPPORT_STATIC_ALLOCATION 必须在 FreeRTOSConfig.h 中设置为 1, xStreamBufferCreateStatic() 才可用。此外,configUSE_SB_COMPLETED_CALLBACK 必须在 FreeRTOSConfig.h 中设置为 1,xStreamBufferCreateStaticWithCallback() 才可用。

将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中即可启用流缓冲区功能。

参数:

xBufferSizeBytes

pucStreamBufferStorageArea 参数所指向的缓冲区的大小(单位:字节)。

xTriggerLevelBytes

在流缓冲区中被阻塞以等待数据的任务离开阻塞状态之前, 流缓冲区中必须存在的字节数。例如,如果一个任务在读取触发等级为 1 的空流缓冲区时被阻塞, 那么当单个字节写入缓冲区或该任务的阻塞时间结束时,该任务将被解除阻塞。 另一个例子是,如果一个任务在读取触发等级为 10 的空流缓冲区时被阻塞, 那么直到流缓冲区至少包含 10 个字节或该任务的阻塞时间结束之前,该任务将不会被解除阻塞。如果 读取任务的阻塞时间在达到触发等级之前过期,那么该任务仍将接收实际可用的字节数 。将触发等级设置为 0 将导致使用触发等级 1。指定 一个大于缓冲区大小的触发等级是无效的。

pucStreamBufferStorageArea

必须指向一个大小至少为 xBufferSizeBytes + 1 的 uint8_t 数组。这是一个数组,当将流写入流缓冲区时, 流会被复制到这个数组中。

pxStaticStreamBuffer

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

pxSendCompletedCallback

当对流缓冲区的数据写入导致缓冲区的字节数超过触发等级时调用的回调函数 。如果参数为 NULL,则使用 sbSEND_COMPLETED 宏所提供的默认实现 。发送完成的回调函数必须具有 StreamBufferCallbackFunction_t 定义的原型,即:

void vSendCallbackFunction( StreamBufferHandle_t xStreamBuffer,
                            BaseType_t xIsInsideISR,
                            BaseType_t * const pxHigherPriorityTaskWoken );

pxReceiveCompletedCallback

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

void vReceiveCallbackFunction( StreamBufferHandle_t xStreamBuffer,
                               BaseType_t xIsInsideISR,
                               BaseType_t * const pxHigherPriorityTaskWoken );

Returns:

如果成功创建了流缓冲区,那么将返回一个所创建流缓冲区的句柄。如果 pucStreamBufferStorageArea 或 pxStaticstreamBuffer 为 NULL,则返回 NULL。

用法示例:

/* Used to dimension the array used to hold the streams. 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 streams within the
 * stream buffer. */
static uint8_t ucStreamBufferStorage[ STORAGE_SIZE_BYTES ];
static uint8_t ucStreamBufferWithCallbackStorage[ STORAGE_SIZE_BYTES ];

/* The variable used to hold the stream buffer structure. */
StaticStreamBuffer_t xStreamBufferStruct;
StaticStreamBuffer_t xStreamBufferWithCallbackStruct;

void vSendCallbackFunction( StreamBufferHandle_t xStreamBuffer,
                            BaseType_t xIsInsideISR,
                            BaseType_t * const pxHigherPriorityTaskWoken )
{
    /* Insert code here which is invoked when a data write operation
     * to the stream buffer causes the number of bytes in the buffer
     * to be more then the trigger level.
     * This is useful when a stream buffer is used to pass data 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
     * xStreamBufferSendCompletedFromISR() API function to check, and if
     * necessary unblock, a task that was waiting for the data. */
}

void vReceiveCallbackFunction( StreamBufferHandle_t xStreamBuffer,
                               BaseType_t xIsInsideISR,
                               BaseType_t * const pxHigherPriorityTaskWoken )
{
    /* Insert code here which is invoked when data is read from a stream
     * buffer.
     * This is useful when a stream buffer is used to pass data 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
     * xStreamBufferReceiveCompletedFromISR() API function to check, and if
     * necessary unblock, a task that was waiting to send the data. */
}

void MyFunction( void )
{
StreamBufferHandle_t xStreamBuffer, xStreamBufferWithCallback;
const size_t xTriggerLevel = 1;

    /* Create a stream buffer that uses the functions defined
     * using the sbSEND_COMPLETED() and sbRECEIVE_COMPLETED()
     * macros as send and receive completed callback functions. */
    xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStreamBufferStorage ),
                                               xTriggerLevel,
                                               ucStreamBufferStorage,
                                               &xStreamBufferStruct );

    /* Create a stream buffer that uses the functions
     * vSendCallbackFunction and vReceiveCallbackFunction as send
     * and receive completed callback functions. */
    xStreamBufferWithCallback = xStreamBufferCreateStaticWithCallback(
                                    sizeof( ucStreamBufferWithCallbackStorage ),
                                    xTriggerLevel,
                                    ucStreamBufferWithCallbackStorage,
                                    &xStreamBufferWithCallbackStruct,
                                    vSendCallbackFunction,
                                    vReceiveCallbackFunction );

    /* As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer
     * parameters were NULL, xStreamBuffer and xStreamBufferWithCallback
     * will not be NULL, and can be used to reference the created stream
     * buffers in other stream buffer API calls. */
    
    /* Other code that uses the stream buffers can go here. */

xStreamBufferSend()
[ RTOS流缓冲区 API ]


stream_buffer.h


size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
                          const void *pvTxData,
                          size_t xDataLengthBytes,
                          TickType_t xTicksToWait );
  

将字节发送到流缓冲区。 字节复制到流缓冲区中。

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

使用 xStreamBufferSend() 从任务写入流缓冲区。 使用 xStreamBufferSendFromSISR () 从 中断服务程序 (ISR) 写入流缓冲区。

通过将 FreeRTOS/source/stream_buffer.c 源文件纳入构建中, 即可启用流缓冲区功能。

参数:

xStreamBuffer  作为流发送目标缓冲区的流缓冲区的句柄 。
pvTxData  一个指向缓冲区的指针, 该缓冲区用于保存要复制到流缓冲区的字节。
xDataLengthBytes 从 pvTxData 复制到流缓冲区的最大字节数 。
xTicksToWait  当流缓冲区的空间太小, 无法 容纳 另一个 xDataLengthBytes 的字节时,任务应保持在阻塞状态,以等待流缓冲区中出现足够空间的最长时间。 阻塞时间的单位为 tick 周期, 因此,它代表的绝对时间取决于 tick 频率。 宏 宏pdMS_TO_TICKS()可以用来将以毫秒为单位的时间 转换为以 tick 为单位的时间。 将xTicksToWait设置为portMAX_DELAY会 导致任务无限期地等待(没有超时),前提是 INCLUDE_vTaskSuspend 在 FreeRTOSConfig.h 中设置为 1。 如果一个任务 在向缓冲区写入所有 xDataLengthBytes 之前就超时, 它仍然会写入尽可能多的字节数。 处于阻塞状态的任务不会使用任何 CPU 时间 。

返回:

写入流缓冲区的字节数。 如果一个任务 在向缓冲区写入所有 xDataLengthBytes 之前就超时, 它仍然会写入尽可能多的字节数。


用法示例:


void vAFunction( StreamBufferHandle_t xStreamBuffer )
{
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 stream buffer, blocking for a maximum of 100ms to
    wait for enough space to be available in the stream buffer. */
    xBytesSent = xStreamBufferSend( xStreamBuffer,
                                   ( void * ) ucArrayToSend,
                                   sizeof( ucArrayToSend ),
                                   x100ms );

    if( xBytesSent != sizeof( ucArrayToSend ) )
    {
        /* The call to xStreamBufferSend() times out before there was enough
        space in the buffer for the data to be written, but it did
        successfully write xBytesSent bytes. */
    }

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

    if( xBytesSent != strlen( pcStringToSend ) )
    {
        /* The entire string could not be added to the stream buffer because
        there was not enough free space in the buffer, but xBytesSent bytes
        were sent.  Could try again to send the remaining bytes. */
    }
}  

xStreamBufferSendFromISR()
[ RTOS流缓冲区 API ]


stream_buffer.h


size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
                                 const void *pvTxData,
                                 size_t xDataLengthBytes,
                                 BaseType_t *pxHigherPriorityTaskWoken );
  

向 流缓冲区 发送字节流的中断安全版本 API 函数。

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

使用 xStreamBufferSend() 从任务写入流缓冲区。 使用 xStreamBufferSendFromSISR () 从 中断服务程序 (ISR) 写入流缓冲区。

通过将 FreeRTOS/source/stream_buffer.c 源文件纳入构建中, 即可启用流缓冲区功能。

参数:

xStreamBuffer  作为流发送目标缓冲区的流缓冲区的句柄 。
pvTxData  一个指向缓冲区的指针, 该缓冲区用于保存要复制到流缓冲区的字节。
xDataLengthBytes  从 pvTxData 复制到流缓冲区的最大字节数 。
pxHigherPriorityTaskWoken (这是一个可选参数,可以设置为 NULL。) 一个流缓冲区有可能会 有一个在其上阻塞的任务,以等待数据。 调用 xStreamBufferSendFromISR() 可以使数据可用,进而导致正在等待数据的任务 离开阻塞状态。 如果调用 xStreamBufferSendFromSISR() 导致任务离开阻塞状态,并且 未阻塞任务的优先级高于当前执行的任务( 被中断的任务),那么 xStreamBufferSendFromISR() 将在内部 把 *pxHigherPriorityTaskWoken 设置为 pdTRUE。 如果 xStreamBufferSendFromSISR() 将此值设置为 pdTRUE,那么通常应在 退出中断之前执行上下文切换。 这将 确保中断直接返回到最高优先级的“就绪” 状态任务。 * pxHigherPriorityTaskWoken在传递给函数之前 应将其设置为 pdFALSE。 有关示例,请参阅下面的示例代码。

Returns:

写入流缓冲区的字节数。 如果一个任务 在向缓冲区写入所有 xDataLengthBytes 之前就超时, 它仍然会写入尽可能多的字节数。


用法示例:


/* A stream buffer that has already been created. */
StreamBufferHandle_t xStreamBuffer;

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 stream buffer. */
    xBytesSent = xStreamBufferSendFromISR( xStreamBuffer,
                                           ( void * ) pcStringToSend,
                                           strlen( pcStringToSend ),
                                           &xHigherPriorityTaskWoken );

    if( xBytesSent != strlen( pcStringToSend ) )
    {
        /* There was not enough free space in the stream buffer for the entire
        string to be written, ut xBytesSent bytes were written. */
    }

    /* If xHigherPriorityTaskWoken was set to pdTRUE inside
    xStreamBufferSendFromISR() 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 );
}
  

xStreamBufferReceive()
[ RTOS流缓冲区 API ]


stream_buffer.h


size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
                             void *pvRxData,
                             size_t xBufferLengthBytes,
                             TickType_t xTicksToWait );
  

从流缓冲区接收字节。

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

使用 xStreamBufferReceive() 从任务的流缓冲区读取数据。 使用 xStreamBufferReceiveFromISR() 从 中断服务程序 (ISR) 的流缓冲区读取数据。

通过将 FreeRTOS/source/stream_buffer.c 源文件纳入构建中, 即可启用流缓冲区功能。

参数:

xStreamBuffer  要接收字节来自的流缓冲区的句柄。
pvRxData  指向缓冲区的指针,接收的字节将被复制到该缓冲区 。
xBufferLengthBytes pvRxData 参数 所指向的缓冲区的长度。 这会设置一次调用中 接收的最大字节数。 xStreamBufferReceive 将返回尽可能多的字节数, 直到达到由 xBufferLengthBytes 设置的最大字节数为止。
xTicksToWait  当流缓冲区为空时, 任务应保持在阻塞状态以等待数据的最长时间 。 如果 xTicksToWait 为 0,xStreamBufferReceive() 将立即返回。 阻塞时间的单位为 tick 周期, 因此,它代表的绝对时间取决于 tick 频率。 宏 pdMS_TO_TICKS() 可以 用来将以毫秒为单位的时间转换成以 tick 为单位的时间 。 将 xTicksToWait 设置为 portMAX_DELAY 将 将导致任务无限期等待(不超时),前提是 INCLUDE_vTaskSuspend 在 FreeRTOSConfig.h 中设置为 1。 处于阻塞状态的任务不会使用任何 CPU 时间 。

Returns:

从流缓冲区读取的字节数。 这将为最多等于 xBufferLengthBytes 的可用字节数。 例如:

  • 如果触发等级为 1 (触发等级是在创建流缓冲区时设置的)-
    • 如果 xBufferLengthBytes 为 10,且在调用 xStreamBufferReceive() 时,流缓冲区中包含 5 个字节,则 xStreamBufferReceive() 不会阻塞,从缓冲区中读取 5 个字节,并返回 5
    • 如果 xBufferLengthBytes 为 10,且在调用 xStreamBufferReceive() 时,流缓冲区中包含 50 个字节,则 xStreamBufferReceive() 不会阻塞,从缓冲区中读取 10 个字节,并返回 10。
    • 如果 xBufferLengthBytes 为 10,且在调用 xStreamBufferReceive() 时,流缓冲区中包含 0 个字节,xTicksToWait 为 100,并且在 50 个 tick 后缓冲区中收到 5 个字节,则 xStreamBufferReceive() 将进入为期 50 个 tick 的阻塞状态(直到数据到达缓冲区为止),之后它将从缓冲区中读取 5 个字节,并返回 5。
    • 如果 xBufferLengthBytes 为 10,且在调用 xStreamBufferReceive() 时,流缓冲区中包含 0 个字节,xTicksToWait 为 100,并且在 100 个 tick 内缓冲区中未收到字节,则 xStreamBufferReceive() 将进入为期 100 个 tick (完整阻塞时间)的阻塞状态,之后它将返回 0。

  • 如果触发等级为 6 -
    • 如果 xBufferLengthBytes 为 10,且在调用 xStreamBufferReceive() 时,流缓冲区中包含 0 个字节,xTicksToWait 为 100,并且在 50 个 tick 后缓冲区中收到 10 个字节,则 xStreamBufferReceive() 将进入为期 50 个 tick 的阻塞状态(直到至少有等于触发等级的字节数到达缓冲区为止),之后它将从缓冲区中读取 10 个字节,并返回 10。
    • 如果 xBufferLengthBytes 为 10,且在调用 xStreamBufferReceive() 时,流缓冲区中包含 0 个字节,xTicksToWait 为 100,并且在 50 个 tick 后缓冲区中收到 5 个字节,则 xStreamBufferReceive() 将在完整的 100 个 tick 阻塞周期内保持阻塞状态(因为缓冲区中的数据量永远无法达到触发等级),之后它将从缓冲区中读取 5 个字节,并返回 5。


用法示例:


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

    /* Receive up to another sizeof( ucRxData ) bytes from the stream buffer.
    Wait in the Blocked state (so not using any CPU processing time) for a
    maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be
    available. */
    xReceivedBytes = xStreamBufferReceive( xStreamBuffer,
                                           ( void * ) ucRxData,
                                           sizeof( ucRxData ),
                                           xBlockTime );

    if( xReceivedBytes > 0 )
    {
        /* A ucRxData contains another xRecievedBytes bytes of data, which can
        be processed here.... */
    }
}  

xStreamBufferReceiveFromISR()
[ RTOS流缓冲区 API ]


stream_buffer.h


size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
                                    void *pvRxData,
                                    size_t xBufferLengthBytes,
                                    BaseType_t *pxHigherPriorityTaskWoken );
  

一个从 流缓冲区中接收字节的 API 函数的中断安全版本。

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

使用 xStreamBufferReceive() 从任务的流缓冲区读取数据。 使用 xStreamBufferReceiveFromISR() 从 中断服务程序 (ISR) 的流缓冲区读取数据。

通过将 FreeRTOS/source/stream_buffer.c 源文件纳入构建中, 即可启用流缓冲区功能。

参数:

xStreamBuffer  要接收字节来自的流缓冲区的句柄。
pvRxData  指向缓冲区的指针,接收的字节将被复制到该缓冲区 。
xBufferLengthBytes  pvRxData 参数 所指向的缓冲区的长度。 这会设置一次调用中 接收的最大字节数。 xStreamBufferReceive 将返回尽可能多的字节数, 直到达到由 xBufferLengthBytes 设置的最大字节数为止。
pxHigherPriorityTaskWoken (这是一个可选参数,可以设置为 NULL。) 一个流缓冲区有可能会 有一个任务阻塞在上面,等待空间可用。 调用 xStreamBufferReceiveFromISR() 可以使空间可用,进而导致正在等待空间的任务 离开阻塞状态。 如果调用 xStreamBufferReceiveFromISR() 导致任务离开阻塞状态,并且 未阻塞任务的优先级高于当前执行的任务 (被中断的任务),那么在内部, xStreamBufferReceiveFromISR() 将把 *pxHigherPriorityTaskWoken 设置为 pdTRUE。 如果 xStreamBufferSendFromSISR() 将此值设置为 pdTRUE,那么通常应在 退出中断之前执行上下文切换。 这将 确保中断直接返回到最高优先级的就绪状态 任务。 * pxHigherPriorityTaskWoken在传递给函数之前 应该设置为pdFALSE。 有关示例,请参阅下面的示例代码。

Returns:

从流缓冲区读取的字节数(如有)。


用法示例:


/* A stream buffer that has already been created. */
StreamBuffer_t xStreamBuffer;

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

    /* Receive the next stream from the stream buffer. */
    xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer,
                                                  ( void * ) ucRxData,
                                                  sizeof( ucRxData ),
                                                  &xHigherPriorityTaskWoken );

    if( xReceivedBytes > 0 )
    {
        /* ucRxData contains xReceivedBytes read from the stream buffer.
        Process the stream here.... */
    }

    /* If xHigherPriorityTaskWoken was set to pdTRUE inside
    xStreamBufferReceiveFromISR() 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 );
}
  

vStreamBufferDelete()
[ RTOS流缓冲区 API ]


stream_buffer.h


void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
  

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

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

将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中, 即可启用流缓冲区功能。

参数:

xStreamBuffer  要删除的流缓冲区的句柄。

xStreamBufferBytesAvailable()
[ RTOS流缓冲区 API ]


stream_buffer.h


size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
  

查询流缓冲区以查看它包含多少数据, 该值等于在流缓冲区为空之前 可以从流缓冲区读取的字节数。

将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中 即可启用流缓冲区功能。

参数:

xStreamBuffer  正在查询的流缓冲区的句柄。

Returns:

在流缓冲区为空之前可从流缓冲区读取的 字节数。

xStreamBufferSpacesAvailable()
[ RTOS 流缓冲区 API ]


stream_buffer.h


size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
  

查询流缓冲区以查看有多少可用空间—— 等于在流缓冲区满之前可以向它发送的数据量 。

通过将 FreeRTOS/source/stream_buffer.c 源文件纳入构建中, 即可启用流缓冲区功能。

参数:

xStreamBuffer  正在被查询的流缓冲区的句柄。

Returns:

在流缓冲区满之前, 可以写入流缓冲区的字节数。

xStreamBufferSetTriggerLevel()
[RTOS 流缓冲区 API]


stream_buffer.h


BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
                                         size_t xTriggerLevel );
  

流缓冲区的触发等级是指在流缓冲区上被阻塞以等待数据的任务离开阻塞状态之前,流缓冲区中必须包含的字节数。例如,如果一个任务在读取触发等级为 1 的空流缓冲区时被阻塞,那么当单个字节写入缓冲区或该任务的阻塞时间到期时,该任务将被解除阻塞。另一个示例是,如果一个任务在读取触发等级为 10 的空流缓冲区时被阻塞,那么直到流缓冲区至少包含 10 个字节或该任务的阻塞时间结束,该任务才会被解除阻塞。如果读任务的阻塞时间在达到触发等级之前过期,那么该任务仍将接收实际可用的字节数。将触发等级设置为 0 将导致使用触发等级 1。指定大于缓冲区大小的触发等级是无效的。

触发等级在创建流缓冲区时设置,可使用 xStreamBufferSetTriggerLevel() 进行修改。

将 FreeRTOS/source/stream_buffer.c 源文件包含在构建中即可启用流缓冲区功能。

参数:

xStreamBuffer  正在更新的流缓冲区的句柄。
xTriggerLevel  流缓冲区的新触发等级。

Returns:

如果 xTriggerLevel 小于或等于流缓冲区的长度,将更新触发等级并返回 pdTRUE。否则,返回 pdFALSE。

xStreamBufferReset()
[ RTOS流缓冲区 API ]


stream_buffer.h


BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
  

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

通过将 FreeRTOS/source/stream_buffer.c 源文件纳入构建中, 即可启用流缓冲区功能。

参数:

xStreamBuffer  正在重置的流缓冲区的句柄。

Returns:

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

xStreamBufferIsEmpty()
[ RTOS流缓冲区 API ]


stream_buffer.h


BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
  

查询流缓冲区以查看其是否为空。 如果流缓冲区不包含任何数据,则为空。

通过将源文件 FreeRTOS/source/stream_buffer.c包括在内,启用流缓冲区功能 即可启用流缓冲区功能。

参数:

xStreamBuffer  正在查询的流缓冲区的句柄。

返回:

如果流缓冲区为空,则返回 pdTRUE。 否则 返回 pdFALSE。

xStreamBufferIsFull()
[ RTOS流缓冲区 API ]


stream_buffer.h


BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
  

查询流缓冲区以查看其是否已满。 如果一个流缓冲区没有任何可用空间,则该流缓冲区已满,因此无法 接受任何更多数据。

通过将 FreeRTOS/source/stream_buffer.c 源文件纳入构建中, 即可启用流缓冲区功能。

参数:

xStreamBuffer  正在被查询的流缓冲区的句柄。

Returns:

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

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

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

  • Z变换零点极点

    在Z变换里 xff0c 零点的位置表示系统的 谷 xff0c 极点的位置表示系统的 峰 xff0c 我们把有峰的地方看做信号可以通过的地方 xff0c 而有谷的地方看做信号被截止的地方 并且我们选择单位圆为频域的一个周期 xff0c 那么可
  • 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 还是到工厂

随机推荐