18
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
19
*/
20
20
21
- #include < hardware/pio.h>
22
21
#include < hardware/clocks.h>
22
+ #include < hardware/irq.h>
23
+ #include < hardware/pio.h>
24
+ #include < pico/multicore.h>
25
+ #include < pico/util/queue.h>
26
+
27
+ class _MFIFO {
28
+ public:
29
+ _MFIFO () { /* noop */ };
30
+ ~_MFIFO () { /* noop */ };
31
+
32
+ void begin (int cores) {
33
+ constexpr int FIFOCNT = 8 ;
34
+ if (cores == 1 ) {
35
+ _multicore = false ;
36
+ return ;
37
+ }
38
+ mutex_init (&_idleMutex);
39
+ queue_init (&_queue[0 ], sizeof (uint32_t ), FIFOCNT);
40
+ queue_init (&_queue[1 ], sizeof (uint32_t ), FIFOCNT);
41
+ _multicore = true ;
42
+ }
43
+
44
+ void registerCore () {
45
+ multicore_fifo_clear_irq ();
46
+ irq_set_exclusive_handler (SIO_IRQ_PROC0 + get_core_num (), _irq);
47
+ irq_set_enabled (SIO_IRQ_PROC0 + get_core_num (), true );
48
+ }
49
+
50
+ void push (uint32_t val) {
51
+ while (!push_nb (val)) { /* noop */ }
52
+ }
53
+
54
+ bool push_nb (uint32_t val) {
55
+ // Push to the other FIFO
56
+ return queue_try_add (&_queue[get_core_num ()^1 ], &val);
57
+ }
58
+
59
+ uint32_t pop () {
60
+ uint32_t ret;
61
+ while (!pop_nb (&ret)) { /* noop */ }
62
+ return ret;
63
+ }
64
+
65
+ bool pop_nb (uint32_t *val) {
66
+ // Pop from my own FIFO
67
+ return queue_try_remove (&_queue[get_core_num ()], val);
68
+ }
69
+
70
+ int available () {
71
+ return queue_get_level (&_queue[get_core_num ()]);
72
+ }
73
+
74
+ void idleOtherCore () {
75
+ if (!_multicore) return ;
76
+ mutex_enter_blocking (&_idleMutex);
77
+ _otherIdled = false ;
78
+ multicore_fifo_push_blocking (_GOTOSLEEP);
79
+ while (!_otherIdled) { /* noop */ }
80
+ }
81
+
82
+ void resumeOtherCore () {
83
+ if (!_multicore) return ;
84
+ mutex_exit (&_idleMutex);
85
+ _otherIdled = false ;
86
+ // Other core will exit busy-loop and return to operation
87
+ // once otherIdled == false.
88
+ }
89
+
90
+ private:
91
+ static void __no_inline_not_in_flash_func (_irq)() {
92
+ multicore_fifo_clear_irq ();
93
+ noInterrupts (); // We need total control, can't run anything
94
+ while (multicore_fifo_rvalid ()) {
95
+ if (_GOTOSLEEP == multicore_fifo_pop_blocking ()) {
96
+ _otherIdled = true ;
97
+ while (_otherIdled) { /* noop */ }
98
+ break ;
99
+ }
100
+ }
101
+ interrupts ();
102
+ }
103
+ bool _multicore = false ;
104
+
105
+ mutex_t _idleMutex;
106
+ static volatile bool _otherIdled;
107
+ queue_t _queue[2 ];
108
+
109
+ static constexpr int _GOTOSLEEP = 0x66666666 ;
110
+ };
23
111
24
112
class RP2040 {
25
113
public:
@@ -33,8 +121,16 @@ class RP2040 {
33
121
static int f_cpu () {
34
122
return clock_get_hz (clk_sys);
35
123
}
124
+
125
+ void idleOtherCore () { fifo.idleOtherCore (); }
126
+ void resumeOtherCore () { fifo.resumeOtherCore (); }
127
+
128
+ // Multicore comms FIFO
129
+ _MFIFO fifo;
36
130
};
37
131
132
+ extern RP2040 rp2040;
133
+
38
134
// Wrapper class for PIO programs, abstracting common operations out
39
135
// TODO - Make dualcore safe
40
136
// TODO - Add unload/destructor
0 commit comments