From 299b3e9c4ec309f25937fc9d391b919c1cdd56b2 Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Mon, 9 Mar 2026 15:21:17 +0800 Subject: [PATCH] feat(core): Add 8-bit and 16-bit atomic operation support --- include/rtatomic.h | 141 +++++++++++++++++++++ include/rttypes.h | 8 ++ libcpu/Kconfig | 24 ++++ libcpu/arm/common/atomic_arm.c | 220 ++++++++++++++++++++++++++++++++- 4 files changed, 392 insertions(+), 1 deletion(-) diff --git a/include/rtatomic.h b/include/rtatomic.h index 4719339d262..6649c7e4c26 100644 --- a/include/rtatomic.h +++ b/include/rtatomic.h @@ -7,6 +7,7 @@ * Date Author Notes * 2023-03-14 WangShun first version * 2023-05-20 Bernard add stdc atomic detection. + * 2026-03-09 wdfk-prog add 8/16-bit atomic operations support */ #ifndef __RT_ATOMIC_H__ #define __RT_ATOMIC_H__ @@ -17,8 +18,16 @@ rt_atomic_t rt_hw_atomic_load(volatile rt_atomic_t *ptr); void rt_hw_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val); +rt_atomic8_t rt_hw_atomic_load8(volatile rt_atomic8_t *ptr); +void rt_hw_atomic_store8(volatile rt_atomic8_t *ptr, rt_atomic8_t val); +rt_atomic16_t rt_hw_atomic_load16(volatile rt_atomic16_t *ptr); +void rt_hw_atomic_store16(volatile rt_atomic16_t *ptr, rt_atomic16_t val); rt_atomic_t rt_hw_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val); rt_atomic_t rt_hw_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val); +rt_atomic8_t rt_hw_atomic_and8(volatile rt_atomic8_t *ptr, rt_atomic8_t val); +rt_atomic8_t rt_hw_atomic_or8(volatile rt_atomic8_t *ptr, rt_atomic8_t val); +rt_atomic16_t rt_hw_atomic_and16(volatile rt_atomic16_t *ptr, rt_atomic16_t val); +rt_atomic16_t rt_hw_atomic_or16(volatile rt_atomic16_t *ptr, rt_atomic16_t val); rt_atomic_t rt_hw_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val); rt_atomic_t rt_hw_atomic_or(volatile rt_atomic_t *ptr, rt_atomic_t val); rt_atomic_t rt_hw_atomic_xor(volatile rt_atomic_t *ptr, rt_atomic_t val); @@ -32,8 +41,16 @@ rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_a #ifndef __STDC_NO_ATOMICS__ #define rt_atomic_load(ptr) atomic_load(ptr) #define rt_atomic_store(ptr, v) atomic_store(ptr, v) +#define rt_atomic_load8(ptr) atomic_load(ptr) +#define rt_atomic_store8(ptr, v) atomic_store(ptr, v) +#define rt_atomic_load16(ptr) atomic_load(ptr) +#define rt_atomic_store16(ptr, v) atomic_store(ptr, v) #define rt_atomic_add(ptr, v) atomic_fetch_add(ptr, v) #define rt_atomic_sub(ptr, v) atomic_fetch_sub(ptr, v) +#define rt_atomic_and8(ptr, v) atomic_fetch_and(ptr, v) +#define rt_atomic_or8(ptr, v) atomic_fetch_or(ptr, v) +#define rt_atomic_and16(ptr, v) atomic_fetch_and(ptr, v) +#define rt_atomic_or16(ptr, v) atomic_fetch_or(ptr, v) #define rt_atomic_and(ptr, v) atomic_fetch_and(ptr, v) #define rt_atomic_or(ptr, v) atomic_fetch_or(ptr, v) #define rt_atomic_xor(ptr, v) atomic_fetch_xor(ptr, v) @@ -48,6 +65,28 @@ rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_a #elif defined(RT_USING_HW_ATOMIC) #define rt_atomic_load(ptr) rt_hw_atomic_load(ptr) #define rt_atomic_store(ptr, v) rt_hw_atomic_store(ptr, v) +#if defined(ARCH_USING_HW_ATOMIC_8) +#define rt_atomic_load8(ptr) rt_hw_atomic_load8(ptr) +#define rt_atomic_store8(ptr, v) rt_hw_atomic_store8(ptr, v) +#define rt_atomic_and8(ptr, v) rt_hw_atomic_and8(ptr, v) +#define rt_atomic_or8(ptr, v) rt_hw_atomic_or8(ptr, v) +#else +#define rt_atomic_load8(ptr) rt_soft_atomic_load8(ptr) +#define rt_atomic_store8(ptr, v) rt_soft_atomic_store8(ptr, v) +#define rt_atomic_and8(ptr, v) rt_soft_atomic_and8(ptr, v) +#define rt_atomic_or8(ptr, v) rt_soft_atomic_or8(ptr, v) +#endif +#if defined(ARCH_USING_HW_ATOMIC_16) +#define rt_atomic_load16(ptr) rt_hw_atomic_load16(ptr) +#define rt_atomic_store16(ptr, v) rt_hw_atomic_store16(ptr, v) +#define rt_atomic_and16(ptr, v) rt_hw_atomic_and16(ptr, v) +#define rt_atomic_or16(ptr, v) rt_hw_atomic_or16(ptr, v) +#else +#define rt_atomic_load16(ptr) rt_soft_atomic_load16(ptr) +#define rt_atomic_store16(ptr, v) rt_soft_atomic_store16(ptr, v) +#define rt_atomic_and16(ptr, v) rt_soft_atomic_and16(ptr, v) +#define rt_atomic_or16(ptr, v) rt_soft_atomic_or16(ptr, v) +#endif #define rt_atomic_add(ptr, v) rt_hw_atomic_add(ptr, v) #define rt_atomic_sub(ptr, v) rt_hw_atomic_sub(ptr, v) #define rt_atomic_and(ptr, v) rt_hw_atomic_and(ptr, v) @@ -62,8 +101,16 @@ rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_a #include #define rt_atomic_load(ptr) rt_soft_atomic_load(ptr) #define rt_atomic_store(ptr, v) rt_soft_atomic_store(ptr, v) +#define rt_atomic_load8(ptr) rt_soft_atomic_load8(ptr) +#define rt_atomic_store8(ptr, v) rt_soft_atomic_store8(ptr, v) +#define rt_atomic_load16(ptr) rt_soft_atomic_load16(ptr) +#define rt_atomic_store16(ptr, v) rt_soft_atomic_store16(ptr, v) #define rt_atomic_add(ptr, v) rt_soft_atomic_add(ptr, v) #define rt_atomic_sub(ptr, v) rt_soft_atomic_sub(ptr, v) +#define rt_atomic_and8(ptr, v) rt_soft_atomic_and8(ptr, v) +#define rt_atomic_or8(ptr, v) rt_soft_atomic_or8(ptr, v) +#define rt_atomic_and16(ptr, v) rt_soft_atomic_and16(ptr, v) +#define rt_atomic_or16(ptr, v) rt_soft_atomic_or16(ptr, v) #define rt_atomic_and(ptr, v) rt_soft_atomic_and(ptr, v) #define rt_atomic_or(ptr, v) rt_soft_atomic_or(ptr, v) #define rt_atomic_xor(ptr, v) rt_soft_atomic_xor(ptr, v) @@ -72,6 +119,100 @@ rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_a #define rt_atomic_flag_test_and_set(ptr) rt_soft_atomic_flag_test_and_set(ptr) #define rt_atomic_compare_exchange_strong(ptr, v,des) rt_soft_atomic_compare_exchange_strong(ptr, v ,des) +rt_inline rt_atomic8_t rt_soft_atomic_load8(volatile rt_atomic8_t *ptr) +{ + rt_base_t level; + rt_atomic8_t temp; + + level = rt_hw_interrupt_disable(); + temp = *ptr; + rt_hw_interrupt_enable(level); + + return temp; +} + +rt_inline void rt_soft_atomic_store8(volatile rt_atomic8_t *ptr, rt_atomic8_t val) +{ + rt_base_t level; + + level = rt_hw_interrupt_disable(); + *ptr = val; + rt_hw_interrupt_enable(level); +} + +rt_inline rt_atomic16_t rt_soft_atomic_load16(volatile rt_atomic16_t *ptr) +{ + rt_base_t level; + rt_atomic16_t temp; + + level = rt_hw_interrupt_disable(); + temp = *ptr; + rt_hw_interrupt_enable(level); + + return temp; +} + +rt_inline void rt_soft_atomic_store16(volatile rt_atomic16_t *ptr, rt_atomic16_t val) +{ + rt_base_t level; + + level = rt_hw_interrupt_disable(); + *ptr = val; + rt_hw_interrupt_enable(level); +} + +rt_inline rt_atomic8_t rt_soft_atomic_and8(volatile rt_atomic8_t *ptr, rt_atomic8_t val) +{ + rt_base_t level; + rt_atomic8_t temp; + + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr = (*ptr) & val; + rt_hw_interrupt_enable(level); + + return temp; +} + +rt_inline rt_atomic8_t rt_soft_atomic_or8(volatile rt_atomic8_t *ptr, rt_atomic8_t val) +{ + rt_base_t level; + rt_atomic8_t temp; + + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr = (*ptr) | val; + rt_hw_interrupt_enable(level); + + return temp; +} + +rt_inline rt_atomic16_t rt_soft_atomic_and16(volatile rt_atomic16_t *ptr, rt_atomic16_t val) +{ + rt_base_t level; + rt_atomic16_t temp; + + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr = (*ptr) & val; + rt_hw_interrupt_enable(level); + + return temp; +} + +rt_inline rt_atomic16_t rt_soft_atomic_or16(volatile rt_atomic16_t *ptr, rt_atomic16_t val) +{ + rt_base_t level; + rt_atomic16_t temp; + + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr = (*ptr) | val; + rt_hw_interrupt_enable(level); + + return temp; +} + rt_inline rt_atomic_t rt_soft_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_base_t level; diff --git a/include/rttypes.h b/include/rttypes.h index cfbaec8bdb8..110e39df0ef 100644 --- a/include/rttypes.h +++ b/include/rttypes.h @@ -99,14 +99,22 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #endif #ifdef __cplusplus + typedef rt_uint8_t rt_atomic8_t; + typedef rt_uint16_t rt_atomic16_t; typedef rt_base_t rt_atomic_t; #else #if defined(RT_USING_STDC_ATOMIC) #include + typedef _Atomic(rt_uint8_t) rt_atomic8_t; + typedef _Atomic(rt_uint16_t) rt_atomic16_t; typedef _Atomic(rt_base_t) rt_atomic_t; #elif defined(RT_USING_HW_ATOMIC) + typedef rt_uint8_t rt_atomic8_t; + typedef rt_uint16_t rt_atomic16_t; typedef rt_base_t rt_atomic_t; #else + typedef rt_uint8_t rt_atomic8_t; + typedef rt_uint16_t rt_atomic16_t; typedef rt_base_t rt_atomic_t; #endif /* RT_USING_STDC_ATOMIC */ #endif /* __cplusplus */ diff --git a/libcpu/Kconfig b/libcpu/Kconfig index 22381a42fe7..c7435fc097e 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -13,6 +13,14 @@ config RT_USING_HW_ATOMIC bool default n +config ARCH_USING_HW_ATOMIC_8 + bool + default n + +config ARCH_USING_HW_ATOMIC_16 + bool + default n + config ARCH_CPU_BIG_ENDIAN bool @@ -60,6 +68,8 @@ config ARCH_ARM_CORTEX_M3 select ARCH_ARM_CORTEX_M select RT_USING_CPU_FFS select RT_USING_HW_ATOMIC + select ARCH_USING_HW_ATOMIC_8 + select ARCH_USING_HW_ATOMIC_16 config ARCH_ARM_MPU bool @@ -71,6 +81,8 @@ config ARCH_ARM_CORTEX_M4 select ARCH_ARM_CORTEX_M select RT_USING_CPU_FFS select RT_USING_HW_ATOMIC + select ARCH_USING_HW_ATOMIC_8 + select ARCH_USING_HW_ATOMIC_16 config ARCH_ARM_CORTEX_M7 bool @@ -78,28 +90,38 @@ config ARCH_ARM_CORTEX_M7 select RT_USING_CPU_FFS select RT_USING_CACHE select RT_USING_HW_ATOMIC + select ARCH_USING_HW_ATOMIC_8 + select ARCH_USING_HW_ATOMIC_16 config ARCH_ARM_CORTEX_M85 bool select ARCH_ARM_CORTEX_M select RT_USING_CPU_FFS select RT_USING_HW_ATOMIC + select ARCH_USING_HW_ATOMIC_8 + select ARCH_USING_HW_ATOMIC_16 config ARCH_ARM_CORTEX_M23 bool select ARCH_ARM_CORTEX_M select RT_USING_HW_ATOMIC + select ARCH_USING_HW_ATOMIC_8 + select ARCH_USING_HW_ATOMIC_16 config ARCH_ARM_CORTEX_M33 bool select ARCH_ARM_CORTEX_M select RT_USING_CPU_FFS select RT_USING_HW_ATOMIC + select ARCH_USING_HW_ATOMIC_8 + select ARCH_USING_HW_ATOMIC_16 config ARCH_ARM_CORTEX_R bool select ARCH_ARM select RT_USING_HW_ATOMIC + select ARCH_USING_HW_ATOMIC_8 + select ARCH_USING_HW_ATOMIC_16 config ARCH_ARM_CORTEX_R52 bool @@ -141,6 +163,8 @@ config ARCH_ARM_CORTEX_A select ARCH_ARM_MMU select RT_USING_CPU_FFS select RT_USING_HW_ATOMIC + select ARCH_USING_HW_ATOMIC_8 + select ARCH_USING_HW_ATOMIC_16 if ARCH_ARM_CORTEX_A config RT_SMP_AUTO_BOOT diff --git a/libcpu/arm/common/atomic_arm.c b/libcpu/arm/common/atomic_arm.c index e9f1d4465b1..196f906aabc 100644 --- a/libcpu/arm/common/atomic_arm.c +++ b/libcpu/arm/common/atomic_arm.c @@ -5,7 +5,8 @@ * * Change Logs: * Date Author Notes - * 2022-07-27 flybreak the first version + * 2022-07-27 flybreak the first version + * 2026-03-09 wdfk-prog add 8/16-bit atomic operations support */ #include @@ -14,6 +15,147 @@ #include #include #endif + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit values. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */ +#ifndef __LDREXB +#define __LDREXB (uint8_t)__builtin_arm_ldrex +#endif +#define __LDREXB_PRIV(ptr) ((rt_atomic8_t)__LDREXB((volatile uint8_t *)(ptr))) +#elif defined(__ARMCC_VERSION) /* ARM Compiler V5 */ +#if __ARMCC_VERSION < 5060020 +#define __LDREXB_PRIV(ptr) ((rt_atomic8_t ) __ldrex(ptr)) +#else +#define __LDREXB_PRIV(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((rt_atomic8_t ) __ldrex(ptr)) _Pragma("pop") +#endif +#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ +_Pragma("inline=forced") __intrinsic rt_atomic8_t __LDREXB_PRIV(volatile rt_atomic8_t *ptr) +{ + return __iar_builtin_LDREXB((volatile unsigned char *)ptr); +} +#elif defined (__GNUC__) /* GNU GCC Compiler */ +__attribute__((always_inline)) static inline rt_atomic8_t __LDREXB_PRIV(volatile rt_atomic8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __asm volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + __asm volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return (rt_atomic8_t)result; +} +#endif + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */ +#ifndef __STREXB +#define __STREXB (uint32_t)__builtin_arm_strex +#endif +#define __STREXB_PRIV(value, ptr) ((rt_atomic_t)__STREXB((uint8_t)(value), (volatile uint8_t *)(ptr))) +#elif defined(__ARMCC_VERSION) /* ARM Compiler V5 */ +#if __ARMCC_VERSION < 5060020 +#define __STREXB_PRIV(value, ptr) __strex(value, ptr) +#else +#define __STREXB_PRIV(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif +#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ +_Pragma("inline=forced") __intrinsic rt_atomic_t __STREXB_PRIV(rt_atomic8_t value, volatile rt_atomic8_t *ptr) +{ + return __iar_builtin_STREXB(value, (volatile unsigned char *)ptr); +} +#elif defined (__GNUC__) /* GNU GCC Compiler */ +__attribute__((always_inline)) static inline rt_atomic_t __STREXB_PRIV(rt_atomic8_t value, volatile rt_atomic8_t *addr) +{ + rt_atomic_t result; + + __asm volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return result; +} +#endif + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */ +#ifndef __LDREXH +#define __LDREXH (uint16_t)__builtin_arm_ldrex +#endif +#define __LDREXH_PRIV(ptr) ((rt_atomic16_t)__LDREXH((volatile uint16_t *)(ptr))) +#elif defined(__ARMCC_VERSION) /* ARM Compiler V5 */ +#if __ARMCC_VERSION < 5060020 +#define __LDREXH_PRIV(ptr) ((rt_atomic16_t ) __ldrex(ptr)) +#else +#define __LDREXH_PRIV(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((rt_atomic16_t ) __ldrex(ptr)) _Pragma("pop") +#endif +#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ +_Pragma("inline=forced") __intrinsic rt_atomic16_t __LDREXH_PRIV(volatile rt_atomic16_t *ptr) +{ + return __iar_builtin_LDREXH((volatile unsigned short *)ptr); +} +#elif defined (__GNUC__) /* GNU GCC Compiler */ +__attribute__((always_inline)) static inline rt_atomic16_t __LDREXH_PRIV(volatile rt_atomic16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __asm volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + __asm volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return (rt_atomic16_t)result; +} +#endif + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */ +#ifndef __STREXH +#define __STREXH (uint32_t)__builtin_arm_strex +#endif +#define __STREXH_PRIV(value, ptr) ((rt_atomic_t)__STREXH((uint16_t)(value), (volatile uint16_t *)(ptr))) +#elif defined(__ARMCC_VERSION) /* ARM Compiler V5 */ +#if __ARMCC_VERSION < 5060020 +#define __STREXH_PRIV(value, ptr) __strex(value, ptr) +#else +#define __STREXH_PRIV(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif +#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ +_Pragma("inline=forced") __intrinsic rt_atomic_t __STREXH_PRIV(rt_atomic16_t value, volatile rt_atomic16_t *ptr) +{ + return __iar_builtin_STREXH(value, (volatile unsigned short *)ptr); +} +#elif defined (__GNUC__) /* GNU GCC Compiler */ +__attribute__((always_inline)) static inline rt_atomic_t __STREXH_PRIV(rt_atomic16_t value, volatile rt_atomic16_t *addr) +{ + rt_atomic_t result; + + __asm volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return result; +} +#endif + /** \brief LDR Exclusive (32 bit) \details Executes a exclusive LDR instruction for 32 bit values. @@ -92,6 +234,42 @@ void rt_hw_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val) } while ((__STREXW(val, ptr)) != 0U); } +rt_atomic8_t rt_hw_atomic_load8(volatile rt_atomic8_t *ptr) +{ + rt_atomic8_t oldval; + do + { + oldval = __LDREXB_PRIV(ptr); + } while ((__STREXB_PRIV(oldval, ptr)) != 0U); + return oldval; +} + +void rt_hw_atomic_store8(volatile rt_atomic8_t *ptr, rt_atomic8_t val) +{ + do + { + __LDREXB_PRIV(ptr); + } while ((__STREXB_PRIV(val, ptr)) != 0U); +} + +rt_atomic16_t rt_hw_atomic_load16(volatile rt_atomic16_t *ptr) +{ + rt_atomic16_t oldval; + do + { + oldval = __LDREXH_PRIV(ptr); + } while ((__STREXH_PRIV(oldval, ptr)) != 0U); + return oldval; +} + +void rt_hw_atomic_store16(volatile rt_atomic16_t *ptr, rt_atomic16_t val) +{ + do + { + __LDREXH_PRIV(ptr); + } while ((__STREXH_PRIV(val, ptr)) != 0U); +} + rt_atomic_t rt_hw_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t oldval; @@ -112,6 +290,46 @@ rt_atomic_t rt_hw_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val) return oldval; } +rt_atomic8_t rt_hw_atomic_and8(volatile rt_atomic8_t *ptr, rt_atomic8_t val) +{ + rt_atomic8_t oldval; + do + { + oldval = __LDREXB_PRIV(ptr); + } while ((__STREXB_PRIV((rt_atomic8_t)(oldval & val), ptr)) != 0U); + return oldval; +} + +rt_atomic8_t rt_hw_atomic_or8(volatile rt_atomic8_t *ptr, rt_atomic8_t val) +{ + rt_atomic8_t oldval; + do + { + oldval = __LDREXB_PRIV(ptr); + } while ((__STREXB_PRIV((rt_atomic8_t)(oldval | val), ptr)) != 0U); + return oldval; +} + +rt_atomic16_t rt_hw_atomic_and16(volatile rt_atomic16_t *ptr, rt_atomic16_t val) +{ + rt_atomic16_t oldval; + do + { + oldval = __LDREXH_PRIV(ptr); + } while ((__STREXH_PRIV((rt_atomic16_t)(oldval & val), ptr)) != 0U); + return oldval; +} + +rt_atomic16_t rt_hw_atomic_or16(volatile rt_atomic16_t *ptr, rt_atomic16_t val) +{ + rt_atomic16_t oldval; + do + { + oldval = __LDREXH_PRIV(ptr); + } while ((__STREXH_PRIV((rt_atomic16_t)(oldval | val), ptr)) != 0U); + return oldval; +} + rt_atomic_t rt_hw_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t oldval;