ringbuffer.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * File : ringbuffer.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2012, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2012-09-30 Bernard first version.
  13. */
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #include <string.h>
  17. void rt_ringbuffer_init(struct rt_ringbuffer *rb,
  18. rt_uint8_t *pool,
  19. rt_uint16_t size)
  20. {
  21. RT_ASSERT(rb != RT_NULL);
  22. /* initialize read and write index */
  23. rb->read_index = rb->write_index = 0;
  24. /* set buffer pool and size */
  25. rb->buffer_ptr = pool;
  26. rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
  27. }
  28. RTM_EXPORT(rt_ringbuffer_init);
  29. rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
  30. const rt_uint8_t *ptr,
  31. rt_uint16_t length)
  32. {
  33. rt_uint16_t size;
  34. rt_uint16_t mask;
  35. rt_uint16_t write_position;
  36. RT_ASSERT(rb != RT_NULL);
  37. mask = rb->buffer_size - 1;
  38. /* whether has enough space */
  39. size = rb->buffer_size - (rb->write_index - rb->read_index);
  40. /* no space */
  41. if (size == 0)
  42. return 0;
  43. /* drop some data */
  44. if (size < length)
  45. length = size;
  46. write_position = (rb->write_index & mask);
  47. if (rb->buffer_size - write_position> length)
  48. {
  49. /* read_index - write_index = empty space */
  50. memcpy(&rb->buffer_ptr[write_position], ptr, length);
  51. }
  52. else
  53. {
  54. memcpy(&rb->buffer_ptr[write_position],
  55. ptr,
  56. rb->buffer_size - write_position);
  57. memcpy(&rb->buffer_ptr[0],
  58. &ptr[rb->buffer_size - write_position],
  59. length - (rb->buffer_size - write_position));
  60. }
  61. rb->write_index += length;
  62. return length;
  63. }
  64. RTM_EXPORT(rt_ringbuffer_put);
  65. /**
  66. * put a character into ring buffer
  67. */
  68. rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
  69. {
  70. rt_uint16_t mask;
  71. RT_ASSERT(rb != RT_NULL);
  72. /* whether has enough space */
  73. mask = rb->buffer_size - 1;
  74. /* whether has enough space */
  75. if (rb->write_index - rb->read_index == rb->buffer_size)
  76. return 0;
  77. /* put character */
  78. rb->buffer_ptr[rb->write_index & mask] = ch;
  79. rb->write_index += 1;
  80. return 1;
  81. }
  82. RTM_EXPORT(rt_ringbuffer_putchar);
  83. /**
  84. * get data from ring buffer
  85. */
  86. rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
  87. rt_uint8_t *ptr,
  88. rt_uint16_t length)
  89. {
  90. rt_size_t size;
  91. rt_uint16_t mask;
  92. rt_uint16_t read_position;
  93. RT_ASSERT(rb != RT_NULL);
  94. /* whether has enough data */
  95. mask = rb->buffer_size - 1;
  96. size = rb->write_index - rb->read_index;
  97. /* no data */
  98. if (size == 0)
  99. return 0;
  100. /* less data */
  101. if (size < length)
  102. length = size;
  103. read_position = rb->read_index & mask;
  104. if (rb->buffer_size - read_position >= length)
  105. {
  106. /* copy all of data */
  107. memcpy(ptr, &rb->buffer_ptr[read_position], length);
  108. }
  109. else
  110. {
  111. /* copy first and second */
  112. memcpy(ptr,
  113. &rb->buffer_ptr[read_position],
  114. rb->buffer_size - read_position);
  115. memcpy(&ptr[rb->buffer_size - read_position],
  116. &rb->buffer_ptr[0],
  117. length - rb->buffer_size + read_position);
  118. }
  119. rb->read_index += length;
  120. return length;
  121. }
  122. RTM_EXPORT(rt_ringbuffer_get);
  123. /**
  124. * get a character from a ringbuffer
  125. */
  126. rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
  127. {
  128. rt_uint16_t mask;
  129. RT_ASSERT(rb != RT_NULL);
  130. /* ringbuffer is empty */
  131. if (rb->read_index == rb->write_index)
  132. return 0;
  133. mask = rb->buffer_size - 1;
  134. /* put character */
  135. *ch = rb->buffer_ptr[rb->read_index & mask];
  136. rb->read_index += 1;
  137. return 1;
  138. }
  139. RTM_EXPORT(rt_ringbuffer_getchar);