From 3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 23 Aug 2018 17:08:59 +0200 Subject: o Initial import. --- .../components/libraries/atomic/nrf_atomic.c | 447 +++++++++++++++++++++ .../components/libraries/atomic/nrf_atomic.h | 274 +++++++++++++ .../libraries/atomic/nrf_atomic_internal.h | 343 ++++++++++++++++ .../libraries/atomic/nrf_atomic_sanity_check.h | 153 +++++++ 4 files changed, 1217 insertions(+) create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic_internal.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic_sanity_check.h (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic') diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic.c new file mode 100644 index 0000000..8d1609f --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic.c @@ -0,0 +1,447 @@ +/** + * Copyright (c) 2018 - 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 "nrf_atomic.h" + +#ifndef NRF_ATOMIC_USE_BUILD_IN +#if (defined(__GNUC__) && defined(WIN32)) + #define NRF_ATOMIC_USE_BUILD_IN 1 +#else + #define NRF_ATOMIC_USE_BUILD_IN 0 +#endif +#endif // NRF_ATOMIC_USE_BUILD_IN + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) +#define STREX_LDREX_PRESENT +#else +#include "app_util_platform.h" +#endif + + +#if (NRF_ATOMIC_USE_BUILD_IN == 0) && defined(STREX_LDREX_PRESENT) +#include "nrf_atomic_internal.h" +#endif + +uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_exchange_n(p_data, value, __ATOMIC_SEQ_CST); + +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data = value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + __atomic_store_n(p_data, value, __ATOMIC_SEQ_CST); + return value; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data = value; + CRITICAL_REGION_EXIT(); + return value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_or(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data |= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_or_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data |= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_and(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data &= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_and_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data &= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_xor(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data ^= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_xor_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data ^= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_add(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data += value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_add_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data += value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_sub(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_sub_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t desired) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_compare_exchange(p_data, + p_expected, + &desired, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + return nrf_atomic_internal_cmp_exch(p_data, p_expected, desired); +#else + CRITICAL_REGION_ENTER(); + if(*p_data == *p_expected) + { + *p_data = desired; + return true; + } + else + { + *p_expected = *p_data; + return false; + } + CRITICAL_REGION_EXIT(); +#endif +} + +uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + uint32_t expected = *p_data; + uint32_t new_val; + bool success; + + do + { + if (expected >= value) + { + new_val = expected - value; + } + else + { + new_val = expected; + } + success = __atomic_compare_exchange(p_data, + &expected, + &new_val, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + } while(!success); + return expected; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + uint32_t expected = *p_data; + uint32_t new_val; + bool success; + + do + { + if (expected >= value) + { + new_val = expected - value; + } + else + { + new_val = expected; + } + success = __atomic_compare_exchange(p_data, + &expected, + &new_val, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + } while(!success); + return new_val; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_or(p_data, 1); +} + +uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_or(p_data, 1); +} + +uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_and(p_data, 0); +} + +uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_and(p_data, 0); +} + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic.h new file mode 100644 index 0000000..6a11eee --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic.h @@ -0,0 +1,274 @@ +/** + * Copyright (c) 2016 - 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 + * + * @defgroup nrf_atomic Atomic operations API + * @ingroup app_common + * @{ + * + * @brief @tagAPI52 This module implements C11 stdatomic.h simplified API. + At this point only Cortex-M3/M4 cores are supported (LDREX/STREX instructions). + * Atomic types are limited to @ref nrf_atomic_u32_t and @ref nrf_atomic_flag_t. + */ + +#ifndef NRF_ATOMIC_H__ +#define NRF_ATOMIC_H__ + +#include "sdk_common.h" + +/** + * @brief Atomic 32 bit unsigned type + * */ +typedef volatile uint32_t nrf_atomic_u32_t; + +/** + * @brief Atomic 1 bit flag type (technically 32 bit) + * */ +typedef volatile uint32_t nrf_atomic_flag_t; + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief If value at pointer is equal to expected value, changes value at pointer to desired + * + * Atomically compares the value pointed to by p_data with the value pointed to by p_expected, + * and if those are equal, replaces the former with desired. Otherwise, loads the actual value + * pointed to by p_data into *p_expected. + * + * @param p_data Atomic memory pointer to test and modify. + * @param p_expected Pointer to test value. + * @param desired Value to be stored to atomic memory. + * + * @retval true *p_data was equal to *p_expected + * @retval false *p_data was not equal to *p_expected + */ +bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t desired); + +/** + * @brief Arithmetic SUB operation on an atomic object performed if object >= value. + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object performed if object >= value. + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); + +/**************************************************************************************************/ + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data); + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_H__ */ + +/** @} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic_internal.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic_internal.h new file mode 100644 index 0000000..534f1b7 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic_internal.h @@ -0,0 +1,343 @@ +/** + * Copyright (c) 2016 - 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_ATOMIC_INTERNAL_H__ +#define NRF_ATOMIC_INTERNAL_H__ + +#include "sdk_common.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @defgroup nrf_atomic_internal Atomic operations internals + * @ingroup nrf_atomic + * @{ + * + */ + +/* Only Cortex M cores > 3 support LDREX/STREX instructions*/ +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error "Unsupported core version" +#endif + +#if defined ( __CC_ARM ) +static __asm uint32_t nrf_atomic_internal_mov(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + /* The base standard provides for passing arguments in core registers (r0-r3) and on the stack. + * Registers r4 and r5 have to be saved on stack. Note that only even number of register push are + * allowed. This is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS]. + * */ + push {r4, r5} + mov r4, r0 + +loop_mov + ldrex r0, [r4] + mov r5, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_mov + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +static __asm uint32_t nrf_atomic_internal_orr(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_orr + ldrex r0, [r4] + orr r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_orr + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_and(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_and + ldrex r0, [r4] + and r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_and + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_eor(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_eor + ldrex r0, [r4] + eor r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_eor + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_add(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_add + ldrex r0, [r4] + add r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_add + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_sub(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub + ldrex r0, [r4] + sub r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t value) +{ +#define RET_REG r0 +#define P_EXPC r1 +#define VALUE r2 +#define STR_RES r3 +#define P_DATA r4 +#define EXPC_VAL r5 +#define ACT_VAL r6 + + push {r4-r6} + mov P_DATA, r0 + mov RET_REG, #0 + +loop_cmp_exch + ldrex ACT_VAL, [P_DATA] + ldr EXPC_VAL, [P_EXPC] + cmp ACT_VAL, EXPC_VAL + ittee eq + strexeq STR_RES, VALUE, [P_DATA] + moveq RET_REG, #1 + strexne STR_RES, ACT_VAL, [P_DATA] + strne ACT_VAL, [P_EXPC] + cmp STR_RES, #0 + itt ne + movne RET_REG, #0 + bne loop_cmp_exch + + pop {r4-r6} + bx lr + +#undef RET_REG +#undef P_EXPC +#undef VALUE +#undef STR_RES +#undef P_DATA +#undef EXPC_VAL +#undef ACT_VAL +} + +static __asm uint32_t nrf_atomic_internal_sub_hs(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub_ge + ldrex r0, [r4] + cmp r0, r1 + ite hs + subhs r5, r0, r1 + movlo r5, r0 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub_ge + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ + old_val = nrf_atomic_internal_##asm_op(ptr, value, &new_val) + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +/** + * @brief Atomic operation generic macro + * @param[in] asm_op operation: mov, orr, and, eor, add, sub + * @param[out] old_val atomic object output (uint32_t), value before operation + * @param[out] new_val atomic object output (uint32_t), value after operation + * @param[in] value atomic operation operand + * */ +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ +{ \ + uint32_t str_res; \ + __ASM volatile( \ + "1: ldrex %["#old_val"], [%["#ptr"]]\n" \ + NRF_ATOMIC_OP_##asm_op(new_val, old_val, value) \ + " strex %[str_res], %["#new_val"], [%["#ptr"]]\n" \ + " teq %[str_res], #0\n" \ + " bne.n 1b" \ + : \ + [old_val]"=&r" (old_val), \ + [new_val]"=&r" (new_val), \ + [str_res]"=&r" (str_res) \ + : \ + [ptr]"r" (ptr), \ + [value]"r" (value) \ + : "cc"); \ + UNUSED_PARAMETER(str_res); \ +} + +#define NRF_ATOMIC_OP_mov(new_val, old_val, value) "mov %["#new_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_orr(new_val, old_val, value) "orr %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_and(new_val, old_val, value) "and %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_eor(new_val, old_val, value) "eor %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_add(new_val, old_val, value) "add %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub(new_val, old_val, value) "sub %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub_hs(new_val, old_val, value) \ + "cmp %["#old_val"], %["#value"]\n " \ + "ite hs\n" \ + "subhs %["#new_val"], %["#old_val"], %["#value"]\n" \ + "movlo %["#new_val"], %["#old_val"]\n" + +static inline bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t value) +{ + bool res = false; + uint32_t str_res = 0; + uint32_t act_val = 0; + uint32_t exp_val = 0; + UNUSED_VARIABLE(str_res); + UNUSED_VARIABLE(act_val); + UNUSED_VARIABLE(exp_val); + __ASM volatile( + "1: ldrex %[act_val], [%[ptr]]\n" + " ldr %[exp_val], [%[expc]]\n" + " cmp %[act_val], %[exp_val]\n" + " ittee eq\n" + " strexeq %[str_res], %[value], [%[ptr]]\n" + " moveq %[res], #1\n" + " strexne %[str_res], %[act_val], [%[ptr]]\n" + " strne %[act_val], [%[expc]]\n" + " cmp %[str_res], #0\n" + " itt ne\n" + " movne %[res], #0\n" + " bne.n 1b" + : + [res] "=&r" (res), + [exp_val] "=&r" (exp_val), + [act_val] "=&r" (act_val), + [str_res] "=&r" (str_res) + : + "0" (res), + "1" (exp_val), + "2" (act_val), + [expc] "r" (p_expected), + [ptr] "r" (p_data), + [value] "r" (value) + : "cc"); + return res; +} + +#else +#error "Unsupported compiler" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_INTERNAL_H__ */ + +/** @} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic_sanity_check.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic_sanity_check.h new file mode 100644 index 0000000..bbc302c --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/atomic/nrf_atomic_sanity_check.h @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2016 - 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_ATOMIC_SANITY_CHECK_H__ +#define NRF_ATOMIC_SANITY_CHECK_H__ + +#include "nrf_atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Quick sanity check of nrf_atomic API + * */ +static inline void nrf_atomic_sanity_check(void) +{ +#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) + nrf_atomic_u32_t val; + nrf_atomic_u32_t flag; + + /*Fetch version tests*/ + val = 0; + ASSERT(nrf_atomic_u32_store_fetch(&val, 10) == 0); + ASSERT(nrf_atomic_u32_store_fetch(&val, 0) == 10); + + val = 0; + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 16) == 0); + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == (0xFFFFFFFF)); + + val = 0xFFFFFFFF; + ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 16)) == 0xFFFFFFFF); + ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 5)) == (0xFFFFFFFF & ~((1 << 16)))); + ASSERT(nrf_atomic_u32_and_fetch(&val, 0) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5))))); + ASSERT(nrf_atomic_u32_and_fetch(&val, 0xFFFFFFFF) == (0)); + + val = 0; + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16)) == 0); + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 5)) == ((1 << 16))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16) | (1 << 5)) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == (0)); + + val = 0; + ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 0); + ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 100); + ASSERT(nrf_atomic_u32_add_fetch(&val, 1 << 24) == 200); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0xFFFFFFFF) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 - 1 + (1 << 24))); + + val = 1000; + ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 1000); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 900); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 800); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0xFFFFFFFF) == 800); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 801); + + flag = 0; + ASSERT(nrf_atomic_flag_set_fetch(&flag) == 0); + ASSERT(nrf_atomic_flag_set_fetch(&flag) == 1); + ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 1); + ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 0); + + /*No fetch version tests*/ + val = 0; + ASSERT(nrf_atomic_u32_store(&val, 10) == 10); + ASSERT(nrf_atomic_u32_store(&val, 0) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_or(&val, 1 << 16) == 1 << 16); + ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 0xFFFFFFFF) == 0xFFFFFFFF); + + val = 0xFFFFFFFF; + ASSERT(nrf_atomic_u32_and(&val, ~(1 << 16)) == (0xFFFFFFFF & ~((1 << 16)))); + ASSERT(nrf_atomic_u32_and(&val, ~(1 << 5)) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5))))); + ASSERT(nrf_atomic_u32_and(&val, 0) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_xor(&val, (1 << 16)) == ((1 << 16))); + ASSERT(nrf_atomic_u32_xor(&val, (1 << 5)) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor(&val, (1 << 16) | (1 << 5)) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_add(&val, 100) == 100); + ASSERT(nrf_atomic_u32_add(&val, 100) == 200); + ASSERT(nrf_atomic_u32_add(&val, 1 << 24) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add(&val, 0) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add(&val, 0xFFFFFFFF) == (200 - 1 + (1 << 24))); + + val = 1000; + ASSERT(nrf_atomic_u32_sub(&val, 100) == 900); + ASSERT(nrf_atomic_u32_sub(&val, 100) == 800); + ASSERT(nrf_atomic_u32_sub(&val, 0) == 800); + ASSERT(nrf_atomic_u32_sub(&val, 0xFFFFFFFF) == 801); + + flag = 0; + ASSERT(nrf_atomic_flag_set(&flag) == 1); + ASSERT(nrf_atomic_flag_set(&flag) == 1); + ASSERT(nrf_atomic_flag_clear(&flag) == 0); + ASSERT(nrf_atomic_flag_clear(&flag) == 0); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_SANITY_CHECK_H__ */ -- cgit v1.2.3