@web-font-path: "roboto-debian.css";
v2.2.0 (RP2040)
Loading...
Searching...
No Matches
sync.h
Go to the documentation of this file.
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _HARDWARE_SYNC_H
#define _HARDWARE_SYNC_H
#include "pico.h"
#include "hardware/address_mapped.h"
#ifdef __riscv
#include "hardware/hazard3.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_SYNC, Enable/disable assertions in the hardware_sync module, type=bool, default=0, group=hardware_sync
#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_SYNC
#ifdef PARAM_ASSERTIONS_ENABLED_SYNC // backwards compatibility with SDK < 2.0.0
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_SYNC PARAM_ASSERTIONS_ENABLED_SYNC
#else
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_SYNC 0
#endif
#endif
__force_inline static void __nop(void) {
#if !__ARM_ARCH_6M__
#ifdef __riscv
__asm volatile ("nop");
#else
__asm volatile ("nop.w");
#endif
#else
__asm volatile ("nop");
#endif
}
#if !__has_builtin(__sev)
__force_inline static void __sev(void) {
#ifdef __riscv
__hazard3_unblock();
#else
pico_default_asm_volatile ("sev");
#endif
}
#endif
#if !__has_builtin(__wfe)
__force_inline static void __wfe(void) {
#ifdef __riscv
__hazard3_block();
#else
pico_default_asm_volatile ("wfe");
#endif
}
#endif
#if !__has_builtin(__wfi)
__force_inline static void __wfi(void) {
pico_default_asm_volatile("wfi");
}
#endif
__force_inline static void __dmb(void) {
#ifdef __riscv
__asm volatile ("fence rw, rw" : : : "memory");
#else
pico_default_asm_volatile ("dmb" : : : "memory");
#endif
}
__force_inline static void __dsb(void) {
#ifdef __riscv
__asm volatile ("fence rw, rw" : : : "memory");
#else
pico_default_asm_volatile ("dsb" : : : "memory");
#endif
}
__force_inline static void __isb(void) {
#ifdef __riscv
__asm volatile ("fence.i" : : : "memory");
#else
pico_default_asm_volatile("isb" ::: "memory");
#endif
}
__force_inline static void __mem_fence_acquire(void) {
// the original code below makes it hard for us to be included from C++ via a header
// which itself is in an extern "C", so just use __dmb instead, which is what
// is required on Cortex M0+
__dmb();
//#ifndef __cplusplus
// atomic_thread_fence(memory_order_acquire);
//#else
// std::atomic_thread_fence(std::memory_order_acquire);
//#endif
}
__force_inline static void __mem_fence_release(void) {
// the original code below makes it hard for us to be included from C++ via a header
// which itself is in an extern "C", so just use __dmb instead, which is what
// is required on Cortex M0+
__dmb();
//#ifndef __cplusplus
// atomic_thread_fence(memory_order_release);
//#else
// std::atomic_thread_fence(std::memory_order_release);
//#endif
}
__force_inline static void disable_interrupts(void) {
#ifdef __riscv
__compiler_memory_barrier();
riscv_clear_csr(mstatus, 8);
__compiler_memory_barrier();
#else
pico_default_asm_volatile ( "cpsid i" : : : "memory");
#endif
}
__force_inline static void enable_interrupts(void) {
#ifdef __riscv
__compiler_memory_barrier();
riscv_set_csr(mstatus, 8);
__compiler_memory_barrier();
#else
pico_default_asm_volatile ( "cpsie i" : : : "memory");
#endif
}
__force_inline static uint32_t save_and_disable_interrupts(void) {
uint32_t status;
#ifdef __riscv
pico_default_asm_volatile (
"csrrci %0, mstatus, 0x8\n"
: "=r" (status) :: "memory"
);
#else
pico_default_asm_volatile (
"mrs %0, PRIMASK\n"
"cpsid i"
: "=r" (status) :: "memory");
#endif
return status;
}
__force_inline static void restore_interrupts(uint32_t status) {
#ifdef __riscv
__compiler_memory_barrier();
if (status & 0x8) {
riscv_set_csr(mstatus, 8);
} else {
riscv_clear_csr(mstatus, 8);
}
__compiler_memory_barrier();
#else
pico_default_asm_volatile ("msr PRIMASK,%0"::"r" (status) : "memory" );
#endif
}
__force_inline static void restore_interrupts_from_disabled(uint32_t status) {
#ifdef __riscv
// on RISC-V this can enable interrupts, but not disable interrupts... which
// is the common case and doesn't require a branch
__compiler_memory_barrier();
riscv_set_csr(mstatus, status & 8);
__compiler_memory_barrier();
#else
// on ARM, this behaves the same as restore_interrupts()
pico_default_asm_volatile ("msr PRIMASK,%0"::"r" (status) : "memory" );
#endif
}
#include "hardware/sync/spin_lock.h"
uint next_striped_spin_lock_num(void);
void spin_lock_claim(uint lock_num);
void spin_lock_claim_mask(uint32_t lock_num_mask);
void spin_lock_unclaim(uint lock_num);
int spin_lock_claim_unused(bool required);
bool spin_lock_is_claimed(uint lock_num);
// no longer use __mem_fence_acquire here, as it is overkill on cortex M0+
#if PICO_C_COMPILER_IS_GNU
#define remove_volatile_cast(t, x) (t)(x)
#define remove_volatile_cast_no_barrier(t, x) (t)(x)
#else
#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"); })
#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"); })
#endif
#ifdef __cplusplus
}
#endif
#endif
address_mapped.h
disable_interrupts
static __force_inline void disable_interrupts(void)
Explicitly disable interrupts on the calling core.
Definition sync.h:204
spin_lock_claim_unused
int spin_lock_claim_unused(bool required)
Claim a free spin lock.
Definition sync.c:43
save_and_disable_interrupts
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
spin_lock_unclaim
void spin_lock_unclaim(uint lock_num)
Mark a spin lock as no longer used.
Definition sync.c:37
__mem_fence_release
static __force_inline void __mem_fence_release(void)
Release a memory fence.
Definition sync.h:189
spin_lock_claim_mask
void spin_lock_claim_mask(uint32_t lock_num_mask)
Mark multiple spin locks as used.
Definition sync.c:31
__sev
static __force_inline void __sev(void)
Insert a SEV instruction in to the code path.
Definition sync.h:90
restore_interrupts_from_disabled
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
spin_lock_claim
void spin_lock_claim(uint lock_num)
Mark a spin lock as used.
Definition sync.c:26
__dmb
static __force_inline void __dmb(void)
Insert a DMB instruction in to the code path.
Definition sync.h:132
enable_interrupts
static __force_inline void enable_interrupts(void)
Explicitly enable interrupts on the calling core.
Definition sync.h:217
__wfe
static __force_inline void __wfe(void)
Insert a WFE instruction in to the code path.
Definition sync.h:106
restore_interrupts
static __force_inline void restore_interrupts(uint32_t status)
Restore interrupts to a specified state on the calling core.
Definition sync.h:258
next_striped_spin_lock_num
uint next_striped_spin_lock_num(void)
Return a spin lock number from the striped range.
Definition sync.c:18
__nop
static __force_inline void __nop(void)
Insert a NOP instruction in to the code path.
Definition sync.h:71
spin_lock_is_claimed
bool spin_lock_is_claimed(uint lock_num)
Determine if a spin lock is claimed.
Definition sync.c:47
__mem_fence_acquire
static __force_inline void __mem_fence_acquire(void)
Acquire a memory fence.
Definition sync.h:173
__wfi
static __force_inline void __wfi(void)
Insert a WFI instruction in to the code path.
Definition sync.h:121
__isb
static __force_inline void __isb(void)
Insert a ISB instruction in to the code path.
Definition sync.h:162
__dsb
static __force_inline void __dsb(void)
Insert a DSB instruction in to the code path.
Definition sync.h:147
__force_inline
#define __force_inline
Attribute to force inlining of a function regardless of optimization level.
Definition compiler.h:128
__compiler_memory_barrier
static __always_inline void __compiler_memory_barrier(void)
Ensure that the compiler does not move memory access across this method call.
Definition compiler.h:176
pico.h