xStreamBufferReceive API reference errors

Hi,

In the FreeRTOS API page for xStreamBufferReceive, there is contradictory / misleading / erroneous information which tripped me up for a while. Can these errors be corrected?

It is regarding the number of bytes that will be received.

Reading the “Parameters” section, xBufferLengthBytes is “maximum number of bytes to receive in one call” and xTicksToWait will “wait for data to become available if the stream buffer is empty.” This is all good. The function returns the moment that even a single byte is in the StreamBuffer. If xBufferLengthBytes is 10 bytes and 1 byte is currently available, it will immediately return, it will not wait. xBufferLengthBytes is not the amount of data being requested, it is the maximum data that can be received.

However, reading the “Returns” section, it states “The number of bytes actually read from the stream buffer, which will be less than xBufferLengthBytes if the call to xStreamBufferReceive() timed out before xBufferLengthBytes were available.” While this is not untrue, it is incomplete and misleading, as often it will be less than xBufferLengthBytes even if it does NOT time out.

Also, reading the “Example Usage” section, there is a comment “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.” This is explicitly wrong, as it will NOT wait for the FULL number of bytes to become available. It could return sooner even if only 1 byte is available.

Please let me know if anything I’ve said here is mistaken, otherwise hopefully the API page can be fixed, thanks!

Is the Trigger Level correctly set? Because if it is set to 1, it explains the behavior you described.

The return value documentation does sound wrong. I will ensure it gets updated although you won’t see the update until the website is next deployed. Thanks for reporting.

Here the streams work like a Berkeley socket stream recv function - in practical situations the length parameter is the length of the buffer into which data is copied, so specifies the maximum number of bytes to read, not the number of bytes to wait for.

I propose updating the text for the return value to:


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 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(), xTicksToWait is 100, and 5 bytes are received into the buffer after 50 ticks then xStreamBufferReceive() will enter the blocked state for 50 ticks, 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(), 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.

@rtel , your examples don’t mention the trigger level, which is set when you create a stream buffer using xStreamBufferCreate(), or later with xStreamBufferSetTriggerLevel().

The current documentation of xStreamBufferReceive() is:

The number of bytes actually read from the stream buffer, which will be less than xBufferLengthBytes if the call to xStreamBufferReceive() timed out before xBufferLengthBytes were available.

I think it should be changed to:

The number of bytes actually read from the stream buffer, which will be less than xBufferLengthBytes if the call to xStreamBufferReceive() timed out before xTriggerLevelBytes were available.

I’m not an expert of FreeRTOS, and I don’t have experience with stream buffers, but this is what I understand from the API documentation. Am I missing something?

Right. Will take another look tomorrow - late here now.

Agreed, the Trigger Level should have an impact… mine was 1. If I set it to a high value, then it should wait. I haven’t experimented yet. So fixed documentation likely will need to refer to this value which is set when the stream buffer is created.

Update to mention the trigger level:


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.