前文说过树莓派 Pico 开发板片上主芯片为 RP2040 单片机,双核 Arm Cortex-M0 + 处理器,工作主频为 133MHz,264K 片上 SRAM,和 2MByteFlash。之前相关的 Project 都只用到了其中 1 个核,这次来体验一下双核。
1、官方代码
pico-examples
官方 pico-examples 提供了相关双核的示例,位于 multicore 目录下,提供了 4 个示例:
- hello_multicore
- multicore_fifo_irqs
- multicore_runner
- multicore_runner_queue
pico-sdk
双核相关接口都在 pico-sdk/blob/master/src/rp2_common/pico_multicore/multicore.c 文件中。
接口:
void multicore_launch_core1(void (*entry)(void));
//fifo
uint32_t multicore_fifo_pop_blocking(void);
void multicore_fifo_push_blocking(uint32_t data);
//irq
inline void multicore_fifo_clear_irq(void);
void irq_set_exclusive_handler(uint num, irq_handler_t handler);
void irq_set_enabled(uint num, bool enabled);
inline bool multicore_fifo_rvalid(void);
2、FreeRTOS应用
FreeRTOS 也已经支持 SMP 功能。FreeRTOS SMP 相关的代码,目前是以分支形式在 FreeRTOS-Kernel 仓库里面的。仓库地址:https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/smp
FreeRTOS SMP 相关介绍可以在官网 https://www.freertos.org/symmetric-multiprocessing-introduction.html 页面下获取。
该页面上面就有 pico 在 FreeRTOS SMP 上应用的相关介绍 https://www.freertos.org/smp-demos-for-the-raspberry-pi-pico-board.html。
FreeRTOS 提供了 SMP 的 demo,位于 https://github.com/FreeRTOS/FreeRTOS-SMP-Demos.
SMP.md 中有介绍 SMP 相关的特殊 API。
DEMO 运行
- 下载 FreeRTOS-SMP-Demos
FreeRTOS-SMP-Demos 仓库里面通过 submodule 模式已经集成了 支持 SMP 的 FreeRTOS-Kernel
$ git clone --recursive https://github.com/FreeRTOS/FreeRTOS-SMP-Demos
- RP2040 的工程位于 FreeRTOS-SMP-Demos/FreeRTOS/Demo/CORTEX_M0+_RP2040,文件夹下集成了 PICO 编译需要的相关文件,可以直接编译。
$ tree -L 1
.
├── CMakeLists.txt
├── OnEitherCore
├── pico_sdk_import.cmake
├── README.md
└── Standard
该目录下有 2 个 demo
- Standard
- OnEitherCore
创建 build 目录并进入 build 目录,运行
$ mkdir build && cd build
$ cmake ..
$ make
编译完成后,会在 2 个 demo 下各自自动生成 2 个可执行文件。
Standard 项目
该项目编译后,会生成 main_blinky 和 main_full 两个可执行文件,分别对应 vLaunch() 下的宏 mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 控制的两个函数。
void vLaunch( void)
{
/* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
of this file. */
#if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )
{
main_blinky();
}
#else
{
main_full();
}
#endif
}
main_blinky 比较简单,分别创建了 2 个任务 prvQueueReceiveTask 和 prvQueueSendTask。
默认源代码不会显示当前任务运行在哪个核,可以在各自的任务中添加 printf("task %s is runing in core %d\r\n", __FUNCTION__, portGET_CORE_ID());
显示当前任务运行核。
运行如下:
task prvQueueSendTask is runing in core 1
task prvQueueReceiveTask is runing in core 0
也有可能 2 个 Task 都运行在 core0 或者 core1,每次上电可能会切换。
可以通过 FreeRTOS 提供的 SMP 专有的 API 设置在创建任务时候设置对应任务运行在哪个核。
void main_blinky( void )
{
printf(" Starting main_blinky.\n");
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
if( xQueue != NULL )
{
/* Start the two tasks as described in the comments at the top of this
file. */
TaskHandle_t task0_Handle = NULL;
xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
"Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
&task0_Handle ); /* The task handle is not required, so NULL is passed. */
UBaseType_t task0_CoreAffinityMask = (1 << 1);
vTaskCoreAffinitySet(task0_Handle, task0_CoreAffinityMask);
TaskHandle_t task1_Handle = NULL;
xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, &task1_Handle );
UBaseType_t task1_CoreAffinityMask = (1 << 0);
vTaskCoreAffinitySet(task1_Handle, task1_CoreAffinityMask);
/* Start the tasks and timer running. */
vTaskStartScheduler();
}
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then
there was insufficient FreeRTOS heap memory available for the Idle and/or
timer tasks to be created. See the memory management section on the
FreeRTOS web site for more details on the FreeRTOS heap
http://www.freertos.org/a00111.html. */
for( ;; );
}
运行如下:
task prvQueueSendTask is runing in core 0
task prvQueueReceiveTask is runing in core 1