FreeRTOS超详细移植教程
目录
FreeRtos 概述
FreeRTOS是面向单片机MCU的开源轻量级抢占式实时操作系统内核,全部使用标准C语言开发,适合资源有限的嵌入式设备。该系统2003年由Richard Barry开发,2017年被亚马逊AWS收购,采用MIT协议,商用免费且无需开源项目源码,这是相比uCOS的核心优势。Free即免费,RTOS是实时操作系统的缩写,原生Vanilla FreeRTOS只保留任务、队列、信号量、定时器核心调度功能,GD32、STM32项目大多移植这个版本;Amazon FreeRTOS额外配套MQTT、TLS、OTA等IoT组件,用于设备接入亚马逊云。它内核体积很小,编译后ROM仅6~12KB,支持四十余种处理器架构,主流编译器均可适配,在工业和物联网领域应用十分广泛。
FreeRTOS默认使用固定优先级抢占式调度,搭配同优先级时间片轮转,高优先级任务就绪时可直接抢占CPU、切换上下文,实现实时响应,这也是它和裸机while(1)循环最大的区别。Tick滴答定时器周期性产生中断,一般设置为1ms,负责系统计时与任务延时判断。任务拥有运行、就绪、阻塞、挂起四种状态,阻塞状态下任务不占用CPU,此时会执行系统自带最低优先级的空闲任务,空闲任务钩子函数能够实现低功耗功能,被手动挂起的任务,需要主动恢复才会参与调度。
准备
首先我们准备一个干净的工程文件,最好是自己验证过能跑个流水灯啥的

下面提供源码下载地址:


裁剪
首先这个文件夹里面大部分文件都可以删除,如下图,后续我们把portable里面需要的文件移植出来,这个portable也可以删除了

portable裁剪
port
-
port.c—— 移植实现(上下文切换、栈初始化、SysTick 等)
我使用的是GD32F450系列芯片不带那个浮点的所以我只能选择这个cm4F,大家可以根据自己的需要进行选择。
参考目录:freerots\portable\RVDS\ARM_CM4F

heap
FreeRTOS 的 5 种堆管理方案,核心区别在于能否释放内存、是否合并碎片、以及能否管理不连续的内存区域。
\portable\MemMang

下面这个是官方关于这五个文件的介绍,我总结了一下,然后常用的就是这个第四个
| 特性 | heap_1 | heap_2 | heap_3 | heap_4 | heap_5 |
|---|---|---|---|---|---|
| 能否释放内存 | ❌ 不能 | ✅ 能 | ✅ 能 | ✅ 能 | ✅ 能 |
| 是否合并空闲块 | N/A | ❌ 不合并 | N/A (由标准库处理) | ✅ 自动合并 | ✅ 自动合并 |
| 管理不连续内存 | ❌ 不支持 | ❌ 不支持 | ❌ 不支持 | ❌ 不支持 | ✅ 支持 |
| 碎片问题 | 一次性分配 | 严重 (不合并) | 取决于标准库 | (合并算法) | 较(合并算法) |
| 实现原理 | 简单分配 | 首次适应算法 | 封装 malloc/free | 最佳匹配+合并 | 同 heap_4 |
| 线程安全 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 适用场景 | 一次性初始化后不再创建/删除对象 | 只创建/删除同尺寸对象 (已过时) | 需要完全依赖标准库的场景 | 通用场景 (最常用) | 内存分散在多个不连续区域 |
freerotsconfig
参考目录:FreeRTOS-Kernel-main\FreeRTOS-Kernel-main\examples\template_configuration
简单让ai帮我写一下中文注释
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/* ========== 硬件描述 ========== */
#define configCPU_CLOCK_HZ ( ( unsigned long ) 20000000 ) /* CPU 主频,Hz,按实际改 */
/* #define configSYSTICK_CLOCK_HZ [平台相关] */ /* SysTick 时钟频率,一般不用定义 */
/* ========== 调度行为 ========== */
#define configTICK_RATE_HZ 100 /* tick 频率,Hz */
#define configUSE_PREEMPTION 1 /* 1=抢占式调度,0=协作式 */
#define configUSE_TIME_SLICING 0 /* 1=同优先级时间片轮转,0=不轮转 */
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 /* 1=用硬件指令选任务,0=通用 C 算法 */
#define configUSE_TICKLESS_IDLE 0 /* 1=低功耗 tickless 模式,0=常开 tick */
#define configMAX_PRIORITIES 5 /* 最大任务优先级数 */
#define configMINIMAL_STACK_SIZE 128 /* 空闲任务栈大小(单位:字) */
#define configMAX_TASK_NAME_LEN 16 /* 任务名最大长度(含结尾符) */
#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS /* tick 计数用 32 位 */
#define configIDLE_SHOULD_YIELD 1 /* 1=空闲任务对同优先级任务让出,0=不让出 */
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 /* 任务通知数组条目数 */
#define configQUEUE_REGISTRY_SIZE 0 /* 队列注册表大小(调试用) */
#define configENABLE_BACKWARD_COMPATIBILITY 0 /* 1=兼容旧版 API 名字,0=不兼容 */
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 /* 线程本地存储指针数量 */
#define configUSE_MINI_LIST_ITEM 1 /* 1=用精简链表项省 RAM,0=用完整项 */
#define configSTACK_DEPTH_TYPE size_t /* 栈深度参数类型 */
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t /* 消息缓冲长度字段类型 */
#define configHEAP_CLEAR_MEMORY_ON_FREE 1 /* 1=释放时清零内存,0=不清零 */
#define configSTATS_BUFFER_MAX_LENGTH 0xFFFF /* vTaskList 等统计缓冲区最大长度 */
#define configUSE_NEWLIB_REENTRANT 0 /* 1=为每个任务分配 newlib 重入结构,0=不分配 */
/* ========== 软件定时器 ========== */
#define configUSE_TIMERS 1 /* 1=启用软件定时器,0=不启用 */
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) /* 定时器任务优先级 */
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE /* 定时器任务栈大小(字) */
#define configTIMER_QUEUE_LENGTH 10 /* 定时器命令队列长度 */
/* ========== 事件组 ========== */
#define configUSE_EVENT_GROUPS 1 /* 1=启用事件组,0=不启用 */
/* ========== 流缓冲 / 消息缓冲 ========== */
#define configUSE_STREAM_BUFFERS 1 /* 1=启用流缓冲,0=不启用 */
/* ========== 内存分配 ========== */
#define configSUPPORT_STATIC_ALLOCATION 1 /* 1=支持静态创建对象 */
#define configSUPPORT_DYNAMIC_ALLOCATION 1 /* 1=支持动态创建对象 */
#define configTOTAL_HEAP_SIZE 4096 /* FreeRTOS 堆总大小,单位:字节 */
#define configAPPLICATION_ALLOCATED_HEAP 0 /* 1=应用自己分配堆数组,0=链接器分配 */
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 /* 1=任务栈从单独堆分配,0=从主堆分配 */
#define configENABLE_HEAP_PROTECTOR 0 /* 1=启用堆指针保护,0=不启用 */
/* ========== 中断嵌套行为 ========== */
#define configKERNEL_INTERRUPT_PRIORITY 0 /* 内核中断优先级(tick/PendSV) */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0 /* 允许调 API 的最高中断优先级 */
#define configMAX_API_CALL_INTERRUPT_PRIORITY 0 /* 同上,不同 port 用的名字 */
/* ========== 钩子函数 ========== */
#define configUSE_IDLE_HOOK 0 /* 1=启用空闲钩子 */
#define configUSE_TICK_HOOK 0 /* 1=启用 tick 钩子 */
#define configUSE_MALLOC_FAILED_HOOK 0 /* 1=启用 malloc 失败钩子 */
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 /* 1=启用守护任务启动钩子 */
#define configUSE_SB_COMPLETED_CALLBACK 0 /* 1=启用流缓冲收发完成回调 */
#define configCHECK_FOR_STACK_OVERFLOW 2 /* 0=不检查栈溢出,1=快但弱,2=慢但强 */
/* ========== 运行时统计 ========== */
#define configGENERATE_RUN_TIME_STATS 0 /* 1=收集各任务运行时间 */
#define configUSE_TRACE_FACILITY 0 /* 1=启用 trace 调试功能 */
#define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* 1=启用 vTaskList 等格式化函数 */
/* ========== 协程 ========== */
#define configUSE_CO_ROUTINES 0 /* 1=启用协程 */
#define configMAX_CO_ROUTINE_PRIORITIES 1 /* 协程最大优先级数 */
/* ========== 调试断言 ========== */
#define configASSERT( x ) \
if( ( x ) == 0 ) \
{ \
taskDISABLE_INTERRUPTS(); \
for( ; ; ) \
; \
} \
/* 断言失败:关中断并死循环,方便调试器查看 */
/* ========== FreeRTOS MPU 相关(标准 Cortex-M port 不用) ========== */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 /* 1=允许应用定义特权函数 */
#define configTOTAL_MPU_REGIONS 8 /* MPU 区域数量,通常 8 或 16 */
#define configTEX_S_C_B_FLASH 0x07UL /* Flash 区域 TEX/S/C/B 位 */
#define configTEX_S_C_B_SRAM 0x07UL /* RAM 区域 TEX/S/C/B 位 */
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1 /* 1=只允许内核发起系统调用 */
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 0 /* 1=允许非特权任务进临界区 */
#define configUSE_MPU_WRAPPERS_V1 0 /* 1=用旧版 MPU wrapper,0=用 v2 */
#define configPROTECTED_KERNEL_OBJECT_POOL_SIZE 10 /* v2 wrapper 下内核对象池大小 */
#define configSYSTEM_CALL_STACK_SIZE 128 /* 系统调用栈大小(字) */
#define configENABLE_ACCESS_CONTROL_LIST 1 /* 1=启用访问控制列表 */
/* ========== SMP 多核相关 ========== */
/* #define configNUMBER_OF_CORES [核心数] */ /* 多核时定义,单核不定义 */
#define configRUN_MULTIPLE_PRIORITIES 0 /* 多核:1=允许不同优先级同时跑 */
#define configUSE_CORE_AFFINITY 0 /* 多核:1=启用核亲和性 */
#define configTASK_DEFAULT_CORE_AFFINITY tskNO_AFFINITY /* 任务默认核亲和性 */
#define configUSE_TASK_PREEMPTION_DISABLE 0 /* 多核:1=允许单任务关抢占 */
#define configUSE_PASSIVE_IDLE_HOOK 0 /* 多核:1=启用被动空闲钩子 */
#define configTIMER_SERVICE_TASK_CORE_AFFINITY tskNO_AFFINITY /* 定时器任务核亲和性 */
#define configIDLE_AFFINITY 0 /* 多核:1=空闲任务绑核 */
/* ========== ARMv8-M 安全侧 ========== */
#define secureconfigMAX_SECURE_CONTEXTS 5 /* 可调用安全侧的最大任务数 */
#define configKERNEL_PROVIDED_STATIC_MEMORY 1 /* 1=内核提供空闲/定时器任务内存 */
/* ========== ARMv8-M port ========== */
#define configENABLE_TRUSTZONE 1 /* 1=启用 TrustZone */
#define configRUN_FREERTOS_SECURE_ONLY 1 /* 1=FreeRTOS 只在安全侧跑 */
#define configENABLE_MPU 1 /* 1=启用 MPU */
#define configENABLE_FPU 1 /* 1=启用 FPU */
#define configENABLE_MVE 1 /* 1=启用 MVE(仅 M52/M55/M85/STAR-MC3) */
/* ========== ARMv7-M / ARMv8-M port ========== */
#define configCHECK_HANDLER_INSTALLATION 1 /* 1=检查 SVC/PendSV 中断是否正确安装 */
/* ========== 功能开关 ========== */
#define configUSE_TASK_NOTIFICATIONS 1 /* 1=启用任务通知 */
#define configUSE_MUTEXES 1 /* 1=启用互斥量 */
#define configUSE_RECURSIVE_MUTEXES 1 /* 1=启用递归互斥量 */
#define configUSE_COUNTING_SEMAPHORES 1 /* 1=启用计数信号量 */
#define configUSE_QUEUE_SETS 0 /* 1=启用队列集 */
#define configUSE_APPLICATION_TASK_TAG 0 /* 1=启用任务标签 */
#define configUSE_POSIX_ERRNO 0 /* 1=启用 POSIX errno */
/* ========== API 函数开关 ========== */
#define INCLUDE_vTaskPrioritySet 1 /* 启用 vTaskPrioritySet */
#define INCLUDE_uxTaskPriorityGet 1 /* 启用 uxTaskPriorityGet */
#define INCLUDE_vTaskDelete 1 /* 启用 vTaskDelete */
#define INCLUDE_vTaskSuspend 1 /* 启用 vTaskSuspend */
#define INCLUDE_xTaskDelayUntil 1 /* 启用 xTaskDelayUntil */
#define INCLUDE_vTaskDelay 1 /* 启用 vTaskDelay */
#define INCLUDE_xTaskGetSchedulerState 1 /* 启用 xTaskGetSchedulerState */
#define INCLUDE_xTaskGetCurrentTaskHandle 1 /* 启用 xTaskGetCurrentTaskHandle */
#define INCLUDE_uxTaskGetStackHighWaterMark 0 /* 启用 uxTaskGetStackHighWaterMark */
#define INCLUDE_xTaskGetIdleTaskHandle 0 /* 启用 xTaskGetIdleTaskHandle */
#define INCLUDE_eTaskGetState 0 /* 启用 eTaskGetState */
#define INCLUDE_xTimerPendFunctionCall 0 /* 启用 xTimerPendFunctionCall */
#define INCLUDE_xTaskAbortDelay 0 /* 启用 xTaskAbortDelay */
#define INCLUDE_xTaskGetHandle 0 /* 启用 xTaskGetHandle */
#define INCLUDE_xTaskResumeFromISR 1 /* 启用 xTaskResumeFromISR */
#endif /* FREERTOS_CONFIG_H */
总共裁剪下来就是

我们把文件添加进我们的工程

Freerotsconfig配置修改
这里我们首次尝试编译:
Build started: Project: gd32f450test
*** Using Compiler 'V5.06 update 7 (build 960)', folder: 'D:\keil5\keil535\ARM\ARMCC\Bin'
Build target 'Target 1'
compiling port.c...
..\freerots\port.c(42): error: #35: #error directive: configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
..\freerots\port.c: 0 warnings, 1 error
".\Objects\gd32f450test.axf" - 1 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed: 00:00:00
意思说我的这个freerotsconfig一些宏定义没有配置
#define configCPU_CLOCK_HZ这个我们取系统时钟,这里也可以自己去看看主频是多少自己填入也可以
#define configCPU_CLOCK_HZ ( ( unsigned long ) 200000000 ) /* 200MHz */
#define configCPU_CLOCK_HZ SystemCoreClock /* CPU 主频 */
定义这个tick,能决定我们的调度的时间片是多少,1000的话也就是1ms一个tick
#define configTICK_RATE_HZ 1000
#define configMAX_PRIORITIES优先级数量,源码是5,可以考虑更改
#define configMAX_PRIORITIES 30
Cortex-M 的优先级寄存器有 8 位,但芯片实际只用了高 4 位(configPRIO_BITS = 4),低 4 位无效。
所以,一个"逻辑优先级"(0~15)要左移 4 位才能写进寄存器:
逻辑优先级 5 → 二进制 0101 → 左移 4 位 → 0101 0000 → 0x50 逻辑优先级 15 → 二进制 1111 → 左移 4 位 → 1111 0000 → 0xF0
FreeRTOS 里的 0xF0、0x40 就是这种"已经左移过的硬件值"。
configKERNEL_INTERRUPT_PRIORITY 0xF0
configMAX_SYSCALL_INTERRUPT_PRIORITY 0x40
configMAX_API_CALL_INTERRUPT_PRIORITY 0x40
| 宏 | 值 | 含义 | 作用 |
|---|---|---|---|
configKERNEL_INTERRUPT_PRIORITY | 0xF0 | PendSV / SysTick 的优先级 | 内核中断设最低,让紧急中断优先,这个优先级就是处理任务调度等任务的优先级 |
configMAX_SYSCALL_INTERRUPT_PRIORITY | 0x40 | 分界线:≥ 此值可调 API | 保护内核,限制哪些中断能调 API,在cortex-m中数字越小优先级越高,所以这里添加这个是为了不允许中断里面添加freerots的任务函数,
|
configMAX_API_CALL_INTERRUPT_PRIORITY | 0x40 | 同上,别名 | 兼容不同 port 的命名 |
下面这个根据自己的芯片来
| 宏 | 修改 | 建议 |
|---|---|---|
configTOTAL_HEAP_SIZE | 100*1024(100KB) | 注意别超过实际可用 RAM |
configUSE_TIMERS | 0 | 省一个线程。你要用软定时器就改成 1 |
configCHECK_FOR_STACK_OVERFLOW | 0 | 调试阶段建议改成 1 或 2,量产再关 |
configUSE_TRACE_FACILITY | 0 | 1 就是方便调试,多占点 ROM |
configUSE_STATS_FORMATTING_FUNCTIONS | 0 | 同上 |
configUSE_POSIX_ERRNO | 0 | 方便拿 errno |
configUSE_QUEUE_SETS | 0 | 开了队列集,不用可以改回 0 |
下面这些是可以保留,但是没啥必要的
| 宏 | 修改 | 说明 |
|---|---|---|
configENABLE_TRUSTZONE | 0 | Cortex-M4 没有 TrustZone,此宏无效 |
configRUN_FREERTOS_SECURE_ONLY | 0 | 同上 |
configENABLE_MPU | 0 | 没 MPU,此宏只对 MPU port 有效 |
configENABLE_MVE | 0 | Cortex-M4 没有 MVE,此宏无效 |
configENABLE_FPU | 1 | GD32F450 有 FPU |
secureconfigMAX_SECURE_CONTEXTS | 0 | ARMv8-M 专用,无效 |
| 所有 SMP 相关 | 一堆 0 | 单核不用,无效,可以直接删除 |
对应的还有
我的 GD32F450 启动文件 startup_gd32f450.s 里定义了一张中断向量表,里面列了所有中断的名字,大家去找自己对应的就好了,比如:
DCD SVC_Handler ; SVCall 中断 DCD PendSV_Handler ; PendSV 中断 DCD SysTick_Handler ; SysTick 中断
CPU 遇到这些中断时,会去这张表里找对应的函数名,然后跳过去执行。
#define configCHECK_HANDLER_INSTALLATION 1 //开机时检查 SVC_Handler、PendSV_Handler 有没有正确安装到中断向量表
这里我们需要添加这个在这个文件末尾
-
启动文件里叫
SVC_Handler、PendSV_Handler、SysTick_Handler; -
FreeRTOS 里叫
vPortSVCHandler、xPortPendSVHandler、xPortSysTickHandler; -
名字对不上,CPU 中断时就找不到 FreeRTOS 的函数,系统跑不起来。
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
下面给大家全部的修改的代码
总
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "system_gd32f4xx.h"
/* ========== 硬件描述 ========== */
#define configCPU_CLOCK_HZ SystemCoreClock /* CPU 主频 */
/* ========== 调度行为 ========== */
#define configTICK_RATE_HZ 1000
#define configUSE_PREEMPTION 1 /* 1=抢占式调度,0=协作式 */
#define configUSE_TIME_SLICING 0 /* 1=同优先级时间片轮转,0=不轮转 */
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 /* 1=用硬件指令选任务,0=通用 C 算法 */
#define configUSE_TICKLESS_IDLE 0 /* 1=低功耗 tickless 模式,0=常开 tick */
#define configMAX_PRIORITIES 30 /* 最大任务优先级数 */
#define configMINIMAL_STACK_SIZE 128 /* 空闲任务栈大小(单位:字) */
#define configMAX_TASK_NAME_LEN 16 /* 任务名最大长度(含结尾符) */
#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS /* tick 计数用 32 位 */
#define configIDLE_SHOULD_YIELD 1 /* 1=空闲任务对同优先级任务让出,0=不让出 */
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 /* 任务通知数组条目数 */
#define configQUEUE_REGISTRY_SIZE 0 /* 队列注册表大小(调试用) */
#define configENABLE_BACKWARD_COMPATIBILITY 0 /* 1=兼容旧版 API 名字,0=不兼容 */
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 /* 线程本地存储指针数量 */
#define configUSE_MINI_LIST_ITEM 1 /* 1=用精简链表项省 RAM,0=用完整项 */
#define configSTACK_DEPTH_TYPE size_t /* 栈深度参数类型 */
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t /* 消息缓冲长度字段类型 */
#define configHEAP_CLEAR_MEMORY_ON_FREE 1 /* 1=释放时清零内存,0=不清零 */
#define configSTATS_BUFFER_MAX_LENGTH 0xFFFF /* vTaskList 等统计缓冲区最大长度 */
#define configUSE_NEWLIB_REENTRANT 0 /* 1=为每个任务分配 newlib 重入结构,0=不分配 */
/* ========== 软件定时器 ========== */
#define configUSE_TIMERS 0
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) /* 定时器任务优先级 */
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE /* 定时器任务栈大小(字) */
#define configTIMER_QUEUE_LENGTH 10 /* 定时器命令队列长度 */
/* ========== 事件组 ========== */
#define configUSE_EVENT_GROUPS 1 /* 1=启用事件组,0=不启用 */
/* ========== 流缓冲 / 消息缓冲 ========== */
#define configUSE_STREAM_BUFFERS 1 /* 1=启用流缓冲,0=不启用 */
/* ========== 内存分配 ========== */
#define configSUPPORT_STATIC_ALLOCATION 1 /* 1=支持静态创建对象 */
#define configSUPPORT_DYNAMIC_ALLOCATION 1 /* 1=支持动态创建对象 */
#define configTOTAL_HEAP_SIZE 100*1024
#define configAPPLICATION_ALLOCATED_HEAP 0 /* 1=应用自己分配堆数组,0=链接器分配 */
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 /* 1=任务栈从单独堆分配,0=从主堆分配 */
#define configENABLE_HEAP_PROTECTOR 0 /* 1=启用堆指针保护,0=不启用 */
/* ========== 中断嵌套行为 ========== */
#define configKERNEL_INTERRUPT_PRIORITY 0xF0
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0x40
#define configMAX_API_CALL_INTERRUPT_PRIORITY 0x40
/* ========== 钩子函数 ========== */
#define configUSE_IDLE_HOOK 0 /* 1=启用空闲钩子 */
#define configUSE_TICK_HOOK 0 /* 1=启用 tick 钩子 */
#define configUSE_MALLOC_FAILED_HOOK 0 /* 1=启用 malloc 失败钩子 */
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 /* 1=启用守护任务启动钩子 */
#define configUSE_SB_COMPLETED_CALLBACK 0 /* 1=启用流缓冲收发完成回调 */
#define configCHECK_FOR_STACK_OVERFLOW 0 /* 0=不检查栈溢出,1=快但弱,2=慢但强 */
/* ========== 运行时统计 ========== */
#define configGENERATE_RUN_TIME_STATS 0 /* 1=收集各任务运行时间 */
#define configUSE_TRACE_FACILITY 0 /* 1=启用 trace 调试功能 */
#define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* 1=启用 vTaskList 等格式化函数 */
/* ========== 协程 ========== */
#define configUSE_CO_ROUTINES 0 /* 1=启用协程 */
#define configMAX_CO_ROUTINE_PRIORITIES 1 /* 协程最大优先级数 */
/* ========== 调试断言 ========== */
#define configASSERT( x ) \
if( ( x ) == 0 ) \
{ \
taskDISABLE_INTERRUPTS(); \
for( ; ; ) \
; \
} \
/* ========== FreeRTOS MPU 相关(标准 Cortex-M port 不用) ========== */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 /* 1=允许应用定义特权函数 */
#define configTOTAL_MPU_REGIONS 8 /* MPU 区域数量,通常 8 或 16 */
#define configTEX_S_C_B_FLASH 0x07UL /* Flash 区域 TEX/S/C/B 位 */
#define configTEX_S_C_B_SRAM 0x07UL /* RAM 区域 TEX/S/C/B 位 */
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1 /* 1=只允许内核发起系统调用 */
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 0 /* 1=允许非特权任务进临界区 */
#define configUSE_MPU_WRAPPERS_V1 0 /* 1=用旧版 MPU wrapper,0=用 v2 */
#define configPROTECTED_KERNEL_OBJECT_POOL_SIZE 10 /* v2 wrapper 下内核对象池大小 */
#define configSYSTEM_CALL_STACK_SIZE 128 /* 系统调用栈大小(字) */
#define configENABLE_ACCESS_CONTROL_LIST 1 /* 1=启用访问控制列表 */
/* ========== ARMv8-M 安全侧 ========== */
#define secureconfigMAX_SECURE_CONTEXTS 5 /* 可调用安全侧的最大任务数 */
#define configKERNEL_PROVIDED_STATIC_MEMORY 1 /* 1=内核提供空闲/定时器任务内存 */
/* ========== ARMv8-M port ========== */
#define configENABLE_TRUSTZONE 0
#define configRUN_FREERTOS_SECURE_ONLY 0
#define configENABLE_MPU 0
#define configENABLE_FPU 1 /* 1=启用 FPU */
#define configENABLE_MVE 0
/* ========== ARMv7-M / ARMv8-M port ========== */
#define configCHECK_HANDLER_INSTALLATION 1 //开机时检查 SVC_Handler、PendSV_Handler 有没有正确安装到中断向量表
/* ========== 功能开关 ========== */
#define configUSE_TASK_NOTIFICATIONS 1 /* 1=启用任务通知 */
#define configUSE_MUTEXES 1 /* 1=启用互斥量 */
#define configUSE_RECURSIVE_MUTEXES 1 /* 1=启用递归互斥量 */
#define configUSE_COUNTING_SEMAPHORES 1 /* 1=启用计数信号量 */
#define configUSE_QUEUE_SETS 0 /* 1=启用队列集 */
#define configUSE_APPLICATION_TASK_TAG 0 /* 1=启用任务标签 */
#define configUSE_POSIX_ERRNO 0 /* 1=启用 POSIX errno */
/* ========== API 函数开关 ========== */
#define INCLUDE_vTaskPrioritySet 1 /* 启用 vTaskPrioritySet */
#define INCLUDE_uxTaskPriorityGet 1 /* 启用 uxTaskPriorityGet */
#define INCLUDE_vTaskDelete 1 /* 启用 vTaskDelete */
#define INCLUDE_vTaskSuspend 1 /* 启用 vTaskSuspend */
#define INCLUDE_xTaskDelayUntil 1 /* 启用 xTaskDelayUntil */
#define INCLUDE_vTaskDelay 1 /* 启用 vTaskDelay */
#define INCLUDE_xTaskGetSchedulerState 1 /* 启用 xTaskGetSchedulerState */
#define INCLUDE_xTaskGetCurrentTaskHandle 1 /* 启用 xTaskGetCurrentTaskHandle */
#define INCLUDE_uxTaskGetStackHighWaterMark 0 /* 启用 uxTaskGetStackHighWaterMark */
#define INCLUDE_xTaskGetIdleTaskHandle 0 /* 启用 xTaskGetIdleTaskHandle */
#define INCLUDE_eTaskGetState 0 /* 启用 eTaskGetState */
#define INCLUDE_xTimerPendFunctionCall 0 /* 启用 xTimerPendFunctionCall */
#define INCLUDE_xTaskAbortDelay 0 /* 启用 xTaskAbortDelay */
#define INCLUDE_xTaskGetHandle 0 /* 启用 xTaskGetHandle */
#define INCLUDE_xTaskResumeFromISR 1 /* 启用 xTaskResumeFromISR */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif /* FREERTOS_CONFIG_H */
应用层编写测试
#include "main.h"
#define INIT_TASK_PRIO ( tskIDLE_PRIORITY + 5 )
#define Led_Task_PRIO ( tskIDLE_PRIORITY + 1 )
#define Regular_Task_PRIO ( tskIDLE_PRIORITY + 1 )
TaskHandle_t InitTask_Handler = NULL;
TaskHandle_t LedTask_Handle = NULL;
TaskHandle_t RegularTask_Handle = NULL;
void LedTask (void *pvParameters);
void RegularTask (void *pvParameters);
void InitTask (void *pvParameters)
{
BaseType_t err;
SEGGER_RTT_Init();
taskENTER_CRITICAL();
err = xTaskCreate(LedTask, "_LED" , configMINIMAL_STACK_SIZE , NULL, Led_Task_PRIO ,(TaskHandle_t *)&LedTask_Handle);
err = xTaskCreate(RegularTask, "_REGULAR" , configMINIMAL_STACK_SIZE , NULL, Regular_Task_PRIO ,(TaskHandle_t *)&RegularTask_Handle);
if (err == pdPASS){}
vTaskDelete(InitTask_Handler);
taskEXIT_CRITICAL();
}
void Led_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOD);
gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_14);
gpio_bit_set(GPIOD, GPIO_PIN_14);
}
int main(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
__set_PRIMASK(0); //开启中断
xTaskCreate(InitTask, "_INIT", configMINIMAL_STACK_SIZE, NULL, INIT_TASK_PRIO, (TaskHandle_t* )&InitTask_Handler);
vTaskStartScheduler();
while(1)
{
}
}
void LedTask(void *pvParameters)
{
Led_Init();
while(1)
{
gpio_bit_set(GPIOD, GPIO_PIN_14);
vTaskDelay(125);
gpio_bit_reset(GPIOD, GPIO_PIN_14);
vTaskDelay(125);
SEGGER_RTT_printf(0,"OK\n");
}
}
void RegularTask(void *pvParameters)
{
while(1)
{
SEGGER_RTT_printf(0,"Ready\n");
vTaskDelay(1000);
}
}
记得添加头文件
#include "FreeRTOS.h"
#include "Task.h"
#include "queue.h"
#include "semphr.h"
#include "Timers.h"
实验:正常

结语
保持好奇,持续学习,一起努力。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐




所有评论(0)