You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2020/11/20 13:33:15 UTC

[incubator-nuttx] 01/02: mm/circbuf: support circular buffer managerment

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 23ddeaf3be530cd8faa7e7077fa9ea7caa83d708
Author: dongjiuzhu <do...@xiaomi.com>
AuthorDate: Thu Nov 12 18:40:06 2020 +0800

    mm/circbuf: support circular buffer managerment
    
    N/A
    
    Change-Id: Ib1fc009b9ce3af5815920f22221fe8a7262299ef
    Signed-off-by: dongjiuzhu <do...@xiaomi.com>
---
 include/nuttx/mm/circbuf.h | 308 +++++++++++++++++++++++++++++
 mm/Kconfig                 |   6 +
 mm/Makefile                |   1 +
 mm/circbuf/Make.defs       |  30 +++
 mm/circbuf/circbuf.c       | 474 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 819 insertions(+)

diff --git a/include/nuttx/mm/circbuf.h b/include/nuttx/mm/circbuf.h
new file mode 100644
index 0000000..c6d291c
--- /dev/null
+++ b/include/nuttx/mm/circbuf.h
@@ -0,0 +1,308 @@
+/****************************************************************************
+ * include/nuttx/mm/circbuf.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_MM_CIRCBUF_H
+#define __INCLUDE_NUTTX_MM_CIRCBUF_H
+
+/* Note about locking: There is no locking required while only one reader
+ * and one writer is using the circular buffer.
+ * For multiple writer and one reader there is only a need to lock the
+ * writer. And vice versa for only one writer and multiple reader there is
+ * only a need to lock the reader.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* This structure describes circular buffer */
+
+struct circbuf_s
+{
+  FAR void *base;     /* The pointer to buffer space */
+  size_t    size;     /* The size of buffer space */
+  size_t    head;     /* The head of buffer space */
+  size_t    tail;     /* The tail of buffer space */
+  bool      external; /* The flag for external buffer */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: circbuf_init
+ *
+ * Description:
+ *   Initialize a circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   base  - A pointer to circular buffer's internal buffer. It can be
+ *           provided by caller because sometimes the creation of buffer
+ *           is special or needs to preallocated, eg: DMA buffer.
+ *           If NULL, a buffer of the given size will be allocated.
+ *   bytes - The size of the internal buffer.
+ *
+ * Returned Value:
+ *   Zero on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int circbuf_init(FAR struct circbuf_s *circ,
+                  FAR void *base, size_t bytes);
+
+/****************************************************************************
+ * Name: circbuf_resize
+ *
+ * Description:
+ *   Resize a circular buffer (change buffer size).
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   bytes - The size of the internal buffer.
+ *
+ * Returned Value:
+ *   Zero on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int circbuf_resize(FAR struct circbuf_s *circ, size_t bytes);
+
+/****************************************************************************
+ * Name: circbuf_uninit
+ *
+ * Description:
+ *   Free the circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+void circbuf_uninit(FAR struct circbuf_s *circ);
+
+/****************************************************************************
+ * Name: circbuf_reset
+ *
+ * Description:
+ *   Remove the entire circular buffer content.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+void circbuf_reset(FAR struct circbuf_s *circ);
+
+/****************************************************************************
+ * Name: circbuf_is_full
+ *
+ * Description:
+ *   Return true if the circular buffer is full.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+bool circbuf_is_full(FAR struct circbuf_s *circ);
+
+/****************************************************************************
+ * Name: circbuf_is_empty
+ *
+ * Description:
+ *   Return true if the circular buffer is empty.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+bool circbuf_is_empty(FAR struct circbuf_s *circ);
+
+/****************************************************************************
+ * Name: circbuf_size
+ *
+ * Description:
+ *   Return size of the circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+size_t circbuf_size(FAR struct circbuf_s *circ);
+
+/****************************************************************************
+ * Name: circbuf_used
+ *
+ * Description:
+ *   Return the used bytes of the circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+size_t circbuf_used(FAR struct circbuf_s *circ);
+
+/****************************************************************************
+ * Name: circbuf_space
+ *
+ * Description:
+ *   Return the remaing space of the circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+size_t circbuf_space(FAR struct circbuf_s *circ);
+
+/****************************************************************************
+ * Name: circbuf_peek
+ *
+ * Description:
+ *   Get data form the circular buffer without removing
+ *
+ * Note :
+ *   That with only one concurrent reader and one concurrent writer,
+ *   you don't need extra locking to use these api.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   dst   - Address where to store the data.
+ *   bytes - Number of bytes to get.
+ *
+ * Returned Value:
+ *   The bytes of get data is returned if the peek data is successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_peek(FAR struct circbuf_s *circ,
+                      FAR void *dst, size_t bytes);
+
+/****************************************************************************
+ * Name: circbuf_read
+ *
+ * Description:
+ *   Get data form the circular buffer.
+ *
+ * Note :
+ *   That with only one concurrent reader and one concurrent writer,
+ *   you don't need extra locking to use these api.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   dst   - Address where to store the data.
+ *   bytes - Number of bytes to get.
+ *
+ * Returned Value:
+ *   The bytes of get data is returned if the read data is successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_read(FAR struct circbuf_s *circ,
+                      FAR void *dst, size_t bytes);
+
+/****************************************************************************
+ * Name: circbuf_skip
+ *
+ * Description:
+ *   Skip data form the circular buffer.
+ *
+ * Note:
+ *   That with only one concurrent reader and one concurrent writer,
+ *   you don't need extra locking to use these api.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   bytes - Number of bytes to skip.
+ *
+ * Returned Value:
+ *   The bytes of get data is returned if the skip data is successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_skip(FAR struct circbuf_s *circ, size_t bytes);
+
+/****************************************************************************
+ * Name: circbuf_write
+ *
+ * Description:
+ *   Write data to the circular buffer.
+ *
+ * Note:
+ *   That with only one concurrent reader and one concurrent writer,
+ *   you don't need extra locking to use these api.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   src   - The data to be added.
+ *   bytes - Number of bytes to be added.
+ *
+ * Returned Value:
+ *   The bytes of get data is returned if the write data is successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_write(FAR struct circbuf_s *circ,
+                       FAR const void *src, size_t bytes);
+
+/****************************************************************************
+ * Name: circbuf_overwrite
+ *
+ * Description:
+ *   Write data to the circular buffer. It can overwrite old data when
+ *   circular buffer don't have enough space to store data.
+ *
+ * Note:
+ *   Usage circbuf_overwrite () is dangerous. It should be only called
+ *   when the buffer is exclusived locked or when it is secured that no
+ *   other thread is accessing the buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   src   - The data to be added.
+ *   bytes - Number of bytes to be added.
+ *
+ * Returned Value:
+ *   The bytes length of overwrite is returned if it's successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_overwrite(FAR struct circbuf_s *circ,
+                           FAR const void *src, size_t bytes);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/mm/Kconfig b/mm/Kconfig
index e4b8170..788ae47 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -155,4 +155,10 @@ config MM_FILL_ALLOCATIONS
 		Fill all malloc() allocations with 0xAA. This helps
 		detecting uninitialized variable errors.
 
+config MM_CIRCBUF
+	bool "Circular buffer support"
+	default n
+	---help---
+		Build in support for the circular buffer management.
+
 source "mm/iob/Kconfig"
diff --git a/mm/Makefile b/mm/Makefile
index b08ad3a..ae04d19 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -43,6 +43,7 @@ include kmm_heap/Make.defs
 include mm_gran/Make.defs
 include shm/Make.defs
 include iob/Make.defs
+include circbuf/Make.defs
 
 BINDIR ?= bin
 
diff --git a/mm/circbuf/Make.defs b/mm/circbuf/Make.defs
new file mode 100644
index 0000000..1d71c24
--- /dev/null
+++ b/mm/circbuf/Make.defs
@@ -0,0 +1,30 @@
+############################################################################
+# mm/circbuf/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# Circular buffer management
+
+ifeq ($(CONFIG_MM_CIRCBUF),y)
+CSRCS += circbuf.c
+
+# Add the circular buffer directory to the build
+
+DEPPATH += --dep-path circbuf
+VPATH += :circbuf
+endif
diff --git a/mm/circbuf/circbuf.c b/mm/circbuf/circbuf.c
new file mode 100644
index 0000000..cef8e13
--- /dev/null
+++ b/mm/circbuf/circbuf.c
@@ -0,0 +1,474 @@
+/****************************************************************************
+ * mm/circbuf/circbuf.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Note about locking: There is no locking required while only one reader
+ * and one writer is using the circular buffer.
+ * For multiple writer and one reader there is only a need to lock the
+ * writer. And vice versa for only one writer and multiple reader there is
+ * only a need to lock the reader.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mm/circbuf.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: circbuf_init
+ *
+ * Description:
+ *   Initialize a circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   base  - A pointer to circular buffer's internal buffer. It can be
+ *           provided by caller because sometimes the creation of buffer
+ *           is special or needs to preallocated, eg: DMA buffer.
+ *           If NULL, a buffer of the given size will be allocated.
+ *   bytes - The size of the internal buffer.
+ *
+ * Returned Value:
+ *   Zero on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int circbuf_init(FAR struct circbuf_s *circ, FAR void *base, size_t bytes)
+{
+  DEBUGASSERT(circ);
+  DEBUGASSERT(!base || bytes);
+
+  circ->external = !!base;
+
+  if (!base && bytes)
+    {
+      base = kmm_malloc(bytes);
+      if (!base)
+        {
+          return -ENOMEM;
+        }
+    }
+
+  circ->base = base;
+  circ->size = bytes;
+  circ->head = 0;
+  circ->tail = 0;
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: circbuf_resize
+ *
+ * Description:
+ *   Resize a circular buffer (change buffer size).
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   bytes - The size of the internal buffer.
+ *
+ * Returned Value:
+ *   Zero on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int circbuf_resize(FAR struct circbuf_s *circ, size_t bytes)
+{
+  FAR void *tmp;
+  size_t len;
+
+  DEBUGASSERT(circ);
+  DEBUGASSERT(!circ->external);
+
+  tmp = kmm_malloc(bytes);
+  if (!tmp)
+    {
+      return -ENOMEM;
+    }
+
+  len = circbuf_used(circ);
+  if (bytes < len)
+    {
+      circbuf_skip(circ, len - bytes);
+      len = bytes;
+    }
+
+  circbuf_read(circ, tmp, len);
+
+  kmm_free(circ->base);
+
+  circ->base = tmp;
+  circ->size = bytes;
+  circ->head = len;
+  circ->tail = 0;
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: circbuf_reset
+ *
+ * Description:
+ *   Remove the entire circular buffer content.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+void circbuf_reset(FAR struct circbuf_s *circ)
+{
+  DEBUGASSERT(circ);
+  circ->head = circ->tail = 0;
+}
+
+/****************************************************************************
+ * Name: circbuf_uninit
+ *
+ * Description:
+ *   Free the circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+void circbuf_uninit(FAR struct circbuf_s *circ)
+{
+  DEBUGASSERT(circ);
+
+  if (!circ->external)
+    {
+      kmm_free(circ->base);
+    }
+
+  memset(circ, 0, sizeof(*circ));
+}
+
+/****************************************************************************
+ * Name: circbuf_size
+ *
+ * Description:
+ *   Return size of the circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+size_t circbuf_size(FAR struct circbuf_s *circ)
+{
+  DEBUGASSERT(circ);
+  return circ->size;
+}
+
+/****************************************************************************
+ * Name: circbuf_used
+ *
+ * Description:
+ *   Return the used bytes of the circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+size_t circbuf_used(FAR struct circbuf_s *circ)
+{
+  DEBUGASSERT(circ);
+  return circ->head - circ->tail;
+}
+
+/****************************************************************************
+ * Name: circbuf_space
+ *
+ * Description:
+ *   Return the remaing space of the circular buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+size_t circbuf_space(FAR struct circbuf_s *circ)
+{
+  return circbuf_size(circ) - circbuf_used(circ);
+}
+
+/****************************************************************************
+ * Name: circbuf_is_empty
+ *
+ * Description:
+ *   Return true if the circular buffer is empty.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+bool circbuf_is_empty(FAR struct circbuf_s *circ)
+{
+  return !circbuf_used(circ);
+}
+
+/****************************************************************************
+ * Name: circbuf_is_full
+ *
+ * Description:
+ *   Return true if the circular buffer is full.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ ****************************************************************************/
+
+bool circbuf_is_full(FAR struct circbuf_s *circ)
+{
+  return !circbuf_space(circ);
+}
+
+/****************************************************************************
+ * Name: circbuf_peek
+ *
+ * Description:
+ *   Get data form the circular buffer without removing
+ *
+ * Note :
+ *   That with only one concurrent reader and one concurrent writer,
+ *   you don't need extra locking to use these api.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   dst   - Address where to store the data.
+ *   bytes - Number of bytes to get.
+ *
+ * Returned Value:
+ *   The bytes of get data is returned if the peek data is successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_peek(FAR struct circbuf_s *circ,
+                      FAR void *dst, size_t bytes)
+{
+  size_t len;
+  size_t off;
+
+  DEBUGASSERT(circ);
+
+  len = circbuf_used(circ);
+  off = circ->tail % circ->size;
+
+  if (bytes > len)
+    {
+      bytes = len;
+    }
+
+  len = circ->size - off;
+  if (bytes < len)
+    {
+      len = bytes;
+    }
+
+  memcpy(dst, circ->base + off, len);
+  memcpy(dst + len, circ->base, bytes - len);
+
+  return bytes;
+}
+
+/****************************************************************************
+ * Name: circbuf_read
+ *
+ * Description:
+ *   Get data form the circular buffer.
+ *
+ * Note :
+ *   That with only one concurrent reader and one concurrent writer,
+ *   you don't need extra locking to use these api.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   dst   - Address where to store the data.
+ *   bytes - Number of bytes to get.
+ *
+ * Returned Value:
+ *   The bytes of get data is returned if the read data is successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_read(FAR struct circbuf_s *circ,
+                      FAR void *dst, size_t bytes)
+{
+  DEBUGASSERT(circ);
+  DEBUGASSERT(dst || !bytes);
+
+  bytes = circbuf_peek(circ, dst, bytes);
+  circ->tail += bytes;
+
+  return bytes;
+}
+
+/****************************************************************************
+ * Name: circbuf_skip
+ *
+ * Description:
+ *   Skip data form the circular buffer.
+ *
+ * Note :
+ *   That with only one concurrent reader and one concurrent writer,
+ *   you don't need extra locking to use these api.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   bytes - Number of bytes to skip.
+ *
+ * Returned Value:
+ *   The bytes of get data is returned if the skip data is successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_skip(FAR struct circbuf_s *circ, size_t bytes)
+{
+  size_t len;
+
+  DEBUGASSERT(circ);
+
+  len = circbuf_used(circ);
+
+  if (bytes > len)
+    {
+      bytes = len;
+    }
+
+  circ->tail += bytes;
+
+  return bytes;
+}
+
+/****************************************************************************
+ * Name: circbuf_write
+ *
+ * Description:
+ *   Write data to the circular buffer.
+ *
+ * Note :
+ *   That with only one concurrent reader and one concurrent writer,
+ *   you don't need extra locking to use these api.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   src   - The data to be added.
+ *   bytes - Number of bytes to be added.
+ *
+ * Returned Value:
+ *   The bytes of get data is returned if the write data is successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_write(FAR struct circbuf_s *circ,
+                       FAR const void *src, size_t bytes)
+{
+  size_t space;
+  size_t off;
+
+  DEBUGASSERT(circ);
+  DEBUGASSERT(src || !bytes);
+
+  space = circbuf_space(circ);
+  off = circ->head % circ->size;
+  if (bytes > space)
+    {
+      bytes = space;
+    }
+
+  space = circ->size - off;
+  if (bytes < space)
+    {
+      space = bytes;
+    }
+
+  memcpy(circ->base + off, src, space);
+  memcpy(circ->base, src + space, bytes - space);
+  circ->head += bytes;
+
+  return bytes;
+}
+
+/****************************************************************************
+ * Name: circbuf_overwrite
+ *
+ * Description:
+ *   Write data to the circular buffer. It can overwrite old data when
+ *   circular buffer don't have enough space to store data.
+ *
+ * Note:
+ *   Usage circbuf_overwrite () is dangerous. It should be only called
+ *   when the buffer is exclusived locked or when it is secured that no
+ *   other thread is accessing the buffer.
+ *
+ * Input Parameters:
+ *   circ  - Address of the circular buffer to be used.
+ *   src   - The data to be added.
+ *   bytes - Number of bytes to be added.
+ *
+ * Returned Value:
+ *   The bytes length of overwrite is returned if it's successful;
+ *   A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+ssize_t circbuf_overwrite(FAR struct circbuf_s *circ,
+                           FAR const void *src, size_t bytes)
+{
+  size_t overwrite = 0;
+  size_t space;
+  size_t off;
+
+  DEBUGASSERT(circ);
+  DEBUGASSERT(src || !bytes);
+
+  if (bytes > circ->size)
+    {
+      src += bytes - circ->size;
+      bytes = circ->size;
+    }
+
+  space = circbuf_space(circ);
+  if (bytes > space)
+    {
+      overwrite = bytes - space;
+    }
+
+  off = circ->head % circ->size;
+  space = circ->size - off;
+  if (bytes < space)
+    {
+      space = bytes;
+    }
+
+  memcpy(circ->base + off, src, space);
+  memcpy(circ->base, src + space, bytes - space);
+  circ->head += bytes;
+  circ->tail += overwrite;
+
+  return overwrite;
+}