1818 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1919 */
2020
21- #include < hardware/pio.h>
2221#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+ };
23111
24112class RP2040 {
25113public:
@@ -33,8 +121,16 @@ class RP2040 {
33121 static int f_cpu () {
34122 return clock_get_hz (clk_sys);
35123 }
124+
125+ void idleOtherCore () { fifo.idleOtherCore (); }
126+ void resumeOtherCore () { fifo.resumeOtherCore (); }
127+
128+ // Multicore comms FIFO
129+ _MFIFO fifo;
36130};
37131
132+ extern RP2040 rp2040;
133+
38134// Wrapper class for PIO programs, abstracting common operations out
39135// TODO - Make dualcore safe
40136// TODO - Add unload/destructor
0 commit comments