ringbuffer.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2012-09-30 Bernard first version.
  9. * 2013-05-08 Grissiom reimplement
  10. * 2016-08-18 heyuanjie add interface
  11. * 2021-07-20 arminker fix write_index bug in function rt_ringbuffer_put_force
  12. */
  13. #include <rtthread.h>
  14. #include <rtdevice.h>
  15. #include <string.h>
  16. rt_inline enum rt_ringbuffer_state rt_ringbuffer_status(struct rt_ringbuffer *rb)
  17. {
  18. if (rb->read_index == rb->write_index)
  19. {
  20. if (rb->read_mirror == rb->write_mirror)
  21. return RT_RINGBUFFER_EMPTY;
  22. else
  23. return RT_RINGBUFFER_FULL;
  24. }
  25. return RT_RINGBUFFER_HALFFULL;
  26. }
  27. void rt_ringbuffer_init(struct rt_ringbuffer *rb,
  28. rt_uint8_t *pool,
  29. rt_int16_t size)
  30. {
  31. RT_ASSERT(rb != RT_NULL);
  32. RT_ASSERT(size > 0);
  33. /* initialize read and write index */
  34. rb->read_mirror = rb->read_index = 0;
  35. rb->write_mirror = rb->write_index = 0;
  36. /* set buffer pool and size */
  37. rb->buffer_ptr = pool;
  38. rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
  39. }
  40. RTM_EXPORT(rt_ringbuffer_init);
  41. /**
  42. * put a block of data into ring buffer
  43. */
  44. rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
  45. const rt_uint8_t *ptr,
  46. rt_uint16_t length)
  47. {
  48. rt_uint16_t size;
  49. RT_ASSERT(rb != RT_NULL);
  50. /* whether has enough space */
  51. size = rt_ringbuffer_space_len(rb);
  52. /* no space */
  53. if (size == 0)
  54. return 0;
  55. /* drop some data */
  56. if (size < length)
  57. length = size;
  58. if (rb->buffer_size - rb->write_index > length)
  59. {
  60. /* read_index - write_index = empty space */
  61. memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
  62. /* this should not cause overflow because there is enough space for
  63. * length of data in current mirror */
  64. rb->write_index += length;
  65. return length;
  66. }
  67. memcpy(&rb->buffer_ptr[rb->write_index],
  68. &ptr[0],
  69. rb->buffer_size - rb->write_index);
  70. memcpy(&rb->buffer_ptr[0],
  71. &ptr[rb->buffer_size - rb->write_index],
  72. length - (rb->buffer_size - rb->write_index));
  73. /* we are going into the other side of the mirror */
  74. rb->write_mirror = ~rb->write_mirror;
  75. rb->write_index = length - (rb->buffer_size - rb->write_index);
  76. return length;
  77. }
  78. RTM_EXPORT(rt_ringbuffer_put);
  79. /**
  80. * put a block of data into ring buffer
  81. *
  82. * When the buffer is full, it will discard the old data.
  83. */
  84. rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
  85. const rt_uint8_t *ptr,
  86. rt_uint16_t length)
  87. {
  88. rt_uint16_t space_length;
  89. RT_ASSERT(rb != RT_NULL);
  90. space_length = rt_ringbuffer_space_len(rb);
  91. if (length > rb->buffer_size)
  92. {
  93. ptr = &ptr[length - rb->buffer_size];
  94. length = rb->buffer_size;
  95. }
  96. if (rb->buffer_size - rb->write_index > length)
  97. {
  98. /* read_index - write_index = empty space */
  99. memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
  100. /* this should not cause overflow because there is enough space for
  101. * length of data in current mirror */
  102. rb->write_index += length;
  103. if (length > space_length)
  104. rb->read_index = rb->write_index;
  105. return length;
  106. }
  107. memcpy(&rb->buffer_ptr[rb->write_index],
  108. &ptr[0],
  109. rb->buffer_size - rb->write_index);
  110. memcpy(&rb->buffer_ptr[0],
  111. &ptr[rb->buffer_size - rb->write_index],
  112. length - (rb->buffer_size - rb->write_index));
  113. /* we are going into the other side of the mirror */
  114. rb->write_mirror = ~rb->write_mirror;
  115. rb->write_index = length - (rb->buffer_size - rb->write_index);
  116. if (length > space_length)
  117. {
  118. if (rb->write_index <= rb->read_index)
  119. rb->read_mirror = ~rb->read_mirror;
  120. rb->read_index = rb->write_index;
  121. }
  122. return length;
  123. }
  124. RTM_EXPORT(rt_ringbuffer_put_force);
  125. /**
  126. * get data from ring buffer
  127. */
  128. rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
  129. rt_uint8_t *ptr,
  130. rt_uint16_t length)
  131. {
  132. rt_size_t size;
  133. RT_ASSERT(rb != RT_NULL);
  134. /* whether has enough data */
  135. size = rt_ringbuffer_data_len(rb);
  136. /* no data */
  137. if (size == 0)
  138. return 0;
  139. /* less data */
  140. if (size < length)
  141. length = size;
  142. if (rb->buffer_size - rb->read_index > length)
  143. {
  144. /* copy all of data */
  145. memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
  146. /* this should not cause overflow because there is enough space for
  147. * length of data in current mirror */
  148. rb->read_index += length;
  149. return length;
  150. }
  151. memcpy(&ptr[0],
  152. &rb->buffer_ptr[rb->read_index],
  153. rb->buffer_size - rb->read_index);
  154. memcpy(&ptr[rb->buffer_size - rb->read_index],
  155. &rb->buffer_ptr[0],
  156. length - (rb->buffer_size - rb->read_index));
  157. /* we are going into the other side of the mirror */
  158. rb->read_mirror = ~rb->read_mirror;
  159. rb->read_index = length - (rb->buffer_size - rb->read_index);
  160. return length;
  161. }
  162. RTM_EXPORT(rt_ringbuffer_get);
  163. /**
  164. * peak data from ring buffer
  165. */
  166. rt_size_t rt_ringbuffer_peak(struct rt_ringbuffer *rb, rt_uint8_t **ptr)
  167. {
  168. RT_ASSERT(rb != RT_NULL);
  169. *ptr = RT_NULL;
  170. /* whether has enough data */
  171. rt_size_t size = rt_ringbuffer_data_len(rb);
  172. /* no data */
  173. if (size == 0)
  174. return 0;
  175. *ptr = &rb->buffer_ptr[rb->read_index];
  176. if(rb->buffer_size - rb->read_index > size)
  177. {
  178. rb->read_index += size;
  179. return size;
  180. }
  181. size = rb->buffer_size - rb->read_index;
  182. /* we are going into the other side of the mirror */
  183. rb->read_mirror = ~rb->read_mirror;
  184. rb->read_index = 0;
  185. return size;
  186. }
  187. RTM_EXPORT(rt_ringbuffer_peak);
  188. /**
  189. * put a character into ring buffer
  190. */
  191. rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
  192. {
  193. RT_ASSERT(rb != RT_NULL);
  194. /* whether has enough space */
  195. if (!rt_ringbuffer_space_len(rb))
  196. return 0;
  197. rb->buffer_ptr[rb->write_index] = ch;
  198. /* flip mirror */
  199. if (rb->write_index == rb->buffer_size-1)
  200. {
  201. rb->write_mirror = ~rb->write_mirror;
  202. rb->write_index = 0;
  203. }
  204. else
  205. {
  206. rb->write_index++;
  207. }
  208. return 1;
  209. }
  210. RTM_EXPORT(rt_ringbuffer_putchar);
  211. /**
  212. * put a character into ring buffer
  213. *
  214. * When the buffer is full, it will discard one old data.
  215. */
  216. rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t ch)
  217. {
  218. enum rt_ringbuffer_state old_state;
  219. RT_ASSERT(rb != RT_NULL);
  220. old_state = rt_ringbuffer_status(rb);
  221. rb->buffer_ptr[rb->write_index] = ch;
  222. /* flip mirror */
  223. if (rb->write_index == rb->buffer_size-1)
  224. {
  225. rb->write_mirror = ~rb->write_mirror;
  226. rb->write_index = 0;
  227. if (old_state == RT_RINGBUFFER_FULL)
  228. {
  229. rb->read_mirror = ~rb->read_mirror;
  230. rb->read_index = rb->write_index;
  231. }
  232. }
  233. else
  234. {
  235. rb->write_index++;
  236. if (old_state == RT_RINGBUFFER_FULL)
  237. rb->read_index = rb->write_index;
  238. }
  239. return 1;
  240. }
  241. RTM_EXPORT(rt_ringbuffer_putchar_force);
  242. /**
  243. * get a character from a ringbuffer
  244. */
  245. rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
  246. {
  247. RT_ASSERT(rb != RT_NULL);
  248. /* ringbuffer is empty */
  249. if (!rt_ringbuffer_data_len(rb))
  250. return 0;
  251. /* put character */
  252. *ch = rb->buffer_ptr[rb->read_index];
  253. if (rb->read_index == rb->buffer_size-1)
  254. {
  255. rb->read_mirror = ~rb->read_mirror;
  256. rb->read_index = 0;
  257. }
  258. else
  259. {
  260. rb->read_index++;
  261. }
  262. return 1;
  263. }
  264. RTM_EXPORT(rt_ringbuffer_getchar);
  265. /**
  266. * get the size of data in rb
  267. */
  268. rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
  269. {
  270. switch (rt_ringbuffer_status(rb))
  271. {
  272. case RT_RINGBUFFER_EMPTY:
  273. return 0;
  274. case RT_RINGBUFFER_FULL:
  275. return rb->buffer_size;
  276. case RT_RINGBUFFER_HALFFULL:
  277. default:
  278. if (rb->write_index > rb->read_index)
  279. return rb->write_index - rb->read_index;
  280. else
  281. return rb->buffer_size - (rb->read_index - rb->write_index);
  282. };
  283. }
  284. RTM_EXPORT(rt_ringbuffer_data_len);
  285. /**
  286. * empty the rb
  287. */
  288. void rt_ringbuffer_reset(struct rt_ringbuffer *rb)
  289. {
  290. RT_ASSERT(rb != RT_NULL);
  291. rb->read_mirror = 0;
  292. rb->read_index = 0;
  293. rb->write_mirror = 0;
  294. rb->write_index = 0;
  295. }
  296. RTM_EXPORT(rt_ringbuffer_reset);
  297. #ifdef RT_USING_HEAP
  298. struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t size)
  299. {
  300. struct rt_ringbuffer *rb;
  301. rt_uint8_t *pool;
  302. RT_ASSERT(size > 0);
  303. size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
  304. rb = (struct rt_ringbuffer *)rt_malloc(sizeof(struct rt_ringbuffer));
  305. if (rb == RT_NULL)
  306. goto exit;
  307. pool = (rt_uint8_t *)rt_malloc(size);
  308. if (pool == RT_NULL)
  309. {
  310. rt_free(rb);
  311. rb = RT_NULL;
  312. goto exit;
  313. }
  314. rt_ringbuffer_init(rb, pool, size);
  315. exit:
  316. return rb;
  317. }
  318. RTM_EXPORT(rt_ringbuffer_create);
  319. void rt_ringbuffer_destroy(struct rt_ringbuffer *rb)
  320. {
  321. RT_ASSERT(rb != RT_NULL);
  322. rt_free(rb->buffer_ptr);
  323. rt_free(rb);
  324. }
  325. RTM_EXPORT(rt_ringbuffer_destroy);
  326. #endif