Chapter 16 of FreeRTOS: Stream Buffer

Table of Contents

    • 1. Core Concepts of Stream Buffer
      • 1.1 Design Purpose
      • 1.2 Key Features
    • 2. Practical Implementation of Efficient Data Stream Transmission
      • 2.1 Serial Data Transmission and Reception Example
      • 2.2 Performance Optimization Techniques
    • 3. In-depth Comparison with Queues
    • 4. Quick Reference for Key APIs
    • 5. Best Practice Recommendations

Chapter 16 of FreeRTOS: Stream Buffer

1. Core Concepts of Stream Buffer

1.1 Design Purpose

  • Optimized for continuous data stream transmission (e.g., UART, SPI data)
  • Lock-free model for single-task writing/single-task reading
  • More memory-efficient than queues (no separate storage units)

1.2 Key Features

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

size_txStreamBufferReceive(StreamBufferHandle_t xStreamBuffer,
void* pvRxData,
size_t xBufferSizeBytes,
                           TickType_t xTicksToWait);
  • Byte-level read and write (queues are message-level)
  • Dynamic blocking trigger (tasks automatically suspend when empty/full)
  • Supports triggered wake-up (via <span>xStreamBufferSendCompletedFromISR()</span>)

2. Practical Implementation of Efficient Data Stream Transmission

2.1 Serial Data Transmission and Reception Example

// Create stream buffer (recommended size is 3 times the hardware buffer)
StreamBufferHandle_t xUartStream = xStreamBufferCreate(1024, 1);

// Sending task
void vUartSendTask(void* pv) {
    uint8_t txData[128];
    while (1) {
        size_t sent = xStreamBufferSend(xUartStream, txData, sizeof(txData), portMAX_DELAY);
        HAL_UART_Transmit(&huart1, txData, sent, 100);
    }
}

// Reception interrupt callback
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    uint8_t rxByte;
    xStreamBufferSendFromISR(xUartStream, &rxByte, 1, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

2.2 Performance Optimization Techniques

  1. Circular buffer design: Memory reuse, avoiding frequent allocations
  2. Single producer-single consumer model: Eliminates mutex overhead
  3. Trigger threshold settings: <span>xTriggerLevelBytes</span> controls wake-up timing

3. In-depth Comparison with Queues

Feature Stream Buffer Queue
Data Unit Byte stream Fixed-size message
Storage Efficiency High (contiguous storage) Low (each message requires metadata)
Applicable Scenarios Streaming data (UART/ADC) Discrete events (commands/status)
Multi-task Safety Requires external synchronization Built-in mutex mechanism
Memory Usage O(1) fixed overhead O(n) additional 8 bytes per message
ISR Support Dedicated API (FromISR) General FromISR API

4. Quick Reference for Key APIs

API Description Typical Use Case
<span>xStreamBufferCreate()</span> Create dynamic buffer During system initialization
<span>xStreamBufferSend()</span> Blocking write Task sending data
<span>xStreamBufferReceive()</span> Blocking read Task processing data
<span>xStreamBufferReset()</span> Clear buffer Recover from communication errors
<span>xStreamBufferSpacesAvailable()</span> Query remaining space Flow control

5. Best Practice Recommendations

  1. Size Calculation: <span>Buffer size = Maximum burst data volume × 2 + Safety margin</span>
  2. Timeout Settings: Avoid permanent blocking (recommended 100-500ms)
  3. Error Handling: Check return values (actual transmitted byte count may be less than requested)
  4. ISR Usage: Prefer using <span>...FromISR()</span> versions and handle task switching

Leave a Comment