diff --git a/multicore/CMakeLists.txt b/multicore/CMakeLists.txt index ea7420d..c19e40b 100644 --- a/multicore/CMakeLists.txt +++ b/multicore/CMakeLists.txt @@ -1,5 +1,6 @@ if (NOT PICO_NO_HARDWARE) add_subdirectory(hello_multicore) add_subdirectory(multicore_runner) + add_subdirectory(multicore_runner_queue) add_subdirectory(multicore_fifo_irqs) endif () \ No newline at end of file diff --git a/multicore/multicore_runner_queue/CMakeLists.txt b/multicore/multicore_runner_queue/CMakeLists.txt new file mode 100644 index 0000000..c35368a --- /dev/null +++ b/multicore/multicore_runner_queue/CMakeLists.txt @@ -0,0 +1,13 @@ +add_executable(multicore_runner_queue + multicore_runner_queue.c + ) + +target_link_libraries(multicore_runner_queue + pico_multicore + pico_stdlib) + +# create map/bin/hex file etc. +pico_add_extra_outputs(multicore_runner_queue) + +# add url via pico_set_program_url +example_auto_set_url(multicore_runner_queue) \ No newline at end of file diff --git a/multicore/multicore_runner_queue/multicore_runner_queue.c b/multicore/multicore_runner_queue/multicore_runner_queue.c new file mode 100644 index 0000000..b0e2ec6 --- /dev/null +++ b/multicore/multicore_runner_queue/multicore_runner_queue.c @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/util/queue.h" +#include "pico/multicore.h" + +#define FLAG_VALUE 123 + +typedef struct +{ + void *func; + int32_t data; +} queue_entry_t; + +queue_t call_queue; +queue_t results_queue; + +void core1_entry() { + while (1) { + // Function pointer is passed to us via the queue_entry_t which also + // contains the function parameter. + // We provide an int32_t return value by simply pushing it back on the + // return queue which also indicates the result is ready. + + queue_entry_t entry; + + queue_remove_blocking(&call_queue, &entry); + + int32_t (*func)() = (int32_t(*)())(entry.func); + int32_t result = (*func)(entry.data); + + queue_add_blocking(&results_queue, &result); + } +} + +int32_t factorial(int32_t n) { + int32_t f = 1; + for (int i = 2; i <= n; i++) { + f *= i; + } + return f; +} + +int32_t fibonacci(int32_t n) { + if (n == 0) return 0; + if (n == 1) return 1; + + int n1 = 0, n2 = 1, n3; + + for (int i = 2; i <= n; i++) { + n3 = n1 + n2; + n1 = n2; + n2 = n3; + } + return n3; +} + +#define TEST_NUM 10 + +int main() { + int32_t res; + + stdio_init_all(); + printf("Hello, multicore_runner using queues!\n"); + + // This example dispatches arbitrary functions to run on the second core + // To do this we run a dispatcher on the second core that accepts a function + // pointer and runs it. The data is passed over using the queue library from + // pico_utils + + queue_init(&call_queue, sizeof(queue_entry_t), 2); + queue_init(&results_queue, sizeof(int32_t), 2); + + multicore_launch_core1(core1_entry); + + queue_entry_t entry = {&factorial, TEST_NUM}; + queue_add_blocking(&call_queue, &entry); + + // We could now do a load of stuff on core 0 and get our result later + + queue_remove_blocking(&results_queue, &res); + + printf("Factorial %d is %d\n", TEST_NUM, res); + + // Now try a different function + entry.func = &fibonacci; + queue_add_blocking(&call_queue, &entry); + + queue_remove_blocking(&results_queue, &res); + + printf("Fibonacci %d is %d\n", TEST_NUM, res); +}