Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
libatomic.c
Go to the documentation of this file.
1
36#include <stdint.h>
37
38#ifdef ESP_NONOS
39
40#ifndef __STRINGIFY
41#define __STRINGIFY(a) #a
42#endif
43
44// these low level routines provide a replacement for SREG interrupt save that AVR uses
45// but are esp8266 specific. A normal use pattern is like
46//
47//{
48// uint32_t savedPS = xt_rsil(1); // this routine will allow level 2 and above
49// // do work here
50// xt_wsr_ps(savedPS); // restore the state
51//}
52//
53// level (0-15), interrupts of the given level and above will be active
54// level 15 will disable ALL interrupts,
55// level 0 will enable ALL interrupts,
56//
57#define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)); state;}))
58#define xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
59
60
61#define ACQ_LOCK() \
62 uint32_t savedPS = xt_rsil(15);
63
64#define REL_LOCK() xt_wsr_ps(savedPS);
65
66#elif defined(STM32F0xx) || (!defined(ARDUINO) && !defined(ESP_PLATFORM))
67// On Cortex-M0 the only way to do atomic operation is to disable interrupts.
68
70#define ACQ_LOCK() \
71 int _pastlock; \
72 __asm volatile(" mrs %0, PRIMASK \n cpsid i\n" : "=r"(_pastlock));
73
75#define REL_LOCK() __asm volatile(" msr PRIMASK, %0\n " : : "r"(_pastlock));
76
77#endif
78
79
80
81
82#ifdef ACQ_LOCK
83
84
88uint8_t __atomic_fetch_add_1(uint8_t *ptr, uint8_t val, int memorder)
89{
90 ACQ_LOCK();
91 uint16_t ret = *ptr;
92 *ptr += val;
93 REL_LOCK();
94 return ret;
95}
96
100uint16_t __atomic_fetch_sub_2(uint16_t *ptr, uint16_t val, int memorder)
101{
102 ACQ_LOCK();
103 uint16_t ret = *ptr;
104 *ptr -= val;
105 REL_LOCK();
106 return ret;
107}
108
112uint8_t __atomic_fetch_or_1(uint8_t *ptr, uint8_t val, int memorder)
113{
114 ACQ_LOCK();
115 uint8_t ret = *ptr;
116 *ptr = ret | val;
117 REL_LOCK();
118 return ret;
119}
120
124uint32_t __atomic_fetch_or_4(uint32_t *ptr, uint32_t val, int memorder)
125{
126 ACQ_LOCK();
127 uint32_t ret = *ptr;
128 *ptr = ret | val;
129 REL_LOCK();
130 return ret;
131}
132
136uint8_t __atomic_fetch_and_1(uint8_t *ptr, uint8_t val, int memorder)
137{
138 ACQ_LOCK();
139 uint8_t ret = *ptr;
140 *ptr = ret & val;
141 REL_LOCK();
142 return ret;
143}
144
148uint32_t __atomic_fetch_and_4(uint32_t *ptr, uint32_t val, int memorder)
149{
150 ACQ_LOCK();
151 uint32_t ret = *ptr;
152 *ptr = ret & val;
153 REL_LOCK();
154 return ret;
155}
156
160uint8_t __atomic_exchange_1(uint8_t *ptr, uint8_t val, int memorder)
161{
162 ACQ_LOCK();
163 uint8_t ret = *ptr;
164 *ptr = val;
165 REL_LOCK();
166 return ret;
167}
168
180_Bool __atomic_compare_exchange_1(uint8_t *ptr, uint8_t *exp, uint8_t desired,
181 _Bool weak, int success_memorder, int failure_memorder)
182{
183 ACQ_LOCK();
184 uint8_t curr = *ptr;
185 if (curr == *exp)
186 {
187 *ptr = desired;
188 REL_LOCK();
189 return 1;
190 }
191 *exp = curr;
192 REL_LOCK();
193 return 0;
194}
195
199_Bool __atomic_compare_exchange_4(uint32_t *ptr, uint32_t *exp,
200 uint32_t desired, _Bool weak, int success_memorder, int failure_memorder)
201{
202 ACQ_LOCK();
203 uint32_t curr = *ptr;
204 if (curr == *exp)
205 {
206 *ptr = desired;
207 REL_LOCK();
208 return 1;
209 }
210 *exp = curr;
211 REL_LOCK();
212 return 0;
213}
214
215#endif // guard for arduino compilation
uint8_t __atomic_exchange_1(uint8_t *ptr, uint8_t val, int memorder)
__atomic_exchange_1
Definition libatomic.c:160
uint32_t __atomic_fetch_and_4(uint32_t *ptr, uint32_t val, int memorder)
__atomic_fetch_and_4
Definition libatomic.c:148
#define ACQ_LOCK()
Disables interrupts and saves the interrupt enable flag in a register.
Definition libatomic.c:70
uint8_t __atomic_fetch_or_1(uint8_t *ptr, uint8_t val, int memorder)
__atomic_fetch_or_1
Definition libatomic.c:112
uint8_t __atomic_fetch_add_1(uint8_t *ptr, uint8_t val, int memorder)
__atomic_fetch_add_1
Definition libatomic.c:88
uint32_t __atomic_fetch_or_4(uint32_t *ptr, uint32_t val, int memorder)
__atomic_fetch_or_4
Definition libatomic.c:124
#define REL_LOCK()
Restores the interrupte enable flag from a register.
Definition libatomic.c:75
uint8_t __atomic_fetch_and_1(uint8_t *ptr, uint8_t val, int memorder)
__atomic_fetch_and_1
Definition libatomic.c:136
uint16_t __atomic_fetch_sub_2(uint16_t *ptr, uint16_t val, int memorder)
__atomic_fetch_sub_2
Definition libatomic.c:100
_Bool __atomic_compare_exchange_4(uint32_t *ptr, uint32_t *exp, uint32_t desired, _Bool weak, int success_memorder, int failure_memorder)
__atomic_compare_exchange_4
Definition libatomic.c:199
_Bool __atomic_compare_exchange_1(uint8_t *ptr, uint8_t *exp, uint8_t desired, _Bool weak, int success_memorder, int failure_memorder)
__atomic_compare_exchange_1
Definition libatomic.c:180