5#include <Settings/NamespaceSettings.hpp>
7#if defined(ARDUINO_ARCH_RP2040)
8#include <hardware/sync.h>
9#elif defined(ARDUINO_ARCH_MBED)
10#include <platform/mbed_critical.h>
17#define CS_USE_REAL_ATOMIC 1
19#elif defined(ARDUINO_ARCH_RP2040)
21class ScopedInterruptDisabler {
23 ScopedInterruptDisabler() :
state {save_and_disable_interrupts()} {}
24 ~ScopedInterruptDisabler() { restore_interrupts(state); }
25 ScopedInterruptDisabler(
const ScopedInterruptDisabler &) =
delete;
26 ScopedInterruptDisabler &
27 operator=(
const ScopedInterruptDisabler &) =
delete;
28 ScopedInterruptDisabler(ScopedInterruptDisabler &&) =
delete;
29 ScopedInterruptDisabler &operator=(ScopedInterruptDisabler &&) =
delete;
35#elif defined(ARDUINO_ARCH_MBED)
38class ScopedInterruptDisabler {
40 ScopedInterruptDisabler() { core_util_critical_section_enter(); }
41 ~ScopedInterruptDisabler() { core_util_critical_section_exit(); }
42 ScopedInterruptDisabler(
const ScopedInterruptDisabler &) =
delete;
43 ScopedInterruptDisabler &
44 operator=(
const ScopedInterruptDisabler &) =
delete;
45 ScopedInterruptDisabler(ScopedInterruptDisabler &&) =
delete;
46 ScopedInterruptDisabler &operator=(ScopedInterruptDisabler &&) =
delete;
49#elif defined(TEENSYDUINO)
54#error "Unknown platform, I don't know how to disable and restore interrupts"
61#if defined(DARDUINO_ARCH_NRF52840) || defined(DARDUINO_ARCH_MBED_GIGA) || \
63#define CS_USE_ATOMIC_RMW 1
65#define CS_USE_ATOMIC_RMW 0
69#ifdef CS_USE_REAL_ATOMIC
86 [[gnu::always_inline]]
static void
89 case std::memory_order_consume:
90 case std::memory_order_acq_rel:
91 case std::memory_order_acquire:
92 std::atomic_signal_fence(std::memory_order_acquire);
94 case std::memory_order_seq_cst:
95 std::atomic_signal_fence(std::memory_order_seq_cst);
97 case std::memory_order_relaxed:
98 case std::memory_order_release:
105 [[gnu::always_inline]]
static void
108 case std::memory_order_consume:
109 case std::memory_order_acq_rel:
110 case std::memory_order_acquire:
111 std::atomic_signal_fence(std::memory_order_acquire);
113 case std::memory_order_seq_cst:
114 std::atomic_signal_fence(std::memory_order_seq_cst);
116 case std::memory_order_relaxed:
117 case std::memory_order_release:
124 [[gnu::always_inline]] T
load(std::memory_order o)
const {
125 if (o == std::memory_order_seq_cst)
126 std::atomic_signal_fence(std::memory_order_seq_cst);
127 auto t =
value.load(std::memory_order_relaxed);
132 [[gnu::always_inline]]
void store(T t, std::memory_order o)
noexcept {
134 value.store(t, std::memory_order_relaxed);
135 if (o == std::memory_order_seq_cst)
136 std::atomic_signal_fence(std::memory_order_seq_cst);
140 [[gnu::always_inline]] T
exchange(T arg, std::memory_order o) {
142 auto t =
value.exchange(arg, std::memory_order_relaxed);
147 [[gnu::always_inline]]
bool
149 std::memory_order o)
noexcept {
151 bool success =
value.compare_exchange_strong(expected, desired,
152 std::memory_order_relaxed);
157 [[gnu::always_inline]]
bool
159 std::memory_order o)
noexcept {
161 bool success =
value.compare_exchange_weak(expected, desired,
162 std::memory_order_relaxed);
167 [[gnu::always_inline]] T
fetch_add(T arg, std::memory_order o) {
169 auto t =
value.fetch_add(arg, std::memory_order_relaxed);
174 [[gnu::always_inline]] T
fetch_sub(T arg, std::memory_order o) {
176 auto t =
value.fetch_sub(arg, std::memory_order_relaxed);
181 [[gnu::always_inline]] T
exchange(T arg, std::memory_order o) {
182 ScopedInterruptDisabler disable_interrupts;
184 auto t =
value.load(std::memory_order_relaxed);
185 value.store(arg, std::memory_order_relaxed);
190 [[gnu::always_inline]]
bool
192 std::memory_order o)
noexcept {
193 ScopedInterruptDisabler disable_interrupts;
194 if (o == std::memory_order_seq_cst)
195 std::atomic_signal_fence(std::memory_order_seq_cst);
196 auto t =
value.load(std::memory_order_relaxed);
197 bool success = t == expected;
200 value.store(desired, std::memory_order_relaxed);
208 [[gnu::always_inline]]
bool
210 std::memory_order o)
noexcept {
214 [[gnu::always_inline]] T
fetch_add(T arg, std::memory_order o) {
215 ScopedInterruptDisabler disable_interrupts;
221 [[gnu::always_inline]] T
fetch_sub(T arg, std::memory_order o) {
222 ScopedInterruptDisabler disable_interrupts;
#define BEGIN_CS_NAMESPACE
Wrapper that provides atomic access to variables shared between the main program and interrupt handle...
T load(std::memory_order o) const
T fetch_add(T arg, std::memory_order o)
T exchange(T arg, std::memory_order o)
interrupt_atomic() noexcept=default
T fetch_sub(T arg, std::memory_order o)
bool compare_exchange_weak(T &expected, T desired, std::memory_order o) noexcept
static void after_load_fence(std::memory_order o) noexcept
bool compare_exchange_strong(T &expected, T desired, std::memory_order o) noexcept
static void before_store_fence(std::memory_order o) noexcept
void store(T t, std::memory_order o) noexcept