summaryrefslogtreecommitdiff
path: root/components/drivers/src
diff options
context:
space:
mode:
authorGrissiom <[email protected]>2013-05-08 15:45:31 +0800
committerGrissiom <[email protected]>2013-05-08 15:45:31 +0800
commit639bd30321bf55b4ea44f55ff2e753f3a270b51a (patch)
treeecf365f2e7816d402339dae48b11a905ea8ceaa6 /components/drivers/src
parent1161e7b3f87914f941900e08807a70c99b36f1a5 (diff)
reimplement ringbuffer
The new implementation use the mirroring method to distinguish full buffer and the empty buffer. It also support buffers of arbitrary size.
Diffstat (limited to 'components/drivers/src')
-rw-r--r--components/drivers/src/ringbuffer.c122
1 files changed, 69 insertions, 53 deletions
diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c
index 6ef8f5da63..efd72d3f84 100644
--- a/components/drivers/src/ringbuffer.c
+++ b/components/drivers/src/ringbuffer.c
@@ -18,12 +18,14 @@
void rt_ringbuffer_init(struct rt_ringbuffer *rb,
rt_uint8_t *pool,
- rt_uint16_t size)
+ rt_int16_t size)
{
RT_ASSERT(rb != RT_NULL);
+ RT_ASSERT(size > 0)
/* initialize read and write index */
- rb->read_index = rb->write_index = 0;
+ rb->read_mirror = rb->read_index = 0;
+ rb->write_mirror = rb->write_index = 0;
/* set buffer pool and size */
rb->buffer_ptr = pool;
@@ -36,38 +38,40 @@ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
rt_uint16_t length)
{
rt_uint16_t size;
- rt_uint16_t mask;
- rt_uint16_t write_position;
RT_ASSERT(rb != RT_NULL);
- mask = rb->buffer_size - 1;
/* whether has enough space */
- size = rb->buffer_size - (rb->write_index - rb->read_index);
+ size = RT_RINGBUFFER_EMPTY(rb);
/* no space */
if (size == 0)
return 0;
+
/* drop some data */
if (size < length)
length = size;
- write_position = (rb->write_index & mask);
- if (rb->buffer_size - write_position> length)
+ if (rb->buffer_size - rb->write_index > length)
{
/* read_index - write_index = empty space */
- memcpy(&rb->buffer_ptr[write_position], ptr, length);
- }
- else
- {
- memcpy(&rb->buffer_ptr[write_position],
- ptr,
- rb->buffer_size - write_position);
- memcpy(&rb->buffer_ptr[0],
- &ptr[rb->buffer_size - write_position],
- length - (rb->buffer_size - write_position));
+ memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
+ /* this should not cause overflow because there is enough space for
+ * length of data in current mirror */
+ rb->write_index += length;
+ return length;
}
- rb->write_index += length;
+
+ memcpy(&rb->buffer_ptr[rb->write_index],
+ &ptr[0],
+ rb->buffer_size - rb->write_index);
+ memcpy(&rb->buffer_ptr[0],
+ &ptr[rb->buffer_size - rb->write_index],
+ length - (rb->buffer_size - rb->write_index));
+
+ /* we are going into the other side of the mirror */
+ rb->write_mirror = ~rb->write_mirror;
+ rb->write_index = length - (rb->buffer_size - rb->write_index);
return length;
}
@@ -78,20 +82,24 @@ RTM_EXPORT(rt_ringbuffer_put);
*/
rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
{
- rt_uint16_t mask;
-
RT_ASSERT(rb != RT_NULL);
- /* whether has enough space */
- mask = rb->buffer_size - 1;
/* whether has enough space */
- if (rb->write_index - rb->read_index == rb->buffer_size)
+ if (!RT_RINGBUFFER_EMPTY(rb))
return 0;
- /* put character */
- rb->buffer_ptr[rb->write_index & mask] = ch;
- rb->write_index += 1;
+ rb->buffer_ptr[rb->write_index] = ch;
+ /* flip mirror */
+ if (rb->write_index == rb->buffer_size-1)
+ {
+ rb->write_mirror = ~rb->write_mirror;
+ rb->write_index = 0;
+ }
+ else
+ {
+ rb->write_index++;
+ }
return 1;
}
RTM_EXPORT(rt_ringbuffer_putchar);
@@ -104,38 +112,41 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
rt_uint16_t length)
{
rt_size_t size;
- rt_uint16_t mask;
- rt_uint16_t read_position;
RT_ASSERT(rb != RT_NULL);
+
/* whether has enough data */
- mask = rb->buffer_size - 1;
- size = rb->write_index - rb->read_index;
+ size = RT_RINGBUFFER_SIZE(rb);
/* no data */
if (size == 0)
return 0;
+
/* less data */
if (size < length)
length = size;
- read_position = rb->read_index & mask;
- if (rb->buffer_size - read_position >= length)
+ if (rb->buffer_size - rb->read_index > length)
{
/* copy all of data */
- memcpy(ptr, &rb->buffer_ptr[read_position], length);
- }
- else
- {
- /* copy first and second */
- memcpy(ptr,
- &rb->buffer_ptr[read_position],
- rb->buffer_size - read_position);
- memcpy(&ptr[rb->buffer_size - read_position],
- &rb->buffer_ptr[0],
- length - rb->buffer_size + read_position);
+ memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
+ /* this should not cause overflow because there is enough space for
+ * length of data in current mirror */
+ rb->read_index += length;
+ return length;
}
- rb->read_index += length;
+
+ /* copy first and second */
+ memcpy(&ptr[0],
+ &rb->buffer_ptr[rb->read_index],
+ rb->buffer_size - rb->read_index);
+ memcpy(&ptr[rb->buffer_size - rb->read_index],
+ &rb->buffer_ptr[0],
+ length - (rb->buffer_size - rb->read_index));
+
+ /* we are going into the other side of the mirror */
+ rb->read_mirror = ~rb->read_mirror;
+ rb->read_index = length - (rb->buffer_size - rb->read_index);
return length;
}
@@ -146,19 +157,24 @@ RTM_EXPORT(rt_ringbuffer_get);
*/
rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
{
- rt_uint16_t mask;
-
RT_ASSERT(rb != RT_NULL);
-
+
/* ringbuffer is empty */
- if (rb->read_index == rb->write_index)
+ if (!RT_RINGBUFFER_SIZE(rb))
return 0;
- mask = rb->buffer_size - 1;
-
/* put character */
- *ch = rb->buffer_ptr[rb->read_index & mask];
- rb->read_index += 1;
+ *ch = rb->buffer_ptr[rb->read_index];
+
+ if (rb->read_index == rb->buffer_size-1)
+ {
+ rb->read_mirror = ~rb->read_mirror;
+ rb->read_index = 0;
+ }
+ else
+ {
+ rb->read_index++;
+ }
return 1;
}