ACFly用到了Steam Buffers,特地调了3个最常见的API查了一下,其他的API都和这些差不多。
Steam Buffers 是最近几版本Freertos出现的数据结构。
xStreamBufferCreate:
官网解释:
StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );
@param xBufferSizeBytes
The total number of bytes the stream buffer will be
able to hold at any one time.
@param xTriggerLevelBytes
The number of bytes that must be in the stream buffer before a task that is blocked on the stream buffer to wait for data is moved out of the blocked state. For example, if a task is blocked on a read of an empty stream buffer that has a trigger level of 1 then the task will be unblocked when a single byte is written to the buffer or the task's block time expires. As another example, if a task is blocked on a read of an empty stream buffer that has a trigger level of 10 then the task will not be unblocked until the stream buffer contains at least 10 bytes or the task's block time expires. If a reading task's block time expires before the trigger level is reached then the task will still receive however many bytes are actually available. Setting a trigger level of 0 will result in a trigger level of 1 being used. It is not valid to specify a trigger level that is greater than the buffer size.
@return If NULL is returned, then the stream buffer cannot be created because there is insufficient heap memory available for FreeRTOS to allocate the stream buffer data structures and storage area. A non-NULL value being returned indicates that the stream buffer has been created successfully the returned value should be stored as the handle to the created stream buffer.
@param xBufferSizeBytes
流缓冲区的总字节数
任何时候都能保持。
@param xTriggerLevelBytes
在流缓冲区上阻塞的任务等待数据移出阻塞状态之前,流缓冲区中必须包含的字节数。例如,如果一个任务在读取一个触发器级别为1的空流缓冲区时被阻塞,那么当一个字节被写入缓冲区或任务的阻塞时间到期时,该任务将被解除阻塞。另一个例子是,如果一个任务在读取一个触发级别为10的空流缓冲区时被阻塞,那么该任务将不会被解除阻塞,直到流缓冲区包含至少10个字节或任务的阻塞时间到期。如果一个读任务的阻塞时间在达到触发器级别之前过期,那么该任务仍然会收到实际可用的字节。将触发器级别设置为0将导致使用触发器级别为1。指定大于缓冲区大小的触发器级别是无效的。
@return
如果返回NULL,则无法创建流缓冲区,因为没有足够的堆内存可供FreeRTOS分配流缓冲区数据结构和存储区域。返回的非null值表明流缓冲区已成功创建,返回值应存储为创建的流缓冲区的句柄。
就是比如当xTriggerLevelBytes为1的时候,任务读取流缓冲区数据,除非流缓冲区有一个字节,否则任务将会被阻塞,当一个字节被写入缓冲区或任务的阻塞时间到期时,该任务将被解除阻塞。
xStreamBufferSend():
官网解释:
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData,
size_t xDataLengthBytes,
TickType_t xTicksToWait );
Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
NOTE: Uniquely among FreeRTOS objects, the stream buffer implementation (so also the message buffer implementation, as message buffers are built on top of stream buffers) assumes there is only one task or interrupt that will write to the buffer (the writer), and only one task or interrupt that will read from the buffer (the reader). It is safe for the writer and reader to be different tasks or interrupts, but, unlike other FreeRTOS objects, it is not safe to have multiple different writers or multiple different readers. If there are to be multiple different writers then the application writer must place each call to a writing API function (such as xStreamBufferSend()) inside a critical section and use a send block time of 0. Likewise, if there are to be multiple different readers then the application writer must place each call to a reading API function (such as xStreamBufferReceive()) inside a critical section and use a receive block time of 0.
Use xStreamBufferSend() to write to a stream buffer from a task. Use xStreamBufferSendFromISR() to write to a stream buffer from an interrupt service routine (ISR).
Stream buffer functionality is enabled by including the FreeRTOS/source/stream_buffer.c source file in the build.
Parameters:
xStreamBuffer The handle of the stream buffer to which a stream is being sent.
pvTxData A pointer to the buffer that holds the bytes to be copied into the stream buffer.
xDataLengthBytes The maximum number of bytes to copy from pvTxData into the stream buffer.
xTicksToWait The maximum amount of time the task should remain in the Blocked state to wait for enough space to become available in the stream buffer, should the stream buffer contain too little space to hold the another xDataLengthBytes bytes. The block time is specified in tick periods, so the absolute time it represents is dependent on the tick frequency. The macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will cause the task to wait indefinitely (without timing out), provided INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. If a task times out before it can write all xDataLengthBytes into the buffer it will still write as many bytes as possible. A task does not use any CPU time when it is in the blocked state.
Returns:
The number of bytes written to the stream buffer. If a task times out before it can write all xDataLengthBytes into the buffer it will still write as many bytes as possible.
注意:流缓冲区实现的假定只有一个任务或中断,将写入缓冲区(作者),且只有一个任务或中断,将从缓冲区读取(读者)。编写器和读取器作为不同的任务或中断是安全的,但是,与其他FreeRTOS对象不同的是,拥有多个不同的编写器或多个不同的读取器是不安全的。如果有多个不同的写入器,那么应用程序写入器必须将每个对写入API函数(如xStreamBufferSend())的调用放在一个临界区中,并使用发送阻塞时间为0。同样地,如果有多个不同的读取器,那么应用程序编写器必须将对读取API函数(如xStreamBufferReceive())的每个调用放置在关键区域内,并使用0的接收阻塞时间。
也就是流缓冲区的设计主要是针对单任务写入单任务读取的,对于多任务写入器和多任务读取器,必须将阻塞时间设为0。
参数:
@param xStreamBuffer 流被发送到的流缓冲区的句柄。
@param pvTxData 一个指向缓冲区的指针,该缓冲区保存要复制到流缓冲区中的字节。
@param xDataLengthBytes 从pvTxData复制到流缓冲区的最大字节数。
@param xTicksToWait 任务保持阻塞状态以等待流缓冲区中有足够的可用空间的最大时间,如果流缓冲区包含的空间太少,不能容纳另一个xDataLengthBytes字节。块时间是在滴答周期中指定的,所以它表示的绝对时间依赖于滴答频率。宏pdMS_TO_TICKS()可用于将以毫秒为单位指定的时间转换为以滴答为单位指定的时间。设置xTicksToWait为portMAX_DELAY将导致任务无限期等待(没有超时),前提是在FreeRTOSConfig.h中将INCLUDE_vTaskSuspend设置为1。如果任务在将所有xDataLengthBytes写入缓冲区之前超时,它仍将尽可能多地写入字节。当一个任务处于阻塞状态时,它不会占用任何CPU时间。
@return 写入流缓冲区的字节数。如果任务在将所有xDataLengthBytes写入缓冲区之前超时,它仍将尽可能多地写入字节。
xStreamBufferReceive()
官网解释:
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
void *pvRxData,
size_t xBufferLengthBytes,
TickType_t xTicksToWait );
Receives bytes from a stream buffer.
NOTE: Uniquely among FreeRTOS objects, the stream buffer implementation (so also the message buffer implementation, as message buffers are built on top of stream buffers) assumes there is only one task or interrupt that will write to the buffer (the writer), and only one task or interrupt that will read from the buffer (the reader). It is safe for the writer and reader to be different tasks or interrupts, but, unlike other FreeRTOS objects, it is not safe to have multiple different writers or multiple different readers. If there are to be multiple different writers then the application writer must place each call to a writing API function (such as xStreamBufferSend()) inside a critical section and use a send block time of 0. Likewise, if there are to be multiple different readers then the application writer must place each call to a reading API function (such as xStreamBufferReceive()) inside a critical section and use a receive block time of 0.
Use xStreamBufferReceive() to read from a stream buffer from a task. Use xStreamBufferReceiveFromISR() to read from a stream buffer from an interrupt service routine (ISR).
Stream buffer functionality is enabled by including the FreeRTOS/source/stream_buffer.c source file in the build.
Parameters:
xStreamBuffer | The handle of the stream buffer from which bytes are to be received. |
pvRxData | A pointer to the buffer into which the received bytes will be copied. |
xBufferLengthBytes | The length of the buffer pointed to by the pvRxData parameter. This sets the maximum number of bytes to receive in one call. xStreamBufferReceive will return as many bytes as possible up to a maximum set by xBufferLengthBytes. |
xTicksToWait | The maximum amount of time the task should remain in the Blocked state to wait for data to become available if the stream buffer is empty. xStreamBufferReceive() will return immediately if xTicksToWait is zero. The block time is specified in tick periods, so the absolute time it represents is dependent on the tick frequency. The macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will cause the task to wait indefinitely (without timing out), provided INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. A task does not use any CPU time when it is in the Blocked state. |
Returns:
The number of bytes read from the stream buffer. This will be the number of bytes available up to a maximum of xBufferLengthBytes. For example:
- If the trigger level is 1 (the trigger level is set when the stream buffer is created) -
- If xBufferLengthBytes is 10 and the stream buffer contains 5 bytes when xStreamBufferReceive() is called - then xStreamBufferReceive() will not block, read 5 bytes from the buffer, and return 5.
- If xBufferLengthBytes is 10 and the stream buffer contains 50 bytes when xStreamBufferReceive() is called - then xStreamBufferReceive() will not block, read 10 bytes from the buffer, and return 10.
- If xBufferLengthBytes is 10, the stream buffer contains 0 bytes when xStreamBufferReceive() is called, xTicksToWait is 100, and 5 bytes are received into the buffer after 50 ticks - then xStreamBufferReceive() will enter the blocked state for 50 ticks (which is until data arrives in the buffer), after which it will read 5 bytes from the buffer, and return 5.
- If xBufferLengthBytes is 10, the stream buffer contains 0 bytes when xStreamBufferReceive() is called, xTicksToWait is 100, and no bytes are received into the buffer within 100 ticks - then xStreamBufferReceive() will enter the blocked state for the full block time of 100 ticks, after which it will return 0.
- If the trigger level is 6 -
- If xBufferLengthBytes is 10, the stream buffer contains 0 bytes when xStreamBufferReceive() is called, xTicksToWait is 100, and 10 bytes are received into the buffer after 50 ticks - then xStreamBufferReceive() will enter the blocked state for 50 ticks (which is until at least the trigger level number of bytes arrives in the buffer), after which it will read 10 bytes from the buffer, and return 10.
- If xBufferLengthBytes is 10, the stream buffer contains 0 bytes when xStreamBufferReceive() is called, xTicksToWait is 100, and 5 bytes are received into the buffer after 50 ticks - then xStreamBufferReceive() will remain blocked for the entire 100 tick block period (because the amount of data in the buffer never reached the trigger level), after which it will read 5 bytes from the buffer, and return 5.
- 从流缓冲区接收字节。
参数:
@param xStreamBuffer 从其中接收字节的流缓冲区句柄。
@param pvRxData 一个指向缓冲区的指针,接收到的字节将被复制到该缓冲区中。
@param xBufferLengthBytes pvRxData 参数所指向的缓冲区长度。这将设置在一个调用中接收的最大字节数。xStreamBufferReceive将返回尽可能多的字节,直到xBufferLengthBytes设置的最大字节。
@param xTicksToWait 当流缓冲区为空时,任务保持阻塞状态以等待数据可用的最大时间。如果xTicksToWait 为零,xStreamBufferReceive()将立即返回。块时间是在滴答周期中指定的,所以它表示的绝对时间依赖于滴答频率。宏pdMS_TO_TICKS()可用于将以毫秒为单位指定的时间转换为以滴答为单位指定的时间。设置xTicksToWait为portMAX_DELAY将导致任务无限期等待(没有超时),前提是在FreeRTOSConfig.h中将INCLUDE_vTaskSuspend设置为1。任务在Blocked状态下不占用CPU时间。
返回:
从流缓冲区读取的字节数。这将是xBufferLengthBytes的最大可用字节数。
官网上举例很清楚:
如果触发级别为1(创建流缓冲区时设置触发级别)
如果xBufferLengthBytes是10并且当xStreamBufferReceive()被调用时,流缓冲区包含5个字节,那么xStreamBufferReceive()将不会阻塞,从缓冲区读取5个字节,并返回5。
如果xBufferLengthBytes是10并且当xStreamBufferReceive()被调用时,流缓冲区包含50字节,那么xStreamBufferReceive()将不会阻塞,从缓冲区读取10个字节,并返回10。
如果xBufferLengthBytes是10,流缓冲区包含0字节当xStreamBufferReceive (), xTicksToWait是100,和5字节接收到缓冲后50Ticks,然后xStreamBufferReceive()将进入阻塞状态50Ticks直到数据到达缓冲区),之后,它将从缓冲区读取5个字节,并返回5。
如果xBufferLengthBytes是10,流缓冲区包含0字节当xStreamBufferReceive (), xTicksToWait是100,和100节拍内没有收到字节缓冲区,那么xStreamBufferReceive()将进入阻塞状态的完整的阻塞时间100个时钟节拍,之后,它将返回0。
如果触发级别为6
如果xBufferLengthBytes是10,流缓冲区包含0字节当xStreamBufferReceive (), xTicksToWait是100,和在50个Ticks后收到10个字节缓冲区,那么xStreamBufferReceive()将进入阻塞状态50Ticks(至少到触发水平到达缓冲区的字节数),之后,它将从缓冲区中读取10个字节,并返回10。
如果xBufferLengthBytes是10,流缓冲区包含0字节当xStreamBufferReceive (), xTicksToWait是100,和在50个Ticks后只收到5个字节缓冲区,那么xStreamBufferReceive()将继续封锁整个100Ticks(因为在缓冲的数据量没有达到触发水平),之后,它将从缓冲区中读取5个字节,并返回5。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)