diff options
Diffstat (limited to 'components/drivers/src/ringbuffer.c')
| -rw-r--r-- | components/drivers/src/ringbuffer.c | 122 |
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; } |
