Better support for task blocking ring buffer reads and writes (#7390)

This commit is contained in:
Kevin Ahrendt 2024-09-02 20:47:54 -04:00 committed by GitHub
parent d6eeac0619
commit f8ec5242c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 69 additions and 2 deletions

View file

@ -20,13 +20,20 @@ std::unique_ptr<RingBuffer> RingBuffer::create(size_t len) {
return nullptr;
}
rb->handle_ = xStreamBufferCreateStatic(len + 1, 0, rb->storage_, &rb->structure_);
rb->handle_ = xStreamBufferCreateStatic(len + 1, 1, rb->storage_, &rb->structure_);
ESP_LOGD(TAG, "Created ring buffer with size %u", len);
return rb;
}
size_t RingBuffer::read(void *data, size_t len, TickType_t ticks_to_wait) {
return xStreamBufferReceive(this->handle_, data, len, ticks_to_wait);
if (ticks_to_wait > 0)
xStreamBufferSetTriggerLevel(this->handle_, len);
size_t bytes_read = xStreamBufferReceive(this->handle_, data, len, ticks_to_wait);
xStreamBufferSetTriggerLevel(this->handle_, 1);
return bytes_read;
}
size_t RingBuffer::write(void *data, size_t len) {
@ -39,6 +46,10 @@ size_t RingBuffer::write(void *data, size_t len) {
return xStreamBufferSend(this->handle_, data, len, 0);
}
size_t RingBuffer::write_without_replacement(void *data, size_t len, TickType_t ticks_to_wait) {
return xStreamBufferSend(this->handle_, data, len, ticks_to_wait);
}
size_t RingBuffer::available() const { return xStreamBufferBytesAvailable(this->handle_); }
size_t RingBuffer::free() const { return xStreamBufferSpacesAvailable(this->handle_); }

View file

@ -12,13 +12,69 @@ namespace esphome {
class RingBuffer {
public:
/**
* @brief Reads from the ring buffer, waiting up to a specified number of ticks if necessary.
*
* Available bytes are read into the provided data pointer. If not enough bytes are available,
* the function will wait up to `ticks_to_wait` FreeRTOS ticks before reading what is available.
*
* @param data Pointer to copy read data into
* @param len Number of bytes to read
* @param ticks_to_wait Maximum number of FreeRTOS ticks to wait (default: 0)
* @return Number of bytes read
*/
size_t read(void *data, size_t len, TickType_t ticks_to_wait = 0);
/**
* @brief Writes to the ring buffer, overwriting oldest data if necessary.
*
* The provided data is written to the ring buffer. If not enough space is available,
* the function will overwrite the oldest data in the ring buffer.
*
* @param data Pointer to data for writing
* @param len Number of bytes to write
* @return Number of bytes written
*/
size_t write(void *data, size_t len);
/**
* @brief Writes to the ring buffer without overwriting oldest data.
*
* The provided data is written to the ring buffer. If not enough space is available,
* the function will wait up to `ticks_to_wait` FreeRTOS ticks before writing as much as possible.
*
* @param data Pointer to data for writing
* @param len Number of bytes to write
* @param ticks_to_wait Maximum number of FreeRTOS ticks to wait (default: 0)
* @return Number of bytes written
*/
size_t write_without_replacement(void *data, size_t len, TickType_t ticks_to_wait = 0);
/**
* @brief Returns the number of available bytes in the ring buffer.
*
* This function provides the number of bytes that can be read from the ring buffer
* without blocking the calling FreeRTOS task.
*
* @return Number of available bytes
*/
size_t available() const;
/**
* @brief Returns the number of free bytes in the ring buffer.
*
* This function provides the number of bytes that can be written to the ring buffer
* without overwriting data or blocking the calling FreeRTOS task.
*
* @return Number of free bytes
*/
size_t free() const;
/**
* @brief Resets the ring buffer, discarding all stored data.
*
* @return pdPASS if successful, pdFAIL otherwise
*/
BaseType_t reset();
static std::unique_ptr<RingBuffer> create(size_t len);