while (true)
{
size_t chunk_length = xStreamBufferSend(stream->_handle, buffer, length, portMAX_DELAY);
bytes_written += chunk_length;
length -= chunk_length;
if (length == 0)
{
break;
}
buffer = (uint8_t *) buffer + chunk_length;
}
return bytes_written;
}
“`
Thank you. Cheers, Pavel
Behavior of xStreamBufferSend / xStreamBufferReceive
Hi,
I am not 100% sure how xStreamBufferSend / xStreamBufferReceive works. Is it safe to assume that xDataLengthBytes are guaranteed to be sent / received when portMAX_DELAY is specified when the call is finished?
If that is the case, then the following wrapper is not necessary. Is that corret?
“`c
sizet osstreamwrite(osstreamt *stream, const void *buffer, sizet length)
{
sizet byteswritten = 0;
Behavior of xStreamBufferSend / xStreamBufferReceive
I am not 100% sure how xStreamBufferSend / xStreamBufferReceive works. Is it safe to assume that xDataLengthBytes are guaranteed to be sent / received when portMAX_DELAY is specified when the call is finished?You have all the source code, and xStreamBufferSend() is a small function to read. Lines 520 and 549 (at the time of writing) show a loop with the task waiting under the required amount of space is available: https://sourceforge.net/p/freertos/code/HEAD/tree/trunk/FreeRTOS/Source/stream_buffer.c
Behavior of xStreamBufferSend / xStreamBufferReceive
Hi Richard, thank you!
Apparently xStreamBufferSend handles that for you inside the do { } while loop, so no wrapper is necessary there.
With xStreamBufferReceive, the situation is different though… the call can return without having the desired length available under normal circumstances (as task can get notified from various reasons) – even if portMAX_DELAY has been specified.
This is the wrapper (with timeout support) I have been using for reference (feedback is welcome):
“`c
sizet osstreamtimedread(osstreamt *stream, void *buffer, size_t length, uint32_t milliseconds)
{
if (milliseconds == 0)
{
return xStreamBufferReceive(stream->_handle, buffer, length, 0);
}
size_t bytes_read = 0;
uint64_t now = os_time_get();
uint64_t timeout = now + milliseconds;
while (now < timeout)
{
size_t chunk_length = xStreamBufferReceive(stream->_handle, buffer, length, pdMS_TO_TICKS(timeout - now));
bytes_read += chunk_length;
length -= chunk_length;
if (length == 0)
{
break;
}
buffer = (uint8_t *) buffer + chunk_length;
now = os_time_get();
}
return bytes_read;
}
“`
Thank you. Cheers, Pavel
Behavior of xStreamBufferSend / xStreamBufferReceive
Correct, in xStreamBufferReceive() the second parameter is the size of
the buffer into which data is to be copied, not the number of bytes to
receive, so xSteamBufferRecevie() will return as soon as it has ‘some’
data, the length of the data it receives in one go being capped to the
buffer length. See the xBufferLengthBytes description here:
https://www.freertos.org/xStreamBufferReceive.html
Ref your implementation of osstreamtimedread() – from a brief look it
seems you have have an issue if the tick count overflows, the likelihood
of which you have avoided by using a uint64t – access to which will
probably not be atomic. It may be easier to use code similar to that
shown on this page: https://www.freertos.org/xTaskCheckForTimeOut.html
which uses FreeRTOS API calls to take possible overflows into account
for you.
Behavior of xStreamBufferSend / xStreamBufferReceive
Thank you, Richard. I was not aware of the xTaskCheckForTimeout function and I will look into it.
You are correct – I use uint64_t for my application ticks as it will “never” overflow… 🙂
However, I have been trying to make the access to this variable safe. Here is the snippet including the vApplicationTickHook callback implementation:
“`c
static uint64t _ostime = 0;
uint64t ostimeget(void)
{
taskENTERCRITICAL();
uint64_t ret = _os_time;
taskEXIT_CRITICAL();
return ret;
}
void vApplicationTickHook(void)
{
static TickType_t xTickLast = 0;
TickType_t xTickNow = xTaskGetTickCountFromISR();
_os_time += xTickNow - xTickLast;
xTickLast = xTickNow;
}
“`
I hope this is sufficient for safe tick counter operation.
Thanks! Regards, Pavel