树莓派pico(RP2040)从零配置FreeRTOS-202210.01 LTS
目录
前期准备
工作环境是Windos 11+wsl2.0(debian)+arm-none-eabi-gcc(12.2.1),vscode,pico_c/c++_sdk(最新版),FreeRTOS(202210.01 LTS)。本文的起点是vscode可以正常编译rp2040工程。不在文中赘述开发环境的安装细节,也不提供相关文件的安装包,搭建环境有困难的私信,不定时回复。涉及到的软件在以下链接下载:
FreeRTOS:
https://github.com/FreeRTOS/FreeRTOS-LTS/releases/download/202210.01-LTS/FreeRTOSv202210.01-LTS.zip
pico-sdk
https://github.com/raspberrypi/pico-sdk
pico-project-generator
https://github.com/raspberrypi/pico-project-generator
step0-准备一个可以正常编译通过的工程
为了保证你的操作完全和我同步,用pico_project_generator来生成模板工程:
./pico_project.py RtosPico
以上代码会在脚本所在目录生成一个名为RtosPico的目录,目录下是名为RtosPico的工程,目录可以移动到任意地方。移动工程后清理cmake缓存或删除build目录。
注意pico_project_generator是一个python脚本,运行时如果提示找不到tk模块,请移步百度自己找安装方法。
如果有可用的工程可以直接拿来用,此步骤非必须。
step1-把FreeRTOS-Kernel文件夹放到工程目录下
注意下载的文件解压后包含多级目录,我们要复制的目录为"FreeRTOS-Kernel"
复制完成后,工程目录的结构如下:
wjl@WWJJLL:~/RtosPico$ ls -all
total 24
drwxr-xr-x 3 wjl wjl 4096 Feb 26 15:52 .
drwx------ 13 wjl wjl 4096 Feb 26 15:49 ..
-rw-r--r-- 1 wjl wjl 1290 Feb 26 15:39 CMakeLists.txt
drwxr-xr-x 4 wjl wjl 4096 Feb 26 15:52 FreeRTOS-Kernel
-rw-r--r-- 1 wjl wjl 3165 Feb 26 15:39 pico_sdk_import.cmake
-rw-r--r-- 1 wjl wjl 126 Feb 26 15:39 RtosPico.c
step2-修改工程顶层CMakeLists.txt文件
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0")
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()
project(RtosPico C CXX ASM)
pico_sdk_init()
add_subdirectory(FreeRTOS-Kernel) #将FreeRTOS作为子模块添加到工程
include_directories(
FreeRTOS-Kernel/include #增加freertos的include目录
)
add_executable(RtosPico RtosPico.c )
pico_set_program_name(RtosPico "RtosPico")
pico_set_program_version(RtosPico "0.1")
pico_enable_stdio_uart(RtosPico 1)
pico_enable_stdio_usb(RtosPico 0)
target_link_libraries(RtosPico
pico_stdlib
freertos_kernel #静态链接Freertos库
hardware_gpio #GPIO用来测试freertos
)
step2-添加FreeRTOSConfig.h文件
在FreeRTOS-Kernel目录下,新建文件"FreeRTOSConfig.h",复制以下内容到文件中:
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ 125000000
#define configSYSTICK_CLOCK_HZ 1000000
#define configTICK_RATE_HZ 1000
#define configMAX_PRIORITIES 4
#define configMINIMAL_STACK_SIZE 256
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_TASK_NOTIFICATIONS 1
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3
#define configUSE_MUTEXES 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_COUNTING_SEMAPHORES 0
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE 10
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
#define configSTACK_DEPTH_TYPE uint16_t
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE 50000
#define configAPPLICATION_ALLOCATED_HEAP 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 1
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 3
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Interrupt nesting behaviour configuration. */
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
/* Define to trap errors during development. */
//#define configASSERT( ( x ) ) assert()
/* FreeRTOS MPU specific definitions. */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
#define configTOTAL_MPU_REGIONS 8 /* Default value. */
#define configTEX_S_C_B_FLASH 0x07UL /* Default value. */
#define configTEX_S_C_B_SRAM 0x07UL /* Default value. */
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xResumeFromISR 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 0
#define INCLUDE_xTaskGetHandle 0
#define INCLUDE_xTaskResumeFromISR 1
#define vPortSVCHandler isr_svcall
#define xPortPendSVHandler isr_pendsv
#define xPortSysTickHandler isr_systick
/* A header file that defines trace macro can be included here. */
#endif /* FREERTOS_CONFIG_H */
step3-修改FreeRTOS的CMakeLists.txt文件
freertos的cmake配置有两处内容是明确要用户做配置的
# User is responsible to set two mandatory options:
# FREERTOS_CONFIG_FILE_DIRECTORY
# FREERTOS_PORT
1.FREERTOS_CONFIG_FILE_DIRECTORY是内核的工程配置文件,填写上一步新建文件的文件路径,注意是绝对路径.
2.FREERTOS_PORT,是平台相关的接口定义文件。文件中有所有内核支持的平台名称,此处我们按说明,配置为"GCC_RP2040"
3.找到这两处定义并修改为如下:
set(FREERTOS_CONFIG_FILE_DIRECTORY "/home/wjl/RtosPico/FreeRTOS-Kernel/" CACHE STRING "Absolute path to the directory with FreeRTOSConfig.h")
set(FREERTOS_PORT "GCC_RP2040" CACHE STRING "")
step4-修改RtosPico.c文件
#include <stdio.h>
#include <hardware/gpio.h>
#include <FreeRTOS.h>
#include <timers.h>
#include <task.h>
#include "pico/stdlib.h"
#define ledApp1 2
#define ledApp2 4
static void app1(void*);
static void app2(void*);
int main()
{
stdio_init_all();
xTaskCreate(app1,"app1",1024,NULL,1,NULL);
xTaskCreate(app2,"app1",1024,NULL,1,NULL);
vTaskStartScheduler();
while(1);
return 0;
}
void app1(void* vp)
{
gpio_init(ledApp1);
gpio_set_dir(ledApp1,GPIO_OUT);
while(1)
{
gpio_put(ledApp1,0);
vTaskDelay(1000);
gpio_put(ledApp1,1);
vTaskDelay(1000);
}
}
void app2(void* vp)
{
gpio_init(ledApp2);
gpio_set_dir(ledApp2,GPIO_OUT);
while(1)
{
gpio_put(ledApp2,0);
vTaskDelay(500);
gpio_put(ledApp2,1);
vTaskDelay(500);
}
}
创建两个应用程序app1,app2分别驱动不同的io,
两个led分别接到gpio2和gpio4,程序正常运行时,两个led以不同的频率闪烁。
step5-注意事项
1.如果工程的包含文件改动后不能生效,尝试清理cmake缓存,或者直接删除build文件夹后重新生成工程。
2.最终版本的工程已上传到git,修改CMakeLists.txt中的pico_sdk_path为你自己的sdk路径就可以直接编译通过。
https://github.com/AndrewWang1111/RtosPico