RingBuffer.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: RingBuffer.cpp
  4. * Description: Implementation of the Ring buffer.
  5. *
  6. * $Date: 30 July 2021
  7. * $Revision: V1.10.0
  8. *
  9. * Target Processor: Cortex-M and Cortex-A cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the License); you may
  17. * not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  24. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. */
  28. /*
  29. RTOS dependent definitions must be in RingPrivate.h.
  30. Without a RingPrivate.h, this code cannot work.
  31. */
  32. #include "RingPrivate.h"
  33. #include "RingBuffer.h"
  34. /*
  35. RTOS Integration
  36. */
  37. #ifndef RING_BEGINCRITICALSECTION
  38. #define RING_BEGINCRITICALSECTION()
  39. #endif
  40. #ifndef RING_ENDCRITICALSECTION
  41. #define RING_ENDCRITICALSECTION()
  42. #endif
  43. #ifndef RING_WAIT_BUFFER
  44. #define RING_WAIT_BUFFER(ID) 0
  45. #endif
  46. #ifndef RING_RELEASE_BUFFER
  47. #define RING_RELEASE_BUFFER(THREADID)
  48. #endif
  49. #ifndef RING_HASWAITERROR
  50. #define RING_HASWAITERROR(ERR) 0
  51. #endif
  52. /*
  53. Debug integration
  54. */
  55. #ifndef RING_DBG_USER_RESERVE_BUFFER
  56. #define RING_DBG_USER_RESERVE_BUFFER(ID,CONF)
  57. #endif
  58. #ifndef RING_DBG_USER_RELEASE_BUFFER
  59. #define RING_DBG_USER_RELEASE_BUFFER(ID,CONF)
  60. #endif
  61. #ifndef RING_DBG_USER_WAIT_BUFFER
  62. #define RING_DBG_USER_WAIT_BUFFER(ID,CONF)
  63. #endif
  64. #ifndef RING_DBG_USER_BUFFER_RELEASED
  65. #define RING_DBG_USER_BUFFER_RELEASED(ID,CONF)
  66. #endif
  67. #ifndef RING_DBG_USER_STATUS
  68. #define RING_DBG_USER_STATUS(SA,SB,CONF)
  69. #endif
  70. #ifndef RING_DBG_INT_RESERVE_BUFFER
  71. #define RING_DBG_INT_RESERVE_BUFFER(ID,CONF)
  72. #endif
  73. #ifndef RING_DBG_INT_RELEASE_BUFFER
  74. #define RING_DBG_INT_RELEASE_BUFFER(ID,CONF)
  75. #endif
  76. #ifndef RING_DBG_INT_RELEASE_USER
  77. #define RING_DBG_INT_RELEASE_USER(CONF)
  78. #endif
  79. #ifndef RING_DBG_INT_STATUS
  80. #define RING_DBG_INT_STATUS(SA,SB,CONF)
  81. #endif
  82. #ifndef RING_DBG_ERROR
  83. #define RING_DBG_ERROR(ERROR,CONF)
  84. #endif
  85. /*
  86. Implementation
  87. */
  88. #define RING_SET(FIELD,BIT) (config->FIELD) |= (1 << (config->BIT))
  89. #define RING_CLEAR(FIELD,BIT) (config->FIELD) &= ~(1 << (config->BIT))
  90. #define RING_TEST(FIELD,BIT) (((config->FIELD) & (1 << (config->BIT))) != 0)
  91. #define RING_INC(ID) \
  92. config->ID++; \
  93. if (config->ID == config->nbBuffers)\
  94. { \
  95. config->ID=0; \
  96. }
  97. #define RING_BUSY(ID) \
  98. (RING_TEST(userBufferStatus,ID) || RING_TEST(intBufferStatus,ID))
  99. void ringInit(ring_config_t *config,
  100. uint32_t nbBuffers,
  101. uint32_t bufferSize,
  102. uint8_t *buffer,
  103. int interruptID,
  104. int timeout)
  105. {
  106. config->buffer=buffer;
  107. config->nbBuffers = nbBuffers;
  108. config->bufferSize = bufferSize;
  109. config->interruptBufferIDStart = 0;
  110. config->interruptBufferIDStop = 0;
  111. config->userBufferIDStart = 0;
  112. config->userBufferIDStop = 0;
  113. config->error=kNoError;
  114. config->waiting=0;
  115. config->timeout=timeout;
  116. config->interruptID = interruptID;
  117. config->userBufferStatus = 0;
  118. config->intBufferStatus = 0;
  119. }
  120. void ringClean(ring_config_t *config)
  121. {
  122. }
  123. uint8_t *ringGetBufferAddress(ring_config_t *config,int id)
  124. {
  125. if (id < 0)
  126. {
  127. return(NULL);
  128. }
  129. else
  130. {
  131. return(&config->buffer[id*config->bufferSize]);
  132. }
  133. }
  134. int ringInterruptReserveBuffer(ring_config_t *config)
  135. {
  136. RING_DBG_INT_STATUS(userBufferStatus,intBufferStatus,config);
  137. if (config->error)
  138. {
  139. return(-1);
  140. }
  141. /* Try to reserve a buffer */
  142. if (RING_BUSY(interruptBufferIDStop))
  143. {
  144. /* If buffer is already used then kErrorOverflowUnderflow*/
  145. config->error=kErrorOverflowUnderflow;
  146. RING_DBG_ERROR(config->error,config);
  147. return(-1);
  148. }
  149. else
  150. {
  151. RING_DBG_INT_RESERVE_BUFFER(config->interruptBufferIDStop,config);
  152. RING_SET(intBufferStatus,interruptBufferIDStop);
  153. RING_DBG_INT_STATUS(userBufferStatus,intBufferStatus,config);
  154. int id=config->interruptBufferIDStop;
  155. RING_INC(interruptBufferIDStop);
  156. return(id);
  157. }
  158. }
  159. void ringInterruptReleaseBuffer(ring_config_t *config,void *threadId)
  160. {
  161. RING_DBG_INT_STATUS(userBufferStatus,intBufferStatus,config);
  162. if (config->error)
  163. {
  164. return;
  165. }
  166. if (config->interruptBufferIDStart != config->interruptBufferIDStop)
  167. {
  168. RING_DBG_INT_RELEASE_BUFFER(config->interruptBufferIDStart,config);
  169. RING_CLEAR(intBufferStatus,interruptBufferIDStart);
  170. /* Send release message in case the thread may be waiting */
  171. if (config->interruptBufferIDStart == config->userBufferIDStop)
  172. {
  173. if (config->waiting)
  174. {
  175. RING_DBG_INT_RELEASE_USER(config);
  176. RING_RELEASE_BUFFER(threadId);
  177. }
  178. }
  179. RING_INC(interruptBufferIDStart);
  180. }
  181. }
  182. int ringUserReserveBuffer(ring_config_t *config)
  183. {
  184. RING_BEGINCRITICALSECTION();
  185. RING_DBG_USER_STATUS(userBufferStatus,intBufferStatus,config);
  186. if (config->error)
  187. {
  188. RING_ENDCRITICALSECTION();
  189. return(-1);
  190. }
  191. /* If buffer is busy we wait*/
  192. if (RING_BUSY(userBufferIDStop))
  193. {
  194. config->waiting=1;
  195. RING_DBG_USER_WAIT_BUFFER(config->userBufferIDStop,config);
  196. RING_ENDCRITICALSECTION();
  197. int err = RING_WAIT_BUFFER(config->timeout);
  198. RING_BEGINCRITICALSECTION();
  199. RING_DBG_USER_BUFFER_RELEASED(config->userBufferIDStop,config);
  200. if (RING_HASWAITERROR(err))
  201. {
  202. RING_DBG_ERROR(err,config);
  203. config->error=kTimeout;
  204. return(-1);
  205. }
  206. }
  207. RING_DBG_USER_RESERVE_BUFFER(config->userBufferIDStop,config);
  208. RING_SET(userBufferStatus,userBufferIDStop);
  209. int id=config->userBufferIDStop;
  210. RING_INC(userBufferIDStop);
  211. RING_ENDCRITICALSECTION();
  212. return(id);
  213. }
  214. void ringUserReleaseBuffer(ring_config_t *config)
  215. {
  216. RING_BEGINCRITICALSECTION();
  217. RING_DBG_USER_STATUS(userBufferStatus,intBufferStatus,config);
  218. if (config->error)
  219. {
  220. RING_ENDCRITICALSECTION();
  221. return;
  222. }
  223. if (config->userBufferIDStart != config->userBufferIDStop)
  224. {
  225. RING_DBG_USER_RELEASE_BUFFER(config->userBufferIDStart,config);
  226. RING_CLEAR(userBufferStatus,userBufferIDStart);
  227. RING_INC(userBufferIDStart);
  228. }
  229. RING_ENDCRITICALSECTION();
  230. }