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"
11
12 #ifndef __cplusplus
13
14 #if (__STDC_VERSION__ >= 201112L)
15 #include <stdatomic.h>
16 #else
17 enum {
18 memory_order_acquire, memory_order_release
19 };
atomic_thread_fence(uint x)20 static inline void atomic_thread_fence(uint x) {}
21 #endif
22
23 #else
24
25 #include <atomic>
26
27 #endif
28
29 // PICO_CONFIG: PICO_SPINLOCK_ID_ATOMIC, Spinlock ID for atomics, min=0, max=31, default=8, group=hardware_sync
30 #ifndef PICO_SPINLOCK_ID_ATOMIC
31 #define PICO_SPINLOCK_ID_ATOMIC 8
32 #endif
33
34 // PICO_CONFIG: PICO_SPINLOCK_ID_IRQ, Spinlock ID for IRQ protection, min=0, max=31, default=9, group=hardware_sync
35 #ifndef PICO_SPINLOCK_ID_IRQ
36 #define PICO_SPINLOCK_ID_IRQ 9
37 #endif
38
39 // PICO_CONFIG: PICO_SPINLOCK_ID_TIMER, Spinlock ID for Timer protection, min=0, max=31, default=10, group=hardware_sync
40 #ifndef PICO_SPINLOCK_ID_TIMER
41 #define PICO_SPINLOCK_ID_TIMER 10
42 #endif
43
44 // PICO_CONFIG: PICO_SPINLOCK_ID_HARDWARE_CLAIM, Spinlock ID for Hardware claim protection, min=0, max=31, default=11, group=hardware_sync
45 #ifndef PICO_SPINLOCK_ID_HARDWARE_CLAIM
46 #define PICO_SPINLOCK_ID_HARDWARE_CLAIM 11
47 #endif
48
49 // PICO_CONFIG: PICO_SPINLOCK_ID_RAND, Spinlock ID for Random Number Generator, min=0, max=31, default=12, group=hardware_sync
50 #ifndef PICO_SPINLOCK_ID_RAND
51 #define PICO_SPINLOCK_ID_RAND 12
52 #endif
53
54 // PICO_CONFIG: PICO_SPINLOCK_ID_OS1, First Spinlock ID reserved for use by low level OS style software, min=0, max=31, default=14, group=hardware_sync
55 #ifndef PICO_SPINLOCK_ID_OS1
56 #define PICO_SPINLOCK_ID_OS1 14
57 #endif
58
59 // PICO_CONFIG: PICO_SPINLOCK_ID_OS2, Second Spinlock ID reserved for use by low level OS style software, min=0, max=31, default=15, group=hardware_sync
60 #ifndef PICO_SPINLOCK_ID_OS2
61 #define PICO_SPINLOCK_ID_OS2 15
62 #endif
63
64 // PICO_CONFIG: PICO_SPINLOCK_ID_STRIPED_FIRST, Lowest Spinlock ID in the 'striped' range, min=0, max=31, default=16, group=hardware_sync
65 #ifndef PICO_SPINLOCK_ID_STRIPED_FIRST
66 #define PICO_SPINLOCK_ID_STRIPED_FIRST 16
67 #endif
68
69 // PICO_CONFIG: PICO_SPINLOCK_ID_STRIPED_LAST, Highest Spinlock ID in the 'striped' range, min=0, max=31, default=23, group=hardware_sync
70 #ifndef PICO_SPINLOCK_ID_STRIPED_LAST
71 #define PICO_SPINLOCK_ID_STRIPED_LAST 23
72 #endif
73
74 // PICO_CONFIG: PICO_SPINLOCK_ID_CLAIM_FREE_FIRST, Lowest Spinlock ID in the 'claim free' range, min=0, max=31, default=24, group=hardware_sync
75 #ifndef PICO_SPINLOCK_ID_CLAIM_FREE_FIRST
76 #define PICO_SPINLOCK_ID_CLAIM_FREE_FIRST 24
77 #endif
78
79 #ifdef PICO_SPINLOCK_ID_CLAIM_FREE_END
80 #warning PICO_SPINLOCK_ID_CLAIM_FREE_END has been renamed to PICO_SPINLOCK_ID_CLAIM_FREE_LAST
81 #endif
82
83 // PICO_CONFIG: PICO_SPINLOCK_ID_CLAIM_FREE_LAST, Highest Spinlock ID in the 'claim free' range, min=0, max=31, default=31, group=hardware_sync
84 #ifndef PICO_SPINLOCK_ID_CLAIM_FREE_LAST
85 #define PICO_SPINLOCK_ID_CLAIM_FREE_LAST 31
86 #endif
87
88 typedef struct _spin_lock_t spin_lock_t;
89
__mem_fence_acquire()90 inline static void __mem_fence_acquire() {
91 #ifndef __cplusplus
92 atomic_thread_fence(memory_order_acquire);
93 #else
94 std::atomic_thread_fence(std::memory_order_acquire);
95 #endif
96 }
97
__mem_fence_release()98 inline static void __mem_fence_release() {
99 #ifndef __cplusplus
100 atomic_thread_fence(memory_order_release);
101 #else
102 std::atomic_thread_fence(std::memory_order_release);
103 #endif
104 }
105
106 #ifdef __cplusplus
107 extern "C" {
108 #endif
109
110 void __sev();
111
112 void __wev();
113
114 void __wfi();
115
116 void __wfe();
117
118 uint32_t save_and_disable_interrupts();
119
120 void restore_interrupts(uint32_t status);
121
122 void restore_interrupts_from_disabled(uint32_t status);
123
124 uint spin_lock_get_num(spin_lock_t *lock);
125
126 spin_lock_t *spin_lock_instance(uint lock_num);
127
128 void spin_lock_unsafe_blocking(spin_lock_t *lock);
129
130 void spin_unlock_unsafe(spin_lock_t *lock);
131
132 uint32_t spin_lock_blocking(spin_lock_t *lock);
133
134 bool is_spin_locked(const spin_lock_t *lock);
135
136 void spin_unlock(spin_lock_t *lock, uint32_t saved_irq);
137
138 spin_lock_t *spin_lock_init(uint lock_num);
139
140 void clear_spin_locks(void);
141 #define spin_locks_reset() clear_spin_locks()
142
143 uint next_striped_spin_lock_num();
144
145 void spin_lock_claim(uint lock_num);
146 void spin_lock_claim_mask(uint32_t lock_num_mask);
147 void spin_lock_unclaim(uint lock_num);
148 int spin_lock_claim_unused(bool required);
149 uint spin_lock_num(spin_lock_t *lock);
150
151 #ifdef __cplusplus
152 }
153 #endif
154 #endif
155