aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo.c189
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo.h424
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo_internal.h577
3 files changed, 1190 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo.c
new file mode 100644
index 0000000..5d7a8ff
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo.c
@@ -0,0 +1,189 @@
+/**
+ * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "app_util.h"
+#include "nrf_atfifo.h"
+#include "nrf_atfifo_internal.h"
+
+#if NRF_ATFIFO_CONFIG_LOG_ENABLED
+ #define NRF_LOG_LEVEL NRF_ATFIFO_CONFIG_LOG_LEVEL
+ #define NRF_LOG_INIT_FILTER_LEVEL NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL
+ #define NRF_LOG_INFO_COLOR NRF_ATFIFO_CONFIG_INFO_COLOR
+ #define NRF_LOG_DEBUG_COLOR NRF_ATFIFO_CONFIG_DEBUG_COLOR
+#else
+ #define NRF_LOG_LEVEL 0
+#endif // NRF_ATFIFO_CONFIG_LOG_ENABLED
+#include "nrf_log.h"
+
+/* Unions testing */
+STATIC_ASSERT(sizeof(nrf_atfifo_postag_t) == sizeof(uint32_t));
+
+
+ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size)
+{
+ if (NULL == p_buf)
+ {
+ NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. p_buf == NULL");
+ return NRF_ERROR_NULL;
+ }
+ if (0 != (buf_size % item_size))
+ {
+ NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. Buf_size not multiple of item_size");
+ return NRF_ERROR_INVALID_LENGTH;
+ }
+
+ p_fifo->p_buf = p_buf;
+ p_fifo->tail.tag = 0;
+ p_fifo->head.tag = 0;
+ p_fifo->buf_size = buf_size;
+ p_fifo->item_size = item_size;
+
+ NRF_LOG_INST_INFO(p_fifo->p_log, "Initialized.");
+ return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo)
+{
+ bool released = nrf_atfifo_space_clear(p_fifo);
+ NRF_LOG_INST_INFO(p_fifo->p_log, "Cleared result:%s", released ? "success" : "busy");
+ return released ? NRF_SUCCESS : NRF_ERROR_BUSY;
+}
+
+
+ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * p_var, size_t size, bool * const p_visible)
+{
+ nrf_atfifo_item_put_t context;
+ bool visible;
+ void * p_data = nrf_atfifo_item_alloc(p_fifo, &context);
+ if (NULL == p_data)
+ {
+ NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying in element (0x%08X) failed - no space.", p_var);
+ return NRF_ERROR_NO_MEM;
+ }
+
+ memcpy(p_data, p_var, size);
+
+ visible = nrf_atfifo_item_put(p_fifo, &context);
+ if (NULL != p_visible)
+ {
+ *p_visible = visible;
+ }
+ NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied in.", p_var);
+ return NRF_SUCCESS;
+}
+
+
+void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context)
+{
+ if (nrf_atfifo_wspace_req(p_fifo, &(p_context->last_tail)))
+ {
+ void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_tail.pos.wr;
+ NRF_LOG_INST_DEBUG(p_fifo->p_log, "Allocated element (0x%08X).", p_item);
+ return p_item;
+ }
+ NRF_LOG_INST_WARNING(p_fifo->p_log, "Allocation failed - no space.");
+ return NULL;
+}
+
+
+bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context)
+{
+ if ((p_context->last_tail.pos.wr) == (p_context->last_tail.pos.rd))
+ {
+ NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (uninterrupted)");
+ nrf_atfifo_wspace_close(p_fifo);
+ return true;
+ }
+ NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (interrupted!)");
+ return false;
+}
+
+
+ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released)
+{
+ nrf_atfifo_item_get_t context;
+ bool released;
+ void const * p_s = nrf_atfifo_item_get(p_fifo, &context);
+ if (NULL == p_s)
+ {
+ NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying out failed - no item in the FIFO.");
+ return NRF_ERROR_NOT_FOUND;
+ }
+
+ memcpy(p_var, p_s, size);
+
+ released = nrf_atfifo_item_free(p_fifo, &context);
+ if (NULL != p_released)
+ {
+ *p_released = released;
+ }
+ NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied out.", p_var);
+ return NRF_SUCCESS;
+}
+
+
+void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context)
+{
+ if (nrf_atfifo_rspace_req(p_fifo, &(p_context->last_head)))
+ {
+ void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_head.pos.rd;
+ NRF_LOG_INST_DEBUG(p_fifo->p_log, "Get element: 0x%08X", p_item);
+ return p_item;
+ }
+ NRF_LOG_INST_WARNING(p_fifo->p_log, "Get failed - no item in the FIFO.");
+ return NULL;
+}
+
+
+bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context)
+{
+ if ((p_context->last_head.pos.wr) == (p_context->last_head.pos.rd))
+ {
+ NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (uninterrupted)");
+ nrf_atfifo_rspace_close(p_fifo);
+ return true;
+ }
+ NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (interrupted)");
+ return false;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo.h
new file mode 100644
index 0000000..37cfc76
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo.h
@@ -0,0 +1,424 @@
+/**
+ * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NRF_ATFIFO_H__
+#define NRF_ATFIFO_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "sdk_config.h"
+#include "nordic_common.h"
+#include "nrf_assert.h"
+#include "sdk_errors.h"
+#include "nrf_log_instance.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrf_atfifo Atomic FIFO
+ * @ingroup app_common
+ *
+ * @brief @tagAPI52 FIFO implementation that allows for making atomic transactions without
+ * locking interrupts.
+ *
+ * @details There are two types of functions to prepare the FIFO writing:
+ * - Single function for simple access:
+ * @code
+ * if (NRF_SUCCESS != nrf_atfifo_simple_put(my_fifo, &data, NULL))
+ * {
+ * // Error handling
+ * }
+ * @endcode
+ * - Function pair to limit data copying:
+ * @code
+ * struct point3d
+ * {
+ * int x, y, z;
+ * }point3d_t;
+ * nrf_atfifo_context_t context;
+ * point3d_t * point;
+ *
+ * if (NULL != (point = nrf_atfifo_item_alloc(my_fifo, &context)))
+ * {
+ * point->x = a;
+ * point->y = b;
+ * point->z = c;
+ * if (nrf_atfifo_item_put(my_fifo, &context))
+ * {
+ * // Send information to the rest of the system
+ * // that there is new data in the FIFO available for reading.
+ * }
+ * }
+ * else
+ * {
+ * // Error handling
+ * }
+ *
+ * @endcode
+ * @note
+ * This atomic FIFO implementation requires that the operation that is
+ * opened last is finished (committed/flushed) first.
+ * This is typical for operations performed from the interrupt runtime
+ * when the other operation is performed from the main thread.
+ *
+ * This implementation does not support typical multithreading operating system
+ * access where operations can be started and finished in totally unrelated order.
+ *
+ * @{
+ */
+
+/**
+ * @brief Read and write position structure.
+ *
+ * A structure that holds the read and write position used by the FIFO head and tail.
+ */
+typedef struct nrf_atfifo_postag_pos_s
+{
+ uint16_t wr; //!< First free space to write the data
+ uint16_t rd; //!< A place after the last data to read
+}nrf_atfifo_postag_pos_t;
+
+/**
+ * @brief End data index tag.
+ *
+ * A tag used to mark the end of data.
+ * To properly realize atomic data committing, the whole variable has to be
+ * accessed atomically.
+ */
+typedef union nrf_atfifo_postag_u
+{
+ uint32_t tag; //!< Whole tag, used for atomic, 32-bit access
+ nrf_atfifo_postag_pos_t pos; //!< Structure that holds reading and writing position separately
+}nrf_atfifo_postag_t;
+
+/**
+ * @brief The FIFO instance.
+ *
+ * The instance of atomic FIFO.
+ * Used with all FIFO functions.
+ */
+typedef struct nrf_atfifo_s
+{
+ void * p_buf; //!< Pointer to the data buffer
+ nrf_atfifo_postag_t tail; //!< Read and write tail position tag
+ nrf_atfifo_postag_t head; //!< Read and write head position tag
+ uint16_t buf_size; //!< FIFO size in number of bytes (has to be divisible by @c item_size)
+ uint16_t item_size; //!< Size of a single FIFO item
+ NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled).
+}nrf_atfifo_t;
+
+/**
+ * @brief FIFO write operation item context.
+ *
+ * Context structure used to mark an allocated space in FIFO that is ready for put.
+ * All the data required to properly put allocated and written data.
+ */
+typedef struct nrf_atfifo_item_put_s
+{
+ nrf_atfifo_postag_t last_tail; //!< Tail tag value that was here when opening the FIFO to write
+}nrf_atfifo_item_put_t;
+
+
+/**
+ * @brief FIFO read operation item context.
+ *
+ * Context structure used to mark an opened get operation to properly free an item after reading.
+ */
+typedef struct nrf_atfifo_rcontext_s
+{
+ nrf_atfifo_postag_t last_head; //!< Head tag value that was here when opening the FIFO to read
+}nrf_atfifo_item_get_t;
+
+
+/** @brief Name of the module used for logger messaging.
+ */
+#define NRF_ATFIFO_LOG_NAME atfifo
+
+/**
+ * @defgroup nrf_atfifo_instmacros FIFO instance macros
+ *
+ * A group of macros helpful for FIFO instance creation and initialization.
+ * They may be used to create and initialize instances for most use cases.
+ *
+ * FIFO may also be created and initialized directly using
+ * @ref nrf_atfifo_init function.
+ * @{
+ */
+ /**
+ * @brief Macro for generating the name for a data buffer.
+ *
+ * The name of the data buffer that would be created by
+ * @ref NRF_ATFIFO_DEF macro.
+ *
+ * @param[in] fifo_id Identifier of the FIFO object.
+ *
+ * @return Name of the buffer variable.
+ *
+ * @note This is auxiliary internal macro and in normal usage
+ * it should not be called.
+ */
+ #define NRF_ATFIFO_BUF_NAME(fifo_id) CONCAT_2(fifo_id, _data)
+
+ /**
+ * @brief Macro for generating the name for a FIFO instance.
+ *
+ * The name of the instance variable that will be created by the
+ * @ref NRF_ATFIFO_DEF macro.
+ *
+ * @param[in] fifo_id Identifier of the FIFO object.
+ *
+ * @return Name of the instance variable.
+ *
+ * @note This is auxiliary internal macro and in normal usage
+ * it should not be called.
+ */
+ #define NRF_ATFIFO_INST_NAME(fifo_id) CONCAT_2(fifo_id, _inst)
+
+ /**
+ * @brief Macro for creating an instance.
+ *
+ * Creates the FIFO object variable itself.
+ *
+ * Usage example:
+ * @code
+ * NRF_ATFIFO_DEF(my_fifo, uint16_t, 12);
+ * NRF_ATFIFO_INIT(my_fifo);
+ *
+ * uint16_t some_val = 45;
+ * nrf_atfifo_item_put(my_fifo, &some_val, sizeof(some_val), NULL);
+ * nrf_atfifo_item_get(my_fifo, &some_val, sizeof(some_val), NULL);
+ * @endcode
+ *
+ * @param[in] fifo_id Identifier of a FIFO object.
+ * This identifier will be a pointer to the instance.
+ * It makes it possible to use this directly for the functions
+ * that operate on the FIFO.
+ * Because it is a static const object, it should be optimized by the compiler.
+ * @param[in] storage_type Type of data that will be stored in the FIFO.
+ * @param[in] item_cnt Capacity of the created FIFO in maximum number of items that may be stored.
+ * The phisical size of the buffer will be 1 element bigger.
+ */
+ #define NRF_ATFIFO_DEF(fifo_id, storage_type, item_cnt) \
+ static storage_type NRF_ATFIFO_BUF_NAME(fifo_id)[(item_cnt)+1]; \
+ NRF_LOG_INSTANCE_REGISTER(NRF_ATFIFO_LOG_NAME, fifo_id, \
+ NRF_ATFIFO_CONFIG_INFO_COLOR, \
+ NRF_ATFIFO_CONFIG_DEBUG_COLOR, \
+ NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL, \
+ NRF_ATFIFO_CONFIG_LOG_ENABLED ? \
+ NRF_ATFIFO_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \
+ static nrf_atfifo_t NRF_ATFIFO_INST_NAME(fifo_id) = { \
+ .p_buf = NULL, \
+ NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_ATFIFO_LOG_NAME, fifo_id) \
+ }; \
+ static nrf_atfifo_t * const fifo_id = &NRF_ATFIFO_INST_NAME(fifo_id)
+
+ /**
+ * @brief Macro for initializing the FIFO that was previously declared by the macro.
+ *
+ * Use this macro to simplify FIFO initialization.
+ *
+ * @note
+ * This macro can be only used on a FIFO object defined by @ref NRF_ATFIFO_DEF macro.
+ *
+ * @param[in] fifo_id Identifier of the FIFO object.
+ *
+ * @return Value from the @ref nrf_atfifo_init function.
+ */
+ #define NRF_ATFIFO_INIT(fifo_id) \
+ nrf_atfifo_init( \
+ fifo_id, \
+ NRF_ATFIFO_BUF_NAME(fifo_id), \
+ sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)), \
+ sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)[0]) \
+ )
+
+/** @} */
+
+/**
+ * @brief Function for initializing the FIFO.
+ *
+ * Preparing the FIFO instance to work.
+ *
+ * @param[out] p_fifo FIFO object to initialize.
+ * @param[in,out] p_buf FIFO buffer for storing data.
+ * @param[in] buf_size Total buffer size (has to be divisible by @c item_size).
+ * @param[in] item_size Size of a single item held inside the FIFO.
+ *
+ * @retval NRF_SUCCESS If initialization was successful.
+ * @retval NRF_ERROR_NULL If a NULL pointer is provided as the buffer.
+ * @retval NRF_ERROR_INVALID_LENGTH If size of the buffer provided is not divisible by @c item_size.
+ *
+ * @note
+ * Buffer size must be able to hold one element more than the designed FIFO capacity.
+ * This one, empty element is used for overflow checking.
+ */
+ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size);
+
+/**
+ * @brief Function for clearing the FIFO.
+ *
+ * Function for clearing the FIFO.
+ *
+ * If this function is called during an opened and uncommitted write operation,
+ * the FIFO is cleared up to the currently ongoing commit.
+ * There is no possibility to cancel an ongoing commit.
+ *
+ * If this function is called during an opened and unflushed read operation,
+ * the read position in the head is set, but copying it into the write head position
+ * is left to read closing operation.
+ *
+ * This way, there is no more data to read, but the memory is released
+ * in the moment when it is safe.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ *
+ * @retval NRF_SUCCESS FIFO totally cleared.
+ * @retval NRF_ERROR_BUSY Function called in the middle of writing or reading operation.
+ * If it is called in the middle of writing operation,
+ * FIFO was cleared up to the already started and uncommitted write.
+ * If it is called in the middle of reading operation,
+ * write head was only moved. It will be copied into read tail when the reading operation
+ * is flushed.
+ */
+ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo);
+
+/**
+ * @brief Function for atomically putting data into the FIFO.
+ *
+ * It uses memcpy function inside and in most situations, it is more suitable to
+ * use @ref nrf_atfifo_item_alloc, write the data, and @ref nrf_atfifo_item_put to store a new value
+ * in a FIFO.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ * @param[in] p_var Variable to copy.
+ * @param[in] size Size of the variable to copy.
+ * Can be smaller or equal to the FIFO item size.
+ * @param[out] p_visible See value returned by @ref nrf_atfifo_item_put.
+ * It may be NULL if the caller does not require the current operation status.
+ *
+ * @retval NRF_SUCCESS If an element has been successfully added to the FIFO.
+ * @retval NRF_ERROR_NO_MEM If the FIFO is full.
+ *
+ * @note
+ * To avoid data copying, you can use the @ref nrf_atfifo_item_alloc and @ref nrf_atfifo_item_put
+ * functions pair.
+ */
+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);
+
+/**
+ * @brief Function for opening the FIFO for writing.
+ *
+ * Function called to start the FIFO write operation and access the given FIFO buffer directly.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ * @param[out] p_context Operation context, required by @ref nrf_atfifo_item_put.
+ *
+ * @return Pointer to the space where variable data can be stored.
+ * NULL if there is no space in the buffer.
+ */
+void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context);
+
+/**
+ * @brief Function for closing the writing operation.
+ *
+ * Puts a previously allocated context into FIFO.
+ * This function must be called to commit an opened write operation.
+ * It sets all the buffers and marks the data, so that it is visible to read.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ * @param[in] p_context Operation context, filled by the @ref nrf_atfifo_item_alloc function.
+ *
+ * @retval true Data is currently ready and will be visible to read.
+ * @retval false The internal commit was marked, but the writing operation interrupted another writing operation.
+ * The data will be available to read when the interrupted operation is committed.
+ */
+bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context);
+
+/**
+ * @brief Function for getting a single value from the FIFO.
+ *
+ * This function gets the value from the top of the FIFO.
+ * The value is removed from the FIFO memory.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ * @param[out] p_var Pointer to the variable to store the data.
+ * @param[in] size Size of the data to be loaded.
+ * @param[out] p_released See the values returned by @ref nrf_atfifo_item_free.
+ *
+ * @retval NRF_SUCCESS Element was successfully copied from the FIFO memory.
+ * @retval NRF_ERROR_NOT_FOUND No data in the FIFO.
+ */
+ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released);
+
+/**
+ * @brief Function for opening the FIFO for reading.
+ *
+ * Function called to start the FIFO read operation and access the given FIFO buffer directly.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ * @param[out] p_context The operation context, required by @ref nrf_atfifo_item_free
+ *
+ * @return Pointer to data buffer or NULL if there is no data in the FIFO.
+ */
+void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context);
+
+/**
+ * @brief Function for closing the reading operation.
+ *
+ * Function used to finish the reading operation.
+ * If this reading operation does not interrupt another reading operation, the head write buffer is moved.
+ * If this reading operation is placed in the middle of another reading, only the new read pointer is written.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ * @param[in] p_context Context of the reading operation to be closed.
+ *
+ * @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).
+ * @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).
+ */
+bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRF_ATFIFO_H__ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo_internal.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo_internal.h
new file mode 100644
index 0000000..e38a223
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic_fifo/nrf_atfifo_internal.h
@@ -0,0 +1,577 @@
+/**
+ * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * @file
+ * @brief Atomic FIFO internal file
+ *
+ * This file should be included only by nrf_atfifo internally.
+ * Needs nrf_atfifo.h included first.
+ */
+#ifndef NRF_ATFIFO_H__
+#error This is internal file. Do not include this file in your program.
+#endif
+
+#ifndef NRF_ATFIFO_INTERNAL_H__
+#define NRF_ATFIFO_INTERNAL_H__
+#include <stddef.h>
+#include "nrf.h"
+#include "app_util.h"
+#include "nordic_common.h"
+
+#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0
+#error Unsupported core version
+#endif
+
+/*
+ * Make sure that rd and wr pos in a tag are aligned like expected
+ * Changing this would require changes inside assembly code!
+ */
+STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, wr) == 0);
+STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, rd) == 2);
+
+/**
+ * @brief Atomically reserve space for a new write.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ * @param[out] old_tail Tail position tag before new space is reserved.
+ *
+ * @retval true Space available.
+ * @retval false Memory full.
+ *
+ * @sa nrf_atfifo_wspace_close
+ */
+static bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail);
+
+/**
+ * @brief Atomically mark all written data available.
+ *
+ * This function marks all data available for reading.
+ * This marking is done by copying tail.pos.wr into tail.pos.rd.
+ *
+ * It must be called only when closing the first write.
+ * It cannot be called if any write access was interrupted.
+ * See the code below:
+ * @code
+ * if (old_tail.pos.wr == old_tail.pos.rd)
+ * {
+ * nrf_atfifo_wspace_close(my_fifo);
+ * return true;
+ * }
+ * return false;
+ * @endcode
+ *
+ * @param[in,out] p_fifo FIFO object.
+ *
+ * @sa nrf_atfifo_wspace_req
+ */
+static void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo);
+
+/**
+ * @brief Atomically get a part of a buffer to read data.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ * @param[out] old_head Head position tag before the data buffer is read.
+ *
+ * @retval true Data available for reading.
+ * @retval false No data in the buffer.
+ *
+ * @sa nrf_atfifo_rspace_close
+ */
+static bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head);
+
+/**
+ * @brief Atomically release all read data.
+ *
+ * This function marks all data that was read as free space,
+ * which is available for writing.
+ * This marking is done by copying head.pos.rd into head.pos.wr.
+ *
+ * It must be called only when closing the first read.
+ * It cannot be called when the current read access interrupted any other read access.
+ * See code below:
+ * @code
+ * if (old_head.pos.wr == old_head.pos.rd)
+ * {
+ * nrf_atfifo_rspace_close(my_fifo);
+ * return true;
+ * }
+ * return false;
+ * @endcode
+ *
+ * @param[in,out] p_fifo FIFO object.
+ *
+ * @sa nrf_atfifo_rspace_req
+ */
+static void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo);
+
+/**
+ * @brief Safely clear the FIFO, internal function.
+ *
+ * This function realizes the functionality required by @ref nrf_atfifo_clear.
+ *
+ * @param[in,out] p_fifo FIFO object.
+ *
+ * @retval true All the data was released.
+ * @retval false All the data available for releasing was released, but there is some pending transfer.
+ */
+static bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo);
+
+
+/* ---------------------------------------------------------------------------
+ * Implementation starts here
+ */
+
+#if defined ( __CC_ARM )
+
+
+__ASM bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail)
+{
+ /* Registry usage:
+ * R0 - p_fifo
+ * R1 - p_old_tail
+ * R2 - internal variable old_tail (saved by caller)
+ * R3 - internal variable new_tail (saved by caller)
+ * R4 - internal temporary register (saved by this function)
+ * R5 - not used stored to keep the stack aligned to 8 bytes
+ * Returned value:
+ * R0 (bool - 32 bits)
+ */
+ push {r4, r5}
+nrf_atfifo_wspace_req_repeat
+ /* Load tail tag and set memory monitor !!! R2 - old tail !!! */
+ ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))]
+ /* Extract write position !!! R3 !!! */
+ uxth r3, r2
+ /* Increment address with overload support !!! R4 used temporary !!! */
+ ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))]
+ add r3, r4
+ ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))]
+ cmp r3, r4
+ it hs
+ subhs r3, r3, r4
+
+ /* Check if FIFO would overload after making this increment !!! R4 used temporary !!! */
+ ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr))]
+ cmp r3, r4
+ ittt eq
+ clrexeq
+ moveq r0, #__cpp(false)
+ beq nrf_atfifo_wspace_req_exit
+
+ /* Pack everything back !!! R3 - new tail !!! */
+ /* Copy lower byte from new_tail, and higher byte is a value from the top of old_tail */
+ pkhbt r3, r3, r2
+
+ /* Store new value clearing memory monitor !!! R4 used temporary !!! */
+ strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))]
+ cmp r4, #0
+ bne nrf_atfifo_wspace_req_repeat
+
+ /* Return true */
+ mov r0, #__cpp(true)
+nrf_atfifo_wspace_req_exit
+ /* Save old tail */
+ str r2, [r1]
+ pop {r4, r5}
+ bx lr
+}
+
+
+__ASM void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo)
+{
+ /* Registry usage:
+ * R0 - p_fifo
+ * R1 - internal temporary register
+ * R2 - new_tail
+ */
+nrf_atfifo_wspace_close_repeat
+ ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))]
+ /* Copy from lower byte to higher */
+ pkhbt r2, r2, r2, lsl #16
+
+ strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))]
+ cmp r1, #0
+ bne nrf_atfifo_wspace_close_repeat
+ bx lr
+}
+
+
+__ASM bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head)
+{
+ /* Registry usage:
+ * R0 - p_fifo
+ * R1 - p_old_head
+ * R2 - internal variable old_head (saved by caller)
+ * R3 - internal variable new_head (saved by caller)
+ * R4 - internal temporary register (saved by this function)
+ * R5 - not used stored to keep the stack aligned to 8 bytes
+ * Returned value:
+ * R0 (bool - 32 bits)
+ */
+ push {r4, r5}
+nrf_atfifo_rspace_req_repeat
+ /* Load tail tag and set memory monitor !!! R2 - old tail !!! */
+ ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))]
+ /* Extract read position !!! R3 !!! */
+ uxth r3, r2, ror #16
+
+ /* Check if we have any data !!! R4 used temporary !!! */
+ ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))]
+ cmp r3, r4
+ ittt eq
+ clrexeq
+ moveq r0, #__cpp(false)
+ beq nrf_atfifo_rspace_req_exit
+
+ /* Increment address with overload support !!! R4 used temporary !!! */
+ ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))]
+ add r3, r4
+ ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))]
+ cmp r3, r4
+ it hs
+ subhs r3, r3, r4
+
+ /* Pack everything back !!! R3 - new tail !!! */
+ /* Copy lower byte from old_head, and higher byte is a value from write_pos */
+ pkhbt r3, r2, r3, lsl #16
+
+ /* Store new value clearing memory monitor !!! R4 used temporary !!! */
+ strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, head))]
+ cmp r4, #0
+ bne nrf_atfifo_rspace_req_repeat
+
+ /* Return true */
+ mov r0, #__cpp(true)
+nrf_atfifo_rspace_req_exit
+ /* Save old head */
+ str r2, [r1]
+ pop {r4, r5}
+ bx lr
+}
+
+
+__ASM void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo)
+{
+ /* Registry usage:
+ * R0 - p_fifo
+ * R1 - internal temporary register
+ * R2 - new_tail
+ */
+nrf_atfifo_rspace_close_repeat
+ ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))]
+ /* Copy from higher byte to lower */
+ pkhtb r2, r2, r2, asr #16
+
+ strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))]
+ cmp r1, #0
+ bne nrf_atfifo_rspace_close_repeat
+ bx lr
+}
+
+
+__ASM bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo)
+{
+ /* Registry usage:
+ * R0 - p_fifo as input, bool output after
+ * R1 - tail, rd pointer, new_head
+ * R2 - head_old, destroyed when creating new_head
+ * R3 - p_fifo - copy
+ */
+ mov r3, r0
+nrf_atfifo_space_clear_repeat
+ /* Load old head in !!! R2 register !!! and read pointer of tail in !!! R1 register !!! */
+ ldrex r2, [r3, #__cpp(offsetof(nrf_atfifo_t, head))]
+ ldrh r1, [r3, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))]
+ cmp r2, r2, ror #16
+ /* Return false as default */
+ mov r0, #__cpp(false)
+ /* Create new head in !!! R1 register !!! Data in !!! R2 register broken !!! */
+ itett ne
+ uxthne r2, r2
+ orreq r1, r1, r1, lsl #16
+ orrne r1, r2, r1, lsl #16
+
+ /* Skip header test */
+ bne nrf_atfifo_space_clear_head_test_skip
+
+ /* Load whole tail and test it !!! R2 used !!! */
+ ldr r2, [r3, #__cpp(offsetof(nrf_atfifo_t, tail))]
+ cmp r2, r2, ror #16
+ /* Return true if equal */
+ it eq
+ moveq r0, #__cpp(true)
+
+nrf_atfifo_space_clear_head_test_skip
+ /* Store and test if success !!! R2 used temporary !!! */
+ strex r2, r1, [r3, #__cpp(offsetof(nrf_atfifo_t, head))]
+ cmp r2, #0
+ bne nrf_atfifo_space_clear_repeat
+ bx lr
+}
+
+#elif defined ( __ICCARM__ ) || defined ( __GNUC__ )
+
+bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail)
+{
+ volatile bool ret;
+ volatile uint32_t old_tail;
+ uint32_t new_tail;
+ uint32_t temp;
+
+ __ASM volatile(
+ /* For more comments see Keil version above */
+ "1: \n"
+ " ldrex %[old_tail], [%[p_fifo], %[offset_tail]] \n"
+ " uxth %[new_tail], %[old_tail] \n"
+ " \n"
+ " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n"
+ " add %[new_tail], %[temp] \n"
+ " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n"
+ " cmp %[new_tail], %[temp] \n"
+ " it hs \n"
+ " subhs %[new_tail], %[new_tail], %[temp] \n"
+ " \n"
+ " ldrh %[temp], [%[p_fifo], %[offset_head_wr]] \n"
+ " cmp %[new_tail], %[temp] \n"
+ " ittt eq \n"
+ " clrexeq \n"
+ " moveq %[ret], %[false_val] \n"
+ " beq.n 2f \n"
+ " \n"
+ " pkhbt %[new_tail], %[new_tail], %[old_tail] \n"
+ " \n"
+ " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n"
+ " cmp %[temp], #0 \n"
+ " bne.n 1b \n"
+ " \n"
+ " mov %[ret], %[true_val] \n"
+ "2: \n"
+ : /* Output operands */
+ [ret] "=r"(ret),
+ [temp] "=&r"(temp),
+ [old_tail]"=&r"(old_tail),
+ [new_tail]"=&r"(new_tail)
+ : /* Input operands */
+ [p_fifo] "r"(p_fifo),
+ [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)),
+ [offset_head_wr] "J"(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr)),
+ [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)),
+ [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)),
+ [true_val] "I"(true),
+ [false_val] "I"(false)
+ : /* Clobbers */
+ "cc");
+
+ p_old_tail->tag = old_tail;
+ UNUSED_VARIABLE(new_tail);
+ UNUSED_VARIABLE(temp);
+ return ret;
+}
+
+
+void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo)
+{
+ uint32_t temp;
+ uint32_t new_tail;
+
+ __ASM volatile(
+ /* For more comments see Keil version above */
+ "1: \n"
+ " ldrex %[new_tail], [%[p_fifo], %[offset_tail]] \n"
+ " pkhbt %[new_tail],%[new_tail], %[new_tail], lsl #16 \n"
+ " \n"
+ " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n"
+ " cmp %[temp], #0 \n"
+ " bne.n 1b \n"
+ : /* Output operands */
+ [temp] "=&r"(temp),
+ [new_tail] "=&r"(new_tail)
+ : /* Input operands */
+ [p_fifo] "r"(p_fifo),
+ [offset_tail] "J"(offsetof(nrf_atfifo_t, tail))
+ : /* Clobbers */
+ "cc");
+
+ UNUSED_VARIABLE(temp);
+ UNUSED_VARIABLE(new_tail);
+}
+
+
+bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head)
+{
+ volatile bool ret;
+ volatile uint32_t old_head;
+ uint32_t new_head;
+ uint32_t temp;
+
+ __ASM volatile(
+ /* For more comments see Keil version above */
+ "1: \n"
+ " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n"
+ " uxth %[new_head], %[old_head], ror #16 \n"
+ " \n"
+ " ldrh %[temp], [%[p_fifo], %[offset_tail_rd]] \n"
+ " cmp %[new_head], %[temp] \n"
+ " ittt eq \n"
+ " clrexeq \n"
+ " moveq %[ret], %[false_val] \n"
+ " beq.n 2f \n"
+ " \n"
+ " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n"
+ " add %[new_head], %[temp] \n"
+ " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n"
+ " cmp %[new_head], %[temp] \n"
+ " it hs \n"
+ " subhs %[new_head], %[new_head], %[temp] \n"
+ " \n"
+ " pkhbt %[new_head], %[old_head], %[new_head], lsl #16 \n"
+ " \n"
+ " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n"
+ " cmp %[temp], #0 \n"
+ " bne.n 1b \n"
+ " \n"
+ " mov %[ret], %[true_val] \n"
+ "2: \n"
+ : /* Output operands */
+ [ret] "=r"(ret),
+ [temp] "=&r"(temp),
+ [old_head]"=&r"(old_head),
+ [new_head]"=&r"(new_head)
+ : /* Input operands */
+ [p_fifo] "r"(p_fifo),
+ [offset_head] "J"(offsetof(nrf_atfifo_t, head)),
+ [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)),
+ [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)),
+ [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)),
+ [true_val] "I"(true),
+ [false_val] "I"(false)
+ : /* Clobbers */
+ "cc");
+
+ p_old_head->tag = old_head;
+ UNUSED_VARIABLE(new_head);
+ UNUSED_VARIABLE(temp);
+ return ret;
+}
+
+
+void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo)
+{
+ uint32_t temp;
+ uint32_t new_head;
+
+ __ASM volatile(
+ /* For more comments see Keil version above */
+ "1: \n"
+ " ldrex %[new_head], [%[p_fifo], %[offset_head]] \n"
+ " pkhtb %[new_head],%[new_head], %[new_head], asr #16 \n"
+ " \n"
+ " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n"
+ " cmp %[temp], #0 \n"
+ " bne.n 1b \n"
+ : /* Output operands */
+ [temp] "=&r"(temp),
+ [new_head] "=&r"(new_head)
+ : /* Input operands */
+ [p_fifo] "r"(p_fifo),
+ [offset_head] "J"(offsetof(nrf_atfifo_t, head))
+ : /* Clobbers */
+ "cc");
+
+ UNUSED_VARIABLE(temp);
+ UNUSED_VARIABLE(new_head);
+}
+
+
+bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo)
+{
+ volatile bool ret;
+ uint32_t old_head; /* This variable is left broken after assembly code finishes */
+ uint32_t new_head;
+
+ __ASM volatile(
+ "1: \n"
+ " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n"
+ " ldrh %[new_head], [%[p_fifo], %[offset_tail_rd]] \n"
+ " cmp %[old_head], %[old_head], ror #16 \n"
+ " \n"
+ " mov %[ret], %[false_val] \n"
+ " \n"
+ " itett ne \n"
+ " uxthne %[old_head], %[old_head] \n"
+ " orreq %[new_head], %[new_head], %[new_head], lsl #16 \n"
+ " orrne %[new_head], %[old_head], %[new_head], lsl #16 \n"
+ " \n"
+ " bne.n 2f \n"
+ " \n"
+ " ldr %[old_head], [%[p_fifo], %[offset_tail]] \n"
+ " cmp %[old_head], %[old_head], ror #16 \n"
+ " it eq \n"
+ " moveq %[ret], %[true_val] \n"
+ " \n"
+ "2: \n"
+ " strex %[old_head], %[new_head], [%[p_fifo], %[offset_head]] \n"
+ " cmp %[old_head], #0 \n"
+ " bne.n 1b \n"
+ : /* Output operands */
+ [ret] "=&r"(ret),
+ [old_head] "=&r"(old_head),
+ [new_head] "=&r"(new_head)
+ : /* Input operands */
+ [p_fifo] "r"(p_fifo),
+ [offset_head] "J"(offsetof(nrf_atfifo_t, head)),
+ [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)),
+ [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)),
+ [true_val] "I"(true),
+ [false_val] "I"(false)
+ : /* Clobbers */
+ "cc");
+
+ UNUSED_VARIABLE(old_head);
+ UNUSED_VARIABLE(new_head);
+ return ret;
+}
+
+#else
+#error Unsupported compiler
+#endif
+
+#endif /* NRF_ATFIFO_INTERNAL_H__ */