rkfifo.c 4.4 KB

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