1 /*
2  * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *    list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  *    contributors may be used to endorse or promote products derived from this
17  *    software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef NRFX_ATOMIC_H__
33 #define NRFX_ATOMIC_H__
34 
35 #include <nrfx.h>
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 /**
42  * @defgroup nrfx_atomic Atomic operations API
43  * @ingroup nrfx
44  * @{
45  *
46  * @brief This module implements C11 stdatomic.h simplified API.
47  *
48  * At this point, only Cortex-M3 and M4 cores are supported (LDREX/STREX instructions).
49  * Atomic types are limited to @ref nrfx_atomic_u32_t and @ref nrfx_atomic_flag_t.
50  */
51 
52 
53 /** @brief Atomic 32-bit unsigned type. */
54 typedef volatile uint32_t nrfx_atomic_u32_t;
55 
56 /** @brief Atomic 1-bit flag type (technically 32-bit). */
57 typedef volatile uint32_t nrfx_atomic_flag_t;
58 
59 /**
60  * @brief Function for storing a value to an atomic object and returning its previous value.
61  *
62  * @param[in] p_data Atomic memory pointer.
63  * @param[in] value  Value to store.
64  *
65  * @return Previous value stored in the atomic object.
66  */
67 uint32_t nrfx_atomic_u32_fetch_store(nrfx_atomic_u32_t * p_data, uint32_t value);
68 
69 /**
70  * @brief Function for storing a value to an atomic object and returning its new value.
71  *
72  * @param[in] p_data Atomic memory pointer.
73  * @param[in] value  Value to store.
74  *
75  * @return New value stored in the atomic object.
76  */
77 uint32_t nrfx_atomic_u32_store(nrfx_atomic_u32_t * p_data, uint32_t value);
78 
79 /**
80  * @brief Function for running a logical OR operation on an atomic object
81  *        and returning its previous value.
82  *
83  * @param[in] p_data Atomic memory pointer.
84  * @param[in] value  Value of the second operand in the OR operation.
85  *
86  * @return Previous value stored in the atomic object.
87  */
88 uint32_t nrfx_atomic_u32_fetch_or(nrfx_atomic_u32_t * p_data, uint32_t value);
89 
90 /**
91  * @brief Function for running a logical OR operation on an atomic object
92  *        and returning its new value.
93  *
94  * @param[in] p_data Atomic memory pointer.
95  * @param[in] value  Value of the second operand in the OR operation.
96  *
97  * @return New value stored in the atomic object.
98  */
99 uint32_t nrfx_atomic_u32_or(nrfx_atomic_u32_t * p_data, uint32_t value);
100 
101 /**
102  * @brief Function for running a logical AND operation on an atomic object
103  *        and returning its previous value.
104  *
105  * @param[in] p_data Atomic memory pointer.
106  * @param[in] value  Value of the second operand in the AND operation.
107  *
108  * @return Previous value stored in the atomic object.
109  */
110 uint32_t nrfx_atomic_u32_fetch_and(nrfx_atomic_u32_t * p_data, uint32_t value);
111 
112 /**
113  * @brief Function for running a logical AND operation on an atomic object
114  *        and returning its new value.
115  *
116  * @param[in] p_data Atomic memory pointer.
117  * @param[in] value  Value of the second operand in the AND operation.
118  *
119  * @return New value stored in the atomic object.
120  */
121 uint32_t nrfx_atomic_u32_and(nrfx_atomic_u32_t * p_data, uint32_t value);
122 
123 /**
124  * @brief Function for running a logical XOR operation on an atomic object
125  *        and returning its previous value.
126  *
127  * @param[in] p_data Atomic memory pointer.
128  * @param[in] value  Value of the second operand in the XOR operation.
129  *
130  * @return Previous value stored in the atomic object.
131  */
132 uint32_t nrfx_atomic_u32_fetch_xor(nrfx_atomic_u32_t * p_data, uint32_t value);
133 
134 /**
135  * @brief Function for running a logical XOR operation on an atomic object
136  *        and returning its new value.
137  *
138  * @param[in] p_data Atomic memory pointer.
139  * @param[in] value  Value of the second operand in the XOR operation.
140  *
141  * @return New value stored in the atomic object.
142  */
143 uint32_t nrfx_atomic_u32_xor(nrfx_atomic_u32_t * p_data, uint32_t value);
144 
145 /**
146  * @brief Function for running an arithmetic ADD operation on an atomic object
147  *        and returning its previous value.
148  *
149  * @param[in] p_data Atomic memory pointer.
150  * @param[in] value  Value of the second operand in the ADD operation.
151  *
152  * @return Previous value stored in the atomic object.
153  */
154 uint32_t nrfx_atomic_u32_fetch_add(nrfx_atomic_u32_t * p_data, uint32_t value);
155 
156 /**
157  * @brief Function for running an arithmetic ADD operation on an atomic object
158  *        and returning its new value.
159  *
160  * @param[in] p_data Atomic memory pointer.
161  * @param[in] value  Value of the second operand in the ADD operation.
162  *
163  * @return New value stored in the atomic object.
164  */
165 uint32_t nrfx_atomic_u32_add(nrfx_atomic_u32_t * p_data, uint32_t value);
166 
167 /**
168  * @brief Function for running an arithmetic SUB operation on an atomic object
169  *        and returning its previous value.
170  *
171  * @param[in] p_data Atomic memory pointer.
172  * @param[in] value  Value of the second operand in the SUB operation.
173  *
174  * @return Old value stored in the atomic object.
175  */
176 uint32_t nrfx_atomic_u32_fetch_sub(nrfx_atomic_u32_t * p_data, uint32_t value);
177 
178 /**
179  * @brief Function for running an arithmetic SUB operation on an atomic object
180  *        and returning its new value.
181  *
182  * @param[in] p_data Atomic memory pointer.
183  * @param[in] value  Value of the second operand in the SUB operation.
184  *
185  * @return New value stored in the atomic object.
186  */
187 uint32_t nrfx_atomic_u32_sub(nrfx_atomic_u32_t * p_data, uint32_t value);
188 
189 /**
190  * @brief Function for atomic conditional value replacement.
191  *
192  * Atomically compares the value pointed to by @p p_data with the value pointed to by @p p_expected.
193  * If those are equal, replaces the former with desired. Otherwise, loads the actual value
194  * pointed to by @p p_data into @p *p_expected.
195  *
196  * @param p_data     Atomic memory pointer to test and modify.
197  * @param p_expected Pointer to the test value.
198  * @param desired    Value to be stored to atomic memory.
199  *
200  * @retval true  @p *p_data was equal to @p *p_expected.
201  * @retval false @p *p_data was not equal to @p *p_expected.
202  */
203 bool nrfx_atomic_u32_cmp_exch(nrfx_atomic_u32_t * p_data,
204                               uint32_t *         p_expected,
205                               uint32_t           desired);
206 
207 /**
208  * @brief Function for running an arithmetic SUB operation on an atomic object
209  *        if object >= value, and returning its previous value.
210  *
211  * @param[in] p_data Atomic memory pointer.
212  * @param[in] value  Value of the second operand in the SUB operation.
213  *
214  * @return Previous value stored in the atomic object.
215  */
216 uint32_t nrfx_atomic_u32_fetch_sub_hs(nrfx_atomic_u32_t * p_data, uint32_t value);
217 
218 /**
219  * @brief Function for running an arithmetic SUB operation on an atomic object
220  *        if object >= value, and returning its new value.
221  *
222  * @param[in] p_data Atomic memory pointer.
223  * @param[in] value  Value of the second operand in the SUB operation.
224  *
225  * @return New value stored in the atomic object.
226  */
227 uint32_t nrfx_atomic_u32_sub_hs(nrfx_atomic_u32_t * p_data, uint32_t value);
228 
229 /**
230  * @brief Function for running a logical one bit flag set operation
231  *        on an atomic object and returning its previous value.
232  *
233  * @param[in] p_data Atomic flag memory pointer.
234  *
235  * @return Previous flag value.
236  */
237 uint32_t nrfx_atomic_flag_set_fetch(nrfx_atomic_flag_t * p_data);
238 
239 /**
240  * @brief Function for running a logical one bit flag set operation
241  *        on an atomic object and returning its new value.
242  *
243  * @param[in] p_data Atomic flag memory pointer.
244  *
245  * @return New flag value.
246  */
247 uint32_t nrfx_atomic_flag_set(nrfx_atomic_flag_t * p_data);
248 
249 /**
250  * @brief Function for running a logical one bit flag clear operation
251  *        on an atomic object and returning its previous value.
252  *
253  * @param[in] p_data Atomic flag memory pointer.
254  *
255  * @return Previous flag value.
256  */
257 uint32_t nrfx_atomic_flag_clear_fetch(nrfx_atomic_flag_t * p_data);
258 
259 /**
260  * @brief Function for running a logical one bit flag clear operation
261  *        on an atomic object and returning its new value.
262  *
263  * @param[in] p_data Atomic flag memory pointer.
264  *
265  * @return New flag value.
266  */
267 uint32_t nrfx_atomic_flag_clear(nrfx_atomic_flag_t * p_data);
268 
269 /** @} */
270 
271 #ifdef __cplusplus
272 }
273 #endif
274 
275 #endif // NRFX_ATOMIC_H__
276