@web-font-path: "roboto-debian.css";
Loading...
Searching...
No Matches
sync.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _HARDWARE_SYNC_H
8#define _HARDWARE_SYNC_H
9
10#include "pico.h"
12
13#ifdef __riscv
14#include "hardware/hazard3.h"
15#endif
16
17#ifdef __cplusplus
18extern "C" {
19#endif
20
56// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_SYNC, Enable/disable assertions in the hardware_sync module, type=bool, default=0, group=hardware_sync
57#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_SYNC
58#ifdef PARAM_ASSERTIONS_ENABLED_SYNC // backwards compatibility with SDK < 2.0.0
59#define PARAM_ASSERTIONS_ENABLED_HARDWARE_SYNC PARAM_ASSERTIONS_ENABLED_SYNC
60#else
61#define PARAM_ASSERTIONS_ENABLED_HARDWARE_SYNC 0
62#endif
63#endif
64
71__force_inline static void __nop(void) {
72#if !__ARM_ARCH_6M__
73#ifdef __riscv
74 __asm volatile ("nop");
75#else
76 __asm volatile ("nop.w");
77#endif
78#else
79 __asm volatile ("nop");
80#endif
81}
82
83
89#if !__has_builtin(__sev)
90__force_inline static void __sev(void) {
91#ifdef __riscv
92 __hazard3_unblock();
93#else
94 pico_default_asm_volatile ("sev");
95#endif
96}
97#endif
98
105#if !__has_builtin(__wfe)
106__force_inline static void __wfe(void) {
107#ifdef __riscv
108 __hazard3_block();
109#else
110 pico_default_asm_volatile ("wfe");
111#endif
112}
113#endif
114
120#if !__has_builtin(__wfi)
121__force_inline static void __wfi(void) {
122 pico_default_asm_volatile("wfi");
123}
124#endif
125
132__force_inline static void __dmb(void) {
133#ifdef __riscv
134 __asm volatile ("fence rw, rw" : : : "memory");
135#else
136 pico_default_asm_volatile ("dmb" : : : "memory");
137#endif
138}
139
147__force_inline static void __dsb(void) {
148#ifdef __riscv
149 __asm volatile ("fence rw, rw" : : : "memory");
150#else
151 pico_default_asm_volatile ("dsb" : : : "memory");
152#endif
153}
154
162__force_inline static void __isb(void) {
163#ifdef __riscv
164 __asm volatile ("fence.i" : : : "memory");
165#else
166 pico_default_asm_volatile("isb" ::: "memory");
167#endif
168}
169
174 // the original code below makes it hard for us to be included from C++ via a header
175 // which itself is in an extern "C", so just use __dmb instead, which is what
176 // is required on Cortex M0+
177 __dmb();
178//#ifndef __cplusplus
179// atomic_thread_fence(memory_order_acquire);
180//#else
181// std::atomic_thread_fence(std::memory_order_acquire);
182//#endif
183}
184
190 // the original code below makes it hard for us to be included from C++ via a header
191 // which itself is in an extern "C", so just use __dmb instead, which is what
192 // is required on Cortex M0+
193 __dmb();
194//#ifndef __cplusplus
195// atomic_thread_fence(memory_order_release);
196//#else
197// std::atomic_thread_fence(std::memory_order_release);
198//#endif
199}
200
204__force_inline static uint32_t disable_interrupts(void) {
205#ifdef __riscv
207 riscv_clear_csr(mstatus, 8);
209#else
210 pico_default_asm_volatile ( "cpsid i" : : : "memory");
211#endif
212}
213
217__force_inline static uint32_t enable_interrupts(void) {
218#ifdef __riscv
220 riscv_set_csr(mstatus, 8);
222#else
223 pico_default_asm_volatile ( "cpsie i" : : : "memory");
224#endif
225}
226
238 uint32_t status;
239#ifdef __riscv
240 pico_default_asm_volatile (
241 "csrrci %0, mstatus, 0x8\n"
242 : "=r" (status) :: "memory"
243 );
244#else
245 pico_default_asm_volatile (
246 "mrs %0, PRIMASK\n"
247 "cpsid i"
248 : "=r" (status) :: "memory");
249#endif
250 return status;
251}
252
258__force_inline static void restore_interrupts(uint32_t status) {
259#ifdef __riscv
261 if (status & 0x8) {
262 riscv_set_csr(mstatus, 8);
263 } else {
264 riscv_clear_csr(mstatus, 8);
265 }
267#else
268 pico_default_asm_volatile ("msr PRIMASK,%0"::"r" (status) : "memory" );
269#endif
270}
271
281#ifdef __riscv
282 // on RISC-V this can enable interrupts, but not disable interrupts... which
283 // is the common case and doesn't require a branch
285 riscv_set_csr(mstatus, status & 8);
287#else
288 // on ARM, this behaves the same as restore_interrupts()
289 pico_default_asm_volatile ("msr PRIMASK,%0"::"r" (status) : "memory" );
290#endif
291}
292
293#include "hardware/sync/spin_lock.h"
294
311
321void spin_lock_claim(uint lock_num);
322
332void spin_lock_claim_mask(uint32_t lock_num_mask);
333
341void spin_lock_unclaim(uint lock_num);
342
349int spin_lock_claim_unused(bool required);
350
359bool spin_lock_is_claimed(uint lock_num);
360
361// no longer use __mem_fence_acquire here, as it is overkill on cortex M0+
362#if PICO_C_COMPILER_IS_GNU
363#define remove_volatile_cast(t, x) (t)(x)
364#define remove_volatile_cast_no_barrier(t, x) (t)(x)
365#else
366#define remove_volatile_cast(t, x) ({__compiler_memory_barrier(); Clang_Pragma("clang diagnostic push"); Clang_Pragma("clang diagnostic ignored \"-Wcast-qual\""); (t)(x); Clang_Pragma("clang diagnostic pop"); })
367#define remove_volatile_cast_no_barrier(t, x) ({ Clang_Pragma("clang diagnostic push"); Clang_Pragma("clang diagnostic ignored \"-Wcast-qual\""); (t)(x); Clang_Pragma("clang diagnostic pop"); })
368#endif
369
370#ifdef __cplusplus
371}
372#endif
373
374#endif
int spin_lock_claim_unused(bool required)
Claim a free spin lock.
Definition sync.c:43
static __force_inline uint32_t save_and_disable_interrupts(void)
Disable interrupts on the calling core, returning the previous interrupt state.
Definition sync.h:237
void spin_lock_unclaim(uint lock_num)
Mark a spin lock as no longer used.
Definition sync.c:37
static __force_inline void __mem_fence_release(void)
Release a memory fence.
Definition sync.h:189
void spin_lock_claim_mask(uint32_t lock_num_mask)
Mark multiple spin locks as used.
Definition sync.c:31
static __force_inline void __sev(void)
Insert a SEV instruction in to the code path.
Definition sync.h:90
static __force_inline void restore_interrupts_from_disabled(uint32_t status)
Restore interrupts to a specified state on the calling core with restricted transitions.
Definition sync.h:280
static __force_inline uint32_t enable_interrupts(void)
Explicitly enable interrupts on the calling core.
Definition sync.h:217
void spin_lock_claim(uint lock_num)
Mark a spin lock as used.
Definition sync.c:26
static __force_inline uint32_t disable_interrupts(void)
Explicitly disable interrupts on the calling core.
Definition sync.h:204
static __force_inline void __dmb(void)
Insert a DMB instruction in to the code path.
Definition sync.h:132
static __force_inline void __wfe(void)
Insert a WFE instruction in to the code path.
Definition sync.h:106
static __force_inline void restore_interrupts(uint32_t status)
Restore interrupts to a specified state on the calling core.
Definition sync.h:258
uint next_striped_spin_lock_num(void)
Return a spin lock number from the striped range.
Definition sync.c:18
static __force_inline void __nop(void)
Insert a NOP instruction in to the code path.
Definition sync.h:71
bool spin_lock_is_claimed(uint lock_num)
Determine if a spin lock is claimed.
Definition sync.c:47
static __force_inline void __mem_fence_acquire(void)
Acquire a memory fence.
Definition sync.h:173
static __force_inline void __wfi(void)
Insert a WFI instruction in to the code path.
Definition sync.h:121
static __force_inline void __isb(void)
Insert a ISB instruction in to the code path.
Definition sync.h:162
static __force_inline void __dsb(void)
Insert a DSB instruction in to the code path.
Definition sync.h:147
#define __force_inline
Attribute to force inlining of a function regardless of optimization level.
Definition compiler.h:125
static __always_inline void __compiler_memory_barrier(void)
Ensure that the compiler does not move memory access across this method call.
Definition compiler.h:173