ring_buf.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include "ring_buf.h"
  2. #include "FreeRTOS.h"
  3. #include "task.h"
  4. #include "main.h"
  5. #ifdef PRINTF_STDLIB
  6. #include <stdio.h>
  7. #endif
  8. #ifdef PRINTF_CUSTOM
  9. #include "tinystdio.h"
  10. #endif
  11. #define _size_w(n) sizeof(n) / sizeof(int)
  12. void rbuf32_init(rbuf_t *rbuf32, uint32_t *buffer, uint32_t size) {
  13. rbuf32->buf_ptr = buffer;
  14. rbuf32->size = size;
  15. rbuf32->read_index = 0;
  16. rbuf32->write_index = 0;
  17. }
  18. void rbuf64_init(rbuf_t *rbuf64, uint64_t *buffer, uint32_t size) {
  19. rbuf64->buf_ptr = (uint32_t *)buffer;
  20. rbuf64->size = size;
  21. rbuf64->read_index = 0;
  22. rbuf64->write_index = 0;
  23. }
  24. bool rbuf_isempty(rbuf_t *rbuf) {
  25. if (rbuf->read_index == rbuf->write_index)
  26. return true;
  27. else
  28. return false;
  29. }
  30. /**
  31. * @brief функция определения свободного места в циклическом буфере
  32. * (всегда остается одна свободная ячейка)
  33. *
  34. */
  35. int32_t rbuf_free_space(rbuf_t *rbuf)
  36. {
  37. int32_t free_space = 0;
  38. if(rbuf->write_index == rbuf->read_index)
  39. free_space = rbuf->size;
  40. else if(rbuf->write_index > rbuf->read_index)
  41. free_space = rbuf->size - (rbuf->write_index - rbuf->read_index);
  42. else
  43. free_space = rbuf->read_index - rbuf->write_index;
  44. return free_space;
  45. }
  46. /**
  47. * @brief функция определения заполнения циклического буфера
  48. * (всегда остается одна свободная ячейка)
  49. *
  50. */
  51. int32_t rbuf_full_space(rbuf_t *rbuf)
  52. {
  53. int32_t full_space = 0;
  54. if(rbuf->write_index == rbuf->read_index)
  55. full_space = 0;
  56. else if(rbuf->write_index > rbuf->read_index)
  57. full_space = rbuf->write_index - rbuf->read_index;
  58. else
  59. full_space = rbuf->size - (rbuf->read_index - rbuf->write_index);
  60. return full_space;
  61. }
  62. bool rbuf_isfull(rbuf_t *rbuf) {
  63. int r_tmp;
  64. if (rbuf->write_index == (rbuf->size - 1)) {
  65. r_tmp = rbuf->read_index + rbuf->size;
  66. }
  67. else
  68. r_tmp = rbuf->read_index;
  69. if (r_tmp - rbuf->write_index == 1)
  70. return true;
  71. else
  72. return false;
  73. }
  74. bool rbuf32_get(rbuf_t *rbuf32, uint32_t *data) {
  75. /* Check whether buffer is not empty */
  76. if (!rbuf_isempty(rbuf32)) {
  77. *data = rbuf32->buf_ptr[rbuf32->read_index++];
  78. /* swap the read pointer */
  79. if (rbuf32->read_index == (rbuf32->size))
  80. rbuf32->read_index = 0;
  81. return true;
  82. }
  83. else
  84. return false;
  85. }
  86. bool rbuf64_get(rbuf_t *rbuf64, uint64_t *data) {
  87. /* Check whether buffer is not empty */
  88. if (!rbuf_isempty(rbuf64)) {
  89. *data = *((uint64_t*)rbuf64->buf_ptr + rbuf64->read_index);
  90. rbuf64->read_index++;
  91. /* swap the read pointer */
  92. if (rbuf64->read_index == (rbuf64->size))
  93. rbuf64->read_index = 0;
  94. return true;
  95. }
  96. else
  97. return false;
  98. }
  99. /*
  100. * Oldest data is overwriting when write_ptr reaches read_ptr - 1 (!).
  101. * For check use rbuf_isfull.
  102. */
  103. bool rbuf32_put(rbuf_t *rbuf32, uint32_t data) {
  104. if(!rbuf_isfull(rbuf32))
  105. {
  106. rbuf32->buf_ptr[rbuf32->write_index++] = data;
  107. /* swap the write pointer */
  108. if (rbuf32->write_index == (rbuf32->size))
  109. rbuf32->write_index = 0;
  110. return true;
  111. }
  112. else
  113. return false;
  114. }
  115. bool rbuf64_put(rbuf_t *rbuf64, uint64_t data) {
  116. uint32_t *data_ptr;
  117. char size_w = _size_w(data);
  118. if(!rbuf_isfull(rbuf64))
  119. {
  120. data_ptr = rbuf64->buf_ptr + rbuf64->write_index * size_w;
  121. *(uint64_t*)data_ptr = data;
  122. rbuf64->write_index++;
  123. /* swap the write pointer */
  124. if (rbuf64->write_index == rbuf64->size)
  125. rbuf64->write_index = 0;
  126. return true;
  127. }
  128. else
  129. return false;
  130. }
  131. /**
  132. * @brief тестовая функция для циклического буфера
  133. *
  134. */
  135. bool buf_test(void) {
  136. rbuf_t rbuf32;
  137. rbuf_t rbuf64;
  138. uint32_t rbuf_data32[32];
  139. uint64_t rbuf_data64[32];
  140. int i;
  141. rbuf32_init(&rbuf32, rbuf_data32, 32);
  142. rbuf64_init(&rbuf64, rbuf_data64, 32);
  143. bool status_test = true;
  144. uint32_t put32 = 0, get32 = 0;
  145. uint64_t put64 = 0x5555555555555555, get64 = 0;
  146. volatile int j;
  147. //DBG printf("capacity 64 = %d\r\n", rbuf64.size);
  148. DBG printf("RBUF64 TEST:\r\n");
  149. DBG printf("FULLNESS TEST:\r\n");
  150. i = 0;
  151. while (rbuf64_put(&rbuf64, put64++)) {
  152. DBG printf("W%d: %.16llX \r\n", i, (long long)rbuf_data64[i]);
  153. i ++;
  154. j = 1000000;
  155. while (j--);
  156. }
  157. if(i != rbuf64.size - 1) {
  158. status_test = false;
  159. DBG printf("Failed: i = %d, rbuf64.size = %d\r\n", i, rbuf64.size);
  160. }
  161. DBG printf("EMPTYNESS TEST:\r\n");
  162. i = 0;
  163. while (rbuf64_get(&rbuf64, &get64)) {
  164. if(get64 != rbuf_data64[i])
  165. status_test = false;
  166. DBG printf("R%d: %.16llX \r\n", i++, (long long)get64);
  167. j = 1000000;
  168. while (j--);
  169. }
  170. if(i != rbuf64.size - 1) {
  171. status_test = false;
  172. DBG printf("Failed\r\n");
  173. }
  174. i = 0;
  175. put64 = 0x4444444444444444;
  176. rbuf64_init(&rbuf64, rbuf_data64, 32);
  177. DBG printf("CYCLE TEST:\r\n");
  178. for(i = 0; i < 2*rbuf64.size; i++)
  179. {
  180. if(rbuf64_put(&rbuf64, put64++))
  181. DBG printf("W%d: %.16llX \r\n", i, (long long)rbuf_data64[i-32*(i/32)]);
  182. else {
  183. status_test = false;
  184. DBG printf("Failed\r\n");
  185. }
  186. j = 1000000;
  187. while (j--);
  188. if(rbuf64_get(&rbuf64, &get64))
  189. {
  190. if(get64 != rbuf_data64[i-32*(i/32)]) {
  191. status_test = false;
  192. DBG printf("Failed\r\n");
  193. }
  194. DBG printf("R%d: %.16llX \r\n", i, (long long)get64);
  195. }
  196. else {
  197. status_test = false;
  198. DBG printf("Failed\r\n");
  199. }
  200. j = 1000000;
  201. while (j--);
  202. }
  203. DBG printf("capacity 32 = %d\r\n", rbuf32.size);
  204. DBG printf("RBUF32 TEST:\r\n");
  205. DBG printf("FULLNESS TEST:\r\n");
  206. i = 0;
  207. while (rbuf32_put(&rbuf32, put32++)) {
  208. DBG printf("W%d: %.16lX \r\n", i, rbuf_data32[i]);
  209. i ++;
  210. j = 1000000;
  211. while (j--);
  212. }
  213. if(i != rbuf32.size - 1) {
  214. status_test = false;
  215. DBG printf("Failed\r\n");
  216. }
  217. DBG printf("EMPTYNESS TEST:\r\n");
  218. i = 0;
  219. while (rbuf32_get(&rbuf32, &get32)) {
  220. if(get32 != rbuf_data32[i]) {
  221. status_test = false;
  222. DBG printf("Failed\r\n");
  223. }
  224. DBG printf("R%d: %.16lX \r\n", i++, get32);
  225. j = 1000000;
  226. while (j--);
  227. }
  228. if(i != rbuf32.size - 1) {
  229. status_test = false;
  230. DBG printf("Failed\r\n");
  231. }
  232. i = 0;
  233. put32 = 0x44444444;
  234. rbuf32_init(&rbuf32, rbuf_data32, 32);
  235. DBG printf("CYCLE TEST:\r\n");
  236. for(i = 0; i < 2*rbuf32.size; i++)
  237. {
  238. if(rbuf32_put(&rbuf32, put32++))
  239. DBG printf("W%d: %.16lX \r\n", i, rbuf_data32[i-32*(i/32)]);
  240. else {
  241. status_test = false;
  242. DBG printf("Failed\r\n");
  243. }
  244. j = 1000000;
  245. while (j--);
  246. if(rbuf32_get(&rbuf32, &get32))
  247. {
  248. if(get32 != rbuf_data32[i-32*(i/32)]) {
  249. status_test = false;
  250. DBG printf("Failed\r\n");
  251. }
  252. DBG printf("R%d: %.16lX \r\n", i, get32);
  253. }
  254. else {
  255. DBG printf("Failed\r\n");
  256. status_test = false;
  257. }
  258. j = 1000000;
  259. while (j--);
  260. }
  261. if (status_test) {
  262. printf("Test OK\r\n");
  263. }
  264. else printf("Test fail\r\n");
  265. return status_test;
  266. }