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。