Recent versions of zeptoforth (release 0.25.0 or newer) now support straightforward symmetric multiprocessing in that they support interaction between tasks executing on different cores of the RP2040 interacting with one another with task communication and synchronization constructs, which was not supported by older versions of zeptoforth which only supported multicore execution where different cores did not interact with each other aside from through shared RAM, hardware spinlocks, and hardware FIFO's. Additionally any task on any core can now start a task on any given core, where previously one had to explicitly boot the second core of the RP2040 from the first core and aside from that tasks could only spawn tasks on their own core.
For an example of multicore operation combined with multitasking with shared task communication and synchronization constructs, take the following example:
continue-module forth
task import
systick import
chan import
\ The data size
1 constant element-size
\ The intermediate stream byte count
256 constant inter-count
\ The endpoint stream byte count
256 constant end-count
\ The endpoint counter interval
1000 constant end-interval
\ The tasks
variable producer-task
variable inter-task
variable consumer-task
\ The streams
element-size inter-count chan-size buffer: inter-chan
element-size end-count chan-size buffer: end-chan
\ The data buffers
element-size buffer: source-send-buf
element-size buffer: inter-recv-buf
element-size buffer: end-recv-buf
\ The receive count
variable recv-count
\ The starting systick
variable start-systick
\ Our producer
: producer ( -- )
source-send-buf element-size 0 fill
begin source-send-buf element-size inter-chan send-chan again
;
\ Our intermediate
: inter ( -- )
begin
inter-recv-buf element-size inter-chan recv-chan
inter-recv-buf swap end-chan send-chan
again
;
\ Our consumer
: consumer ( -- )
begin
1 recv-count +!
end-recv-buf element-size end-chan recv-chan drop
recv-count @ end-interval > if
0 recv-count !
systick-counter dup start-systick @ -
cr ." Receives per second: " 0 swap 0 end-interval f/
10000,0 f/ 1,0 2swap f/ f.
start-systick !
then
again
;
\ Initialize our test
: init-test ( -- )
0 recv-count !
systick-counter start-systick !
element-size inter-count inter-chan init-chan
element-size end-count end-chan init-chan
0 ['] consumer 320 128 512 0 spawn-on-core consumer-task !
0 ['] inter 320 128 512 1 spawn-on-core inter-task !
0 ['] producer 320 128 512 0 spawn-on-core producer-task !
consumer-task @ run
inter-task @ run
producer-task @ run
;
end-module
In this example, three tasks are spawned, a consumer task on core 0, an intermediate task on core 1, and a producer task on core 0. Two queue channels (a task synchronization and communication construct that consists of a queue which one or more tasks send messages to and which one or more task receive messages from) are created, one for communication from the producer task to the intermediate task, and one for communication from the intermediate task to the consumer task.
The producer task continually sends messages to the intermediate task with the only delays being when the channel for communication from the producer task to the intermediate task is full. The intermediate task continually receives single messages from the producer task and sends the same messages to the consumer task. The consumer task continually receives messages from the intermediate task, and times how long it takes for a given number of messages to be received, with which it calculates how many messages it has received per second and displays it to the user..
By this inter-task communication is demonstrated to function across multiple cores using task communication and synchronization constructs. Likewise, one task can use RUN to initiate a task on another core, as also shown here. (Unlike previously, spawning a task on another core no longer starts it immediately; rather the user must use RUN to start its execution.)
Travis Bemann
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.