nrf_atfifo.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /**
  2. * Copyright (c) 2011 - 2019, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #ifndef NRF_ATFIFO_H__
  41. #define NRF_ATFIFO_H__
  42. #include <stdint.h>
  43. #include <stdbool.h>
  44. #include "sdk_config.h"
  45. #include "nordic_common.h"
  46. #include "nrf_assert.h"
  47. #include "sdk_errors.h"
  48. #include "nrf_log_instance.h"
  49. #ifdef __cplusplus
  50. extern "C" {
  51. #endif
  52. /**
  53. * @defgroup nrf_atfifo Atomic FIFO
  54. * @ingroup app_common
  55. *
  56. * @brief @tagAPI52 FIFO implementation that allows for making atomic transactions without
  57. * locking interrupts.
  58. *
  59. * @details There are two types of functions to prepare the FIFO writing:
  60. * - Single function for simple access:
  61. * @code
  62. * if (NRF_SUCCESS != nrf_atfifo_simple_put(my_fifo, &data, NULL))
  63. * {
  64. * // Error handling
  65. * }
  66. * @endcode
  67. * - Function pair to limit data copying:
  68. * @code
  69. * struct point3d
  70. * {
  71. * int x, y, z;
  72. * }point3d_t;
  73. * nrf_atfifo_context_t context;
  74. * point3d_t * point;
  75. *
  76. * if (NULL != (point = nrf_atfifo_item_alloc(my_fifo, &context)))
  77. * {
  78. * point->x = a;
  79. * point->y = b;
  80. * point->z = c;
  81. * if (nrf_atfifo_item_put(my_fifo, &context))
  82. * {
  83. * // Send information to the rest of the system
  84. * // that there is new data in the FIFO available for reading.
  85. * }
  86. * }
  87. * else
  88. * {
  89. * // Error handling
  90. * }
  91. *
  92. * @endcode
  93. * @note
  94. * This atomic FIFO implementation requires that the operation that is
  95. * opened last is finished (committed/flushed) first.
  96. * This is typical for operations performed from the interrupt runtime
  97. * when the other operation is performed from the main thread.
  98. *
  99. * This implementation does not support typical multithreading operating system
  100. * access where operations can be started and finished in totally unrelated order.
  101. *
  102. * @{
  103. */
  104. /**
  105. * @brief Read and write position structure.
  106. *
  107. * A structure that holds the read and write position used by the FIFO head and tail.
  108. */
  109. typedef struct nrf_atfifo_postag_pos_s
  110. {
  111. uint16_t wr; //!< First free space to write the data
  112. uint16_t rd; //!< A place after the last data to read
  113. }nrf_atfifo_postag_pos_t;
  114. /**
  115. * @brief End data index tag.
  116. *
  117. * A tag used to mark the end of data.
  118. * To properly realize atomic data committing, the whole variable has to be
  119. * accessed atomically.
  120. */
  121. typedef union nrf_atfifo_postag_u
  122. {
  123. uint32_t tag; //!< Whole tag, used for atomic, 32-bit access
  124. nrf_atfifo_postag_pos_t pos; //!< Structure that holds reading and writing position separately
  125. }nrf_atfifo_postag_t;
  126. /**
  127. * @brief The FIFO instance.
  128. *
  129. * The instance of atomic FIFO.
  130. * Used with all FIFO functions.
  131. */
  132. typedef struct nrf_atfifo_s
  133. {
  134. void * p_buf; //!< Pointer to the data buffer
  135. nrf_atfifo_postag_t tail; //!< Read and write tail position tag
  136. nrf_atfifo_postag_t head; //!< Read and write head position tag
  137. uint16_t buf_size; //!< FIFO size in number of bytes (has to be divisible by @c item_size)
  138. uint16_t item_size; //!< Size of a single FIFO item
  139. NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled).
  140. }nrf_atfifo_t;
  141. /**
  142. * @brief FIFO write operation item context.
  143. *
  144. * Context structure used to mark an allocated space in FIFO that is ready for put.
  145. * All the data required to properly put allocated and written data.
  146. */
  147. typedef struct nrf_atfifo_item_put_s
  148. {
  149. nrf_atfifo_postag_t last_tail; //!< Tail tag value that was here when opening the FIFO to write
  150. }nrf_atfifo_item_put_t;
  151. /**
  152. * @brief FIFO read operation item context.
  153. *
  154. * Context structure used to mark an opened get operation to properly free an item after reading.
  155. */
  156. typedef struct nrf_atfifo_rcontext_s
  157. {
  158. nrf_atfifo_postag_t last_head; //!< Head tag value that was here when opening the FIFO to read
  159. }nrf_atfifo_item_get_t;
  160. /** @brief Name of the module used for logger messaging.
  161. */
  162. #define NRF_ATFIFO_LOG_NAME atfifo
  163. /**
  164. * @defgroup nrf_atfifo_instmacros FIFO instance macros
  165. *
  166. * A group of macros helpful for FIFO instance creation and initialization.
  167. * They may be used to create and initialize instances for most use cases.
  168. *
  169. * FIFO may also be created and initialized directly using
  170. * @ref nrf_atfifo_init function.
  171. * @{
  172. */
  173. /**
  174. * @brief Macro for generating the name for a data buffer.
  175. *
  176. * The name of the data buffer that would be created by
  177. * @ref NRF_ATFIFO_DEF macro.
  178. *
  179. * @param[in] fifo_id Identifier of the FIFO object.
  180. *
  181. * @return Name of the buffer variable.
  182. *
  183. * @note This is auxiliary internal macro and in normal usage
  184. * it should not be called.
  185. */
  186. #define NRF_ATFIFO_BUF_NAME(fifo_id) CONCAT_2(fifo_id, _data)
  187. /**
  188. * @brief Macro for generating the name for a FIFO instance.
  189. *
  190. * The name of the instance variable that will be created by the
  191. * @ref NRF_ATFIFO_DEF macro.
  192. *
  193. * @param[in] fifo_id Identifier of the FIFO object.
  194. *
  195. * @return Name of the instance variable.
  196. *
  197. * @note This is auxiliary internal macro and in normal usage
  198. * it should not be called.
  199. */
  200. #define NRF_ATFIFO_INST_NAME(fifo_id) CONCAT_2(fifo_id, _inst)
  201. /**
  202. * @brief Macro for creating an instance.
  203. *
  204. * Creates the FIFO object variable itself.
  205. *
  206. * Usage example:
  207. * @code
  208. * NRF_ATFIFO_DEF(my_fifo, uint16_t, 12);
  209. * NRF_ATFIFO_INIT(my_fifo);
  210. *
  211. * uint16_t some_val = 45;
  212. * nrf_atfifo_item_put(my_fifo, &some_val, sizeof(some_val), NULL);
  213. * nrf_atfifo_item_get(my_fifo, &some_val, sizeof(some_val), NULL);
  214. * @endcode
  215. *
  216. * @param[in] fifo_id Identifier of a FIFO object.
  217. * This identifier will be a pointer to the instance.
  218. * It makes it possible to use this directly for the functions
  219. * that operate on the FIFO.
  220. * Because it is a static const object, it should be optimized by the compiler.
  221. * @param[in] storage_type Type of data that will be stored in the FIFO.
  222. * @param[in] item_cnt Capacity of the created FIFO in maximum number of items that may be stored.
  223. * The phisical size of the buffer will be 1 element bigger.
  224. */
  225. #define NRF_ATFIFO_DEF(fifo_id, storage_type, item_cnt) \
  226. static storage_type NRF_ATFIFO_BUF_NAME(fifo_id)[(item_cnt)+1]; \
  227. NRF_LOG_INSTANCE_REGISTER(NRF_ATFIFO_LOG_NAME, fifo_id, \
  228. NRF_ATFIFO_CONFIG_INFO_COLOR, \
  229. NRF_ATFIFO_CONFIG_DEBUG_COLOR, \
  230. NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL, \
  231. NRF_ATFIFO_CONFIG_LOG_ENABLED ? \
  232. NRF_ATFIFO_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \
  233. static nrf_atfifo_t NRF_ATFIFO_INST_NAME(fifo_id) = { \
  234. .p_buf = NULL, \
  235. NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_ATFIFO_LOG_NAME, fifo_id) \
  236. }; \
  237. static nrf_atfifo_t * const fifo_id = &NRF_ATFIFO_INST_NAME(fifo_id)
  238. /**
  239. * @brief Macro for initializing the FIFO that was previously declared by the macro.
  240. *
  241. * Use this macro to simplify FIFO initialization.
  242. *
  243. * @note
  244. * This macro can be only used on a FIFO object defined by @ref NRF_ATFIFO_DEF macro.
  245. *
  246. * @param[in] fifo_id Identifier of the FIFO object.
  247. *
  248. * @return Value from the @ref nrf_atfifo_init function.
  249. */
  250. #define NRF_ATFIFO_INIT(fifo_id) \
  251. nrf_atfifo_init( \
  252. fifo_id, \
  253. NRF_ATFIFO_BUF_NAME(fifo_id), \
  254. sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)), \
  255. sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)[0]) \
  256. )
  257. /** @} */
  258. /**
  259. * @brief Function for initializing the FIFO.
  260. *
  261. * Preparing the FIFO instance to work.
  262. *
  263. * @param[out] p_fifo FIFO object to initialize.
  264. * @param[in,out] p_buf FIFO buffer for storing data.
  265. * @param[in] buf_size Total buffer size (has to be divisible by @c item_size).
  266. * @param[in] item_size Size of a single item held inside the FIFO.
  267. *
  268. * @retval NRF_SUCCESS If initialization was successful.
  269. * @retval NRF_ERROR_NULL If a NULL pointer is provided as the buffer.
  270. * @retval NRF_ERROR_INVALID_LENGTH If size of the buffer provided is not divisible by @c item_size.
  271. *
  272. * @note
  273. * Buffer size must be able to hold one element more than the designed FIFO capacity.
  274. * This one, empty element is used for overflow checking.
  275. */
  276. ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size);
  277. /**
  278. * @brief Function for clearing the FIFO.
  279. *
  280. * Function for clearing the FIFO.
  281. *
  282. * If this function is called during an opened and uncommitted write operation,
  283. * the FIFO is cleared up to the currently ongoing commit.
  284. * There is no possibility to cancel an ongoing commit.
  285. *
  286. * If this function is called during an opened and unflushed read operation,
  287. * the read position in the head is set, but copying it into the write head position
  288. * is left to read closing operation.
  289. *
  290. * This way, there is no more data to read, but the memory is released
  291. * in the moment when it is safe.
  292. *
  293. * @param[in,out] p_fifo FIFO object.
  294. *
  295. * @retval NRF_SUCCESS FIFO totally cleared.
  296. * @retval NRF_ERROR_BUSY Function called in the middle of writing or reading operation.
  297. * If it is called in the middle of writing operation,
  298. * FIFO was cleared up to the already started and uncommitted write.
  299. * If it is called in the middle of reading operation,
  300. * write head was only moved. It will be copied into read tail when the reading operation
  301. * is flushed.
  302. */
  303. ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo);
  304. /**
  305. * @brief Function for atomically putting data into the FIFO.
  306. *
  307. * It uses memcpy function inside and in most situations, it is more suitable to
  308. * use @ref nrf_atfifo_item_alloc, write the data, and @ref nrf_atfifo_item_put to store a new value
  309. * in a FIFO.
  310. *
  311. * @param[in,out] p_fifo FIFO object.
  312. * @param[in] p_var Variable to copy.
  313. * @param[in] size Size of the variable to copy.
  314. * Can be smaller or equal to the FIFO item size.
  315. * @param[out] p_visible See value returned by @ref nrf_atfifo_item_put.
  316. * It may be NULL if the caller does not require the current operation status.
  317. *
  318. * @retval NRF_SUCCESS If an element has been successfully added to the FIFO.
  319. * @retval NRF_ERROR_NO_MEM If the FIFO is full.
  320. *
  321. * @note
  322. * To avoid data copying, you can use the @ref nrf_atfifo_item_alloc and @ref nrf_atfifo_item_put
  323. * functions pair.
  324. */
  325. ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * const p_var, size_t size, bool * const p_visible);
  326. /**
  327. * @brief Function for opening the FIFO for writing.
  328. *
  329. * Function called to start the FIFO write operation and access the given FIFO buffer directly.
  330. *
  331. * @param[in,out] p_fifo FIFO object.
  332. * @param[out] p_context Operation context, required by @ref nrf_atfifo_item_put.
  333. *
  334. * @return Pointer to the space where variable data can be stored.
  335. * NULL if there is no space in the buffer.
  336. */
  337. void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context);
  338. /**
  339. * @brief Function for closing the writing operation.
  340. *
  341. * Puts a previously allocated context into FIFO.
  342. * This function must be called to commit an opened write operation.
  343. * It sets all the buffers and marks the data, so that it is visible to read.
  344. *
  345. * @param[in,out] p_fifo FIFO object.
  346. * @param[in] p_context Operation context, filled by the @ref nrf_atfifo_item_alloc function.
  347. *
  348. * @retval true Data is currently ready and will be visible to read.
  349. * @retval false The internal commit was marked, but the writing operation interrupted another writing operation.
  350. * The data will be available to read when the interrupted operation is committed.
  351. */
  352. bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context);
  353. /**
  354. * @brief Function for getting a single value from the FIFO.
  355. *
  356. * This function gets the value from the top of the FIFO.
  357. * The value is removed from the FIFO memory.
  358. *
  359. * @param[in,out] p_fifo FIFO object.
  360. * @param[out] p_var Pointer to the variable to store the data.
  361. * @param[in] size Size of the data to be loaded.
  362. * @param[out] p_released See the values returned by @ref nrf_atfifo_item_free.
  363. *
  364. * @retval NRF_SUCCESS Element was successfully copied from the FIFO memory.
  365. * @retval NRF_ERROR_NOT_FOUND No data in the FIFO.
  366. */
  367. ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released);
  368. /**
  369. * @brief Function for opening the FIFO for reading.
  370. *
  371. * Function called to start the FIFO read operation and access the given FIFO buffer directly.
  372. *
  373. * @param[in,out] p_fifo FIFO object.
  374. * @param[out] p_context The operation context, required by @ref nrf_atfifo_item_free
  375. *
  376. * @return Pointer to data buffer or NULL if there is no data in the FIFO.
  377. */
  378. void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context);
  379. /**
  380. * @brief Function for closing the reading operation.
  381. *
  382. * Function used to finish the reading operation.
  383. * If this reading operation does not interrupt another reading operation, the head write buffer is moved.
  384. * If this reading operation is placed in the middle of another reading, only the new read pointer is written.
  385. *
  386. * @param[in,out] p_fifo FIFO object.
  387. * @param[in] p_context Context of the reading operation to be closed.
  388. *
  389. * @retval true This operation is not generated in the middle of another read operation and the write head will be updated to the read head (space is released).
  390. * @retval false This operation was performed in the middle of another read operation and the write buffer head was not moved (no space is released).
  391. */
  392. bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context);
  393. /** @} */
  394. #ifdef __cplusplus
  395. }
  396. #endif
  397. #endif /* NRF_ATFIFO_H__ */