| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577 | 
							- /**
 
-  * Copyright (c) 2011 - 2020, 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__ */
 
 
  |