1 // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #pragma once
16
17 #include <stdint.h>
18 #include <stdbool.h>
19 #include "soc/cpu.h"
20 #include "soc/soc_memory_layout.h"
21
22 #if __XTENSA__
23 #include "xtensa/xtruntime.h"
24 #endif
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
compare_and_set_native(volatile uint32_t * addr,uint32_t compare,uint32_t * set)30 static inline void __attribute__((always_inline)) compare_and_set_native(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
31 {
32 #if (XCHAL_HAVE_S32C1I > 0)
33 __asm__ __volatile__ (
34 "WSR %2,SCOMPARE1 \n"
35 "S32C1I %0, %1, 0 \n"
36 :"=r"(*set)
37 :"r"(addr), "r"(compare), "0"(*set)
38 );
39 #else
40 uint32_t old_value;
41
42 #ifdef __XTENSA__
43 // No S32C1I, so do this by disabling and re-enabling interrupts (slower)
44 uint32_t intlevel;
45 __asm__ __volatile__ ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) "\n"
46 : "=r"(intlevel));
47 #else
48 unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
49 #endif
50
51 old_value = *addr;
52 if (old_value == compare) {
53 *addr = *set;
54 }
55
56 #ifdef __XTENSA__
57 __asm__ __volatile__ ("memw \n"
58 "wsr %0, ps\n"
59 :: "r"(intlevel));
60
61 #else
62 RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
63 #endif
64
65 *set = old_value;
66 #endif
67 }
68
69
70 void compare_and_set_extram(volatile uint32_t *addr, uint32_t compare, uint32_t *set);
71
72 #ifdef __cplusplus
73 }
74 #endif
75