Multicore Words¶
Currently the only platform on which multicore execution is supported is the RP2040. On this platform cores communicate and synchronize via hardware spinlocks and hardware FIFO’s (i.e. mailboxes). On platforms other than the RP2040 multicore words exist in the dictionary but are merely stubs which will always raise exceptions when called.
Note that prior limitations to multicore operation on the RP2040 have been resolved, with there being no need to disable interrupt-driven serial IO, with tasks being able to be started arbitrarily on any core from a task on any core, with multitasking constructs being able to be used across cores, and with writing and erasing flash functioning properly when both cores are operational.
Multicore support in zeptoforth is largely implemented outside the zeptoforth kernel and is split between src/rp2040/forth/multicore.fs (on platforms other than RP2040 stubbed out in src/common/forth/multicore.fs) and src/common/forth/task.fs, with a bit of supporting functionality also in src/common/forth/systick.fs and src/rp2040/forth/erase.fs.
forth¶
Built into the kernel exists:
cpu-count¶
( – count )
Get the core count.
cpu-index¶
( – index )
Get the index of the core from which cpu-index was called.
cpu-offset¶
( – offset )
Return 4 times cpu-index.
sio-hook¶
( – addr )
Get the address of a hook for the current core which may be set to an xt ( u – ) to handle values written to that core’s FIFO by the other core; note that a value of 0 (the default value) means that values read from the core’s FIFO are discarded.
In src/common/forth/basic.fs, in forth, exists:
cpu-variable¶
( “global-name” “cpu-name” – )
Compile a one-cell-per-core variable into flash that has two words referring to it, a global-name which takes a core index when called and outputs the address for that core, and a cpu-name which returns its address for the current core.
multicore¶
In both src/rp2040/forth/multicore.fs and src/common/forth/multicore.fs, in multicore on all platforms, exists:
x-spinlock-out-of-range¶
( – )
Spinlock out of range exception.
x-core-out-of-range¶
( – )
Core out of range exception, i.e. core index not in range 0 <= core < cpu-count.
x-core-not-addressable¶
( – )
Core not addressable exception, i.e. invalid core for an operation carried out ont the current core.
In src/rp2040/forth/multicore.fs, in multicore on the rp2040 platform, exists:
sev¶
( – )
Signal an event to the other core.
wfe¶
( – )
Wait for an event.
SIO_IRQ_PROC0¶
( – irq )
SIO processor 0 IRQ index, i.e. 15.
SIO_IRQ_PROC1¶
( – irq )
SIO processor 1 RIQ index, i.e. 16.
FIFO_ST¶
( – addr )
FIFO status register; note that core 0 can see the read side of the 1 -> 0 FIFO and the write side of the 0 -> 1 FIFO; the converse is true of core 1
FIFO_ST_ROE¶
( – bit )
Sticky flag indicating the RX FIFO was read when empty; write to clear.
FIFO_ST_WOF¶
( – bit )
Sticky flag indicating the TX FIFO was written when full; write to clear.
FIFO_ST_VLD¶
( – bit )
Set if this core’s RX FIFO is not empty.
FIFO_WR¶
( – bit )
Write access from this core’s TX FIFO.
FIFO_RD¶
( – bit )
Read access to this core’s RX FIFO.
SPINLOCK¶
( index – addr )
Returns the address of a spinlock with a given index. Note that reading from an spinlock claims it if a value other than 0 is read (which will be the index of the spinlock), with a value of 0 indicating that the spinlock is already held, and writing to a spinlock releases it.
spinlock-count¶
( – count )
Returns the spinlock count, i.e. 32.
claim-spinlock¶
( spinlock-index – )
Claim a spinlock; no validation is carried out.
release-spinlock¶
( spinlock-index – )
Release a spinlock; no validation is carried out.
claim-same-core-spinlock¶
( – )
Claim a multitasker spinlock for the current core.
release-same-core-spinlock¶
( – )
Release a multitasker spinlock for the current core.
claim-other-core-spinlock¶
( core – )
Claim a multitasker spinlock for the specified core.
release-other-core-spinlock¶
( core – )
Release a multitasker spinlock for the specified core.
claim-all-core-spinlock¶
( – )
Claim all the multitasker spinlocks.
release-all-core-spinlock¶
( – )
Release all the multitasker spinlocks.
with-spinlock¶
( xt spinlock – )
Claim a spinlock while executing xt, releasing it afterwards
critical-with-spinlock¶
( xt spinlock – )
Claim a spinlock, enter a critical section, execute xt, release the spinlock, and then exit the critical section.
critical-with-other-core-spinlock¶
( xt core – )
Claim a multitasker spinlock for the specified core, enter a critical section, execute xt, release the spinlock, and then exit the critical section.
fifo-drain¶
( core – )
Drain a FIFO for inter-core communication; if core is outside the range 0 <= x < 2 x-core-out-of-range is raised; if core is equal to cpu-index x-core-not-addressable is raised.
fifo-push-blocking¶
( x core – )
Do a blocking push onto a FIFO for inter-core communication; if core is outside the range 0 <= x < 2 x-core-out-of-range is raised; if core is equal to cpu-index x-core-not-addressable is raised.
fifo-pop-blocking¶
( core – x )
Do a blocking pop from a FIFO for inter-core communication; if core is outside the range 0 <= x < 2 x-core-out-of-range is raised; if core is equal to cpu-index x-core-not-addressable is raised.
fifo-push-confirm¶
( x core – confirmed? )
Do a blocking push onto a FIFO for inter-core communication; if core is outside the range 0 <= x < 2 x-core-out-of-range is raised; if core is equal to cpu-index x-core-not-addressable is raised. Afterwards do a blocking pop from the FIFO for receiving fromt he same core and return whether the value pushed is the same as the value popped.
launch-aux-core¶
( vector-table stack-ptr rstack-ptr entry-xt core – )
Launch an auxiliary core, i.e. a core core other than core 0 and execute entry-xt on it with the return stack pointer rstack-ptr, the data stack pointer stack-ptr, and the vector table base vector-table. Note that it is not recommended that this be used by the user, rather the user should use spawn-aux-main in src/common/forth/task.fs.
with-hold-core¶
( xt – )
Hold the other core, execute the provided xt, release the other core even if an exception had been raised, and if an exception had been raised re-raise it.
In src/common/forth/multicore.fs, in multicore for all platforms other than rp2040, exists:
spinlock-count¶
( – count )
Returns the spinlock count, i.e. 0.
claim-spinlock¶
( spinlock-index – )
Drop spinlock-index.
release-spinlock¶
( spinlock-index – )
Drop spinlock-index.
claim-same-core-spinlock¶
( – )
This is a no-op.
release-same-core-spinlock¶
( – )
This is a no-op.
claim-other-core-spinlock¶
( core – )
Drop core.
release-other-core-spinlock¶
( core – )
Drop core.
claim-all-core-spinlock¶
( – )
This is a no-op.
release-all-core-spinlock¶
( – )
This is a no-op.
with-spinlock¶
( xt spinlock – )
Drop spinlock and execute xt.
critical-with-spinlock¶
( xt spinlock – )
Drop spinlock and execute xt in a critical section.
critical-with-other-core-spinlock¶
( xt core – )
Drop core and execute xt in a critical section.
test-set¶
( value addr – set? )
Atomically test a value at addr and set it to value if it was previously 0, and return whether it was previously 0.
test-set-raw¶
( value addr – set? )
Atomically test a value at addr and set it to value if it was previously 0, and return whether it was previously 0. This is different from test-set in that it assumes that interrupts were already disabled, and does not enable interrupts.
fifo-drain¶
( core – )
Placeholder for draining a FIFO for inter-core communication; this will always raise x-core-out-of-range.
fifo-push-blocking¶
( x core – )
Placeholder for doing a blocking push onto a FIFO for inter-core communication; this will always raise x-core-out-of-range.
fifo-pop-blocking¶
( core – x )
Placeholder for doing a blocking pop from a FIFO for inter-core communication; this will always raise x-core-out-of-range.
fifo-push-confirm¶
( x core – confirmed? )
Placeholder for attempting to send data on a FIFO and confirming that the same data is sent back; this will always raise x-core-out-of-range.
launch-aux-core¶
( xt stack-ptr rstack-ptr core – )
Placeholder for attempting to launch an auxiliary core; this will always raise x-core-out-of-range.
with-hold-core¶
( xt – )
This simply executes the provided xt.