rkfifo.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include "rkfifo.h"
  2. #include <string.h>
  3. #define min(x,y) \
  4. ({ \
  5. typeof(x) _min1 = x; \
  6. typeof(y) _min2 = y; \
  7. (void)(&_min1 == &_min2); \
  8. _min1 < _min2 ? _min1 : _min2; \
  9. })
  10. #define max(x,y) \
  11. ({ \
  12. typeof(x) _max1 = x; \
  13. typeof(y) _max2 = y; \
  14. (void)(&_max1 == &_max2); \
  15. _max1 > _max2 ? _max1 : _max2; \
  16. })
  17. /* 检查是否是 2 的幂次数 */
  18. #define is_power_of_2(x) ((x) != 0 && (((x) & ((x)-1)) == 0))
  19. /**
  20. * @brief 返回输入参数的最高有效 bit 位
  21. *
  22. * @param x 输入参数
  23. * @return int 最高有效 bit 位, 从低到高 1~32, 0 表示无输入参数为 0
  24. */
  25. static inline int fls_int(int x)
  26. {
  27. int r = 32;
  28. if (!x)
  29. return 0;
  30. if (!(x & 0xffff0000u))
  31. {
  32. x <<= 16;
  33. r -= 16;
  34. }
  35. if (!(x & 0xff000000u))
  36. {
  37. x <<= 8;
  38. r -= 8;
  39. }
  40. if (!(x & 0xf0000000u))
  41. {
  42. x <<= 4;
  43. r -= 4;
  44. }
  45. if (!(x & 0xc0000000u))
  46. {
  47. x <<= 2;
  48. r -= 2;
  49. }
  50. if (!(x & 0x80000000u))
  51. {
  52. x <<= 1;
  53. r -= 1;
  54. }
  55. return r;
  56. }
  57. /**
  58. * @brief 找到 n 向下取最大的 2 的幂次数
  59. *
  60. * @param n 输入整数 n
  61. * @return uint32_t n 向下取最大的 2 的幂次数
  62. */
  63. static inline uint32_t rounddown_pow_of_two(uint32_t n)
  64. {
  65. if (0 == n || is_power_of_2(n))
  66. {
  67. return n;
  68. }
  69. else
  70. {
  71. return 1 << (fls_int(n) - 1);
  72. }
  73. }
  74. /**
  75. * @brief 查找 fifo 中的剩余空间
  76. *
  77. * @param fifo
  78. * @return unsigned int
  79. */
  80. static inline unsigned int kfifo_unused(rkfifo_t *fifo)
  81. {
  82. return (fifo->mask + 1) - (fifo->in - fifo->out);
  83. }
  84. int rkfifo_init(rkfifo_t *fifo, void *buffer, uint32_t size, uint32_t esize)
  85. {
  86. size /= esize;
  87. /* size 必须是 2 的幂次数 */
  88. if (!is_power_of_2(size))
  89. {
  90. size = rounddown_pow_of_two(size);
  91. }
  92. fifo->in = 0;
  93. fifo->out = 0;
  94. fifo->esize = esize;
  95. fifo->data = buffer;
  96. if (size < 2)
  97. {
  98. fifo->mask = 0;
  99. return -RKFIFO_EINVAL;
  100. }
  101. fifo->mask = size - 1;
  102. return 0;
  103. }
  104. static void __rkfifo_copy_in(rkfifo_t *fifo, const void *src, unsigned int len,
  105. unsigned int offset)
  106. {
  107. unsigned int size = fifo->mask + 1;
  108. unsigned int esize = fifo->esize;
  109. unsigned int l;
  110. offset &= fifo->mask;
  111. if (esize != 1)
  112. {
  113. offset *= esize;
  114. size *= esize;
  115. len *= esize;
  116. }
  117. l = min(len, size - offset);
  118. memcpy((uint8_t*)fifo->data + offset, src, l);
  119. memcpy(fifo->data, (uint8_t*)src + l, len - l);
  120. /* 多核处理器需要内存屏障 */
  121. /* smp_wmb(); */
  122. }
  123. unsigned int rkfifo_in(rkfifo_t *fifo, const void *buf, unsigned int len)
  124. {
  125. unsigned int l;
  126. l = kfifo_unused(fifo);
  127. if (len > l)
  128. len = l;
  129. __rkfifo_copy_in(fifo, buf, len, fifo->in);
  130. fifo->in += len;
  131. return len;
  132. }
  133. static void __rkfifo_copy_out(rkfifo_t *fifo, void *dst, unsigned int len,
  134. unsigned int off)
  135. {
  136. unsigned int size = fifo->mask + 1;
  137. unsigned int esize = fifo->esize;
  138. unsigned int l;
  139. off &= fifo->mask;
  140. if (esize != 1)
  141. {
  142. off *= esize;
  143. size *= esize;
  144. len *= esize;
  145. }
  146. l = min(len, size - off);
  147. memcpy(dst, (uint8_t*)fifo->data + off, l);
  148. memcpy((uint8_t*)dst + l, fifo->data, len - l);
  149. /* smp_wmb(); */
  150. }
  151. unsigned int rkfifo_out_peek(rkfifo_t *fifo, void *buf, unsigned int len)
  152. {
  153. unsigned int l;
  154. l = fifo->in - fifo->out;
  155. if (len > l)
  156. len = l;
  157. __rkfifo_copy_out(fifo, buf, len, fifo->out);
  158. return len;
  159. }
  160. unsigned int rkfifo_out(rkfifo_t *fifo, void *buf, unsigned int len)
  161. {
  162. len = rkfifo_out_peek(fifo, buf, len);
  163. fifo->out += len;
  164. return len;
  165. }