记录一下我是如何将 FreeRTOS 移植到SC32芯片上的。

获取并整理源码

啥也别说,第一步先获取 FreeRTOS 的源码。
下载并解压,只留下以下内容,其余删除:

根目录/
├── examples/                   # 移植实例
│   └── template_configuration/ 
│       └── FreeRTOSConfig.h    # FreeRTOS 配置文件
├── include/                    # FreeRTOS 头文件
├── portable/                   # 用于移植的代码
│   ├── RVDS/                   # 芯片架构
│   │   └── ARM_CM0/            # 基于 ARM-Cortex-M0 的系列芯片(需正确配对)
│   ├── MemMang/                # 内存管理
│   │   └── heap_4.c            # heap_4 涵盖大多数使用场景
│   └── Keil/                   # Keil 相关文件(可删)
├── croutine.c                  # 协作式多任务处理
├── event_groups.c              # 事件组
├── list.c                      # 列表
├── queue.c                     # 队列
├── stream_buffer.c             # 流缓冲区
├── tasks.c                     # 任务管理
└── timers.c                    # 定时器

接下来把上述文件导入到 Keil 工程中,包括源文件的导入和头文件路径的添加。

替换中断函数

打开 startup_xxx.s 文件,在向量中断表中找到这三个中断函数:

    DCD     SVC_Handler         ; 用户模式请求内核服务
    DCD     PendSV_Handler      ; 延迟处理上下文切换
    DCD     SysTick_IRQHandler  ; 提供周期性时基中断

打开 FreeRTOSport.c 文件,分别找到与上面一一对应的中断处理函数:

void vPortSVCHandler(void) {
    ...
}

void xPortPendSVHandler(void) {
    ...
}

void xPortSysTickHandler(void) {
    ...
}

这三个函数是 FreeRTOS 官方给 Cortex-M0 系列芯片写好的移植代码用于替换启动文件 startup_xxx.s 中的三个中断函数。 那么我用最简单的宏定义来实现替换操作,在 FreeRTOSConfig.h 添加如下代码:

#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_IRQHandler

然后需要把项目中原先 SVC_HandlerPendSV_HandlerSysTick_IRQHandler 这三个函数的定义删除掉(注释掉),避免出现多重定义的编译错误。

调整配置文件

打开 FreeRTOSConfig.h 文件,这里对里面的主要配置进行解释,若熟悉可跳过:

/*
 * FreeRTOS 内核 <开发分支>
 * 版权所有 (C) 2021 Amazon.com, Inc. 或其关联公司。保留所有权利。
 *
 * 许可证:MIT
 *
 * 特此免费授予任何获得本软件及相关文档文件("软件")的人士,不受限制地处理
 * 软件的权限,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售
 * 软件副本的权利,并允许向其提供软件的人士这样做,需满足以下条件:
 *
 * 上述版权声明和本许可声明必须包含在所有软件副本或重要部分中。
 *
 * 软件按"原样"提供,不提供任何形式的明示或暗示担保,包括但不限于适销性、
 * 特定用途适用性和非侵权的担保。在任何情况下,作者或版权持有者对任何索赔、
 * 损害或其他责任均不负责任,无论该责任是因合同、侵权行为还是其他方式引起的,
 * 与软件或使用或其他交易有关。
 *
 * https://www.FreeRTOS.org 
 * https://github.com/FreeRTOS 
 *
 */
/*******************************************************************************
 * 本文件提供了一个示例 FreeRTOSConfig.h 头文件,包含每个配置项的简要说明。
 * 完整文档请参考在线资料和官方手册:
 * https://www.freertos.org/a00110.html 
 *
 * 方括号('[' 和 ']')内的常量值必须在文件构建前完成填写。
 *
 * 请优先使用与当前 RTOS 端口配套的 FreeRTOSConfig.h 文件,而非本通用文件。
 ******************************************************************************/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/******************************************************************************/
/* 硬件描述相关定义 **********************************/
/******************************************************************************/
/* configCPU_CLOCK_HZ 通常需设置为驱动内核周期性节拍中断的外设时钟频率(单位:Hz)。
 * 默认值 20MHz 适用于 QEMU 模拟器演示。实际应用需根据硬件修改。
 * 此值通常(但并非总是)等于系统主时钟频率。 */
#define configCPU_CLOCK_HZ    ( ( unsigned long ) 64000000 )

/* configSYSTICK_CLOCK_HZ 仅用于 ARM Cortex-M 系列端口。
 *
 * 默认情况下,ARM Cortex-M 端口通过 Cortex-M 的 SysTick 定时器生成 RTOS 节拍中断。
 * 大多数 Cortex-M 微控制器以与 MCU 核心相同的频率运行 SysTick 定时器。
 * 此时无需定义此参数,保持默认未定义状态。
 * 如果 SysTick 定时器时钟频率不同于 MCU 核心频率:
 * - 将 configCPU_CLOCK_HZ 设为 MCU 时钟频率
 * - 将 configSYSTICK_CLOCK_HZ 设为 SysTick 时钟频率
 * 默认未定义(注释状态)。如需此功能,请取消注释并设置合适值。 */
#define configSYSTICK_CLOCK_HZ    8000000
/******************************************************************************/
/* 调度行为相关定义 **********************************/
/******************************************************************************/
/* configTICK_RATE_HZ 设置节拍中断频率(单位:Hz),通常由 configCPU_CLOCK_HZ 计算得出。 */
#define configTICK_RATE_HZ                         8000

/* configUSE_PREEMPTION 设置抢占式调度(1)或协作式调度(0)。
 * 参考文档:https://www.freertos.org/single-core-amp-smp-rtos-scheduling.html  */
#define configUSE_PREEMPTION                       0

/* configUSE_TIME_SLICING 设置为 1 时,相同优先级就绪任务在每次节拍中断后切换;
 * 设置为 0 时禁止因节拍中断触发的任务切换。
 * 参考文档:https://freertos.org/single-core-amp-smp-rtos-scheduling.html  */
#define configUSE_TIME_SLICING                     1

/* configUSE_PORT_OPTIMISED_TASK_SELECTION 设置为 1 时,使用针对目标硬件指令集优化的
 * 任务选择算法(通常基于汇编指令);
 * 设置为 0 时使用通用 C 算法。
 * 并非所有 FreeRTOS 端口支持此选项。未定义时默认为 0。 */
#define configUSE_PORT_OPTIMISED_TASK_SELECTION    0

/* configUSE_TICKLESS_IDLE 设置为 1 启用低功耗无节拍模式;设置为 0 保持持续节拍中断。
 * 并非所有 FreeRTOS 端口支持无节拍模式。
 * 参考文档:https://www.freertos.org/low-power-tickless-rtos.html 
 * 未定义时默认为 0。 */
#define configUSE_TICKLESS_IDLE                    0

/* configMAX_PRIORITIES 设置可用任务优先级数量。
 * 任务优先级范围为 0 到 (configMAX_PRIORITIES - 1),0 为最低优先级。 */
#define configMAX_PRIORITIES                       5

/* configMINIMAL_STACK_SIZE 设置空闲任务的最小栈大小(以字为单位,非字节!)。
 * 内核不会用此常量作其他用途。演示程序使用此值提高跨架构的移植性。 */
#define configMINIMAL_STACK_SIZE                   64

/* configMAX_TASK_NAME_LEN 设置任务可读名称的最大长度(含空终止符)。 */
#define configMAX_TASK_NAME_LEN                    16

/* 时间以"节拍"为单位度量 - 即节拍中断自内核启动以来的执行次数。
 * 节拍计数存储在 TickType_t 类型变量中。
 *
 * configTICK_TYPE_WIDTH_IN_BITS 控制 TickType_t 的类型(即位宽):
 *
 * - TICK_TYPE_WIDTH_16_BITS → 无符号 16 位类型
 * - TICK_TYPE_WIDTH_32_BITS → 无符号 32 位类型
 * - TICK_TYPE_WIDTH_64_BITS → 无符号 64 位类型 */
#define configTICK_TYPE_WIDTH_IN_BITS              TICK_TYPE_WIDTH_16_BITS

/* configIDLE_SHOULD_YIELD 设置为 1 时,若存在就绪状态的空闲优先级任务(优先级 0),
 * 空闲任务会主动让出 CPU;设置为 0 时,空闲任务会用尽其时间片。
 * 未定义时默认为 1。 */
#define configIDLE_SHOULD_YIELD                    1

/* 每个任务拥有一个任务通知数组。
 * configTASK_NOTIFICATION_ARRAY_ENTRIES 设置数组索引数量。
 * 参考文档:https://www.freertos.org/RTOS-task-notifications.html 
 * 未定义时默认为 1。 */
#define configTASK_NOTIFICATION_ARRAY_ENTRIES      1

/* configQUEUE_REGISTRY_SIZE 设置队列注册表可引用的最大队列/信号量数量。
 * 仅调试时使用(内核感知调试器相关)。
 * 未定义时默认为 0。 */
#define configQUEUE_REGISTRY_SIZE                  8

/* configENABLE_BACKWARD_COMPATIBILITY 设置为 1 时,启用旧版 FreeRTOS 函数名和数据类型的兼容映射。
 * 未定义时默认为 1。 */
#define configENABLE_BACKWARD_COMPATIBILITY        0

/* 每个任务拥有自己的线程本地存储指针数组。
 * configNUM_THREAD_LOCAL_STORAGE_POINTERS 设置数组索引数量。
 * 参考文档:https://www.freertos.org/thread-local-storage-pointers.html 
 * 未定义时默认为 0。 */
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS    0

/* configUSE_MINI_LIST_ITEM 设置为 0 时,MiniListItem_t 和 ListItem_t 相同;
 * 设置为 1 时,MiniListItem_t 比 ListItem_t 少 3 个字段,节省 RAM 但可能违反严格别名规则
 * (影响编译器优化)。
 * 未定义时默认为 1。 */
#define configUSE_MINI_LIST_ITEM                   1

/* configSTACK_DEPTH_TYPE 设置 xTaskCreate() 中栈大小参数的类型。
 * 此类型也用于返回栈使用信息的 API。
 * 未定义时默认为 size_t。 */
#define configSTACK_DEPTH_TYPE                     size_t

/* configMESSAGE_BUFFER_LENGTH_TYPE 设置消息缓冲区消息长度的类型。
 * 未定义时默认为 size_t,若消息长度始终小于 uint8_t 范围,可改用 uint8_t 节省内存。 */
#define configMESSAGE_BUFFER_LENGTH_TYPE           size_t

/* configHEAP_CLEAR_MEMORY_ON_FREE 设置为 1 时,调用 vPortFree() 释放内存时会清零对应内存块。
 * 未定义时默认为 0。 */
#define configHEAP_CLEAR_MEMORY_ON_FREE            1

/* vTaskList 和 vTaskGetRunTimeStats API 使用固定长度的缓冲区。
 * configSTATS_BUFFER_MAX_LENGTH 设置缓冲区最大长度,默认 0xFFFF。
 * 新应用推荐使用显式指定缓冲区长度的 vTaskListTasks 和 vTaskGetRunTimeStatistics API。
 * 未定义时默认为 0xFFFF。 */
#define configSTATS_BUFFER_MAX_LENGTH              0xFFFF

/* configUSE_NEWLIB_REENTRANT 设置为 1 时,为每个任务分配 newlib 的 reent 结构;
 * 设置为 0 时禁用 newlib 支持。
 * 未定义时默认为 0。
 *
 * 注意:newlib 支持是应用户需求添加,FreeRTOS 维护者未测试其功能。
 * 用户需熟悉 newlib 并提供必要的存根实现。注意 newlib 当前设计使用全局 malloc(),
 * 需提供锁机制。 */
#define configUSE_NEWLIB_REENTRANT                 0
/******************************************************************************/
/* 软件定时器相关定义 ****************************************/
/******************************************************************************/
/* configUSE_TIMERS 设置为 1 时包含软件定时器功能;
 * 设置为 0 时排除软件定时器功能。
 * 若启用,需包含 FreeRTOS/source/timers.c 文件。
 * 默认未定义(即 0)。
 * 参考文档:https://www.freertos.org/RTOS-software-timer.html  */
#define configUSE_TIMERS                1

/* configTIMER_TASK_PRIORITY 设置定时器任务的优先级(仅 configUSE_TIMERS=1 时有效)。
 * 定时器任务是标准 FreeRTOS 任务。
 * 参考文档:https://www.freertos.org/RTOS-software-timer-service-daemon-task.html  */
#define configTIMER_TASK_PRIORITY       ( configMAX_PRIORITIES - 1 )

/* configTIMER_TASK_STACK_DEPTH 设置定时器任务的栈大小(以字为单位,非字节!)。
 * 定时器任务是标准 FreeRTOS 任务。
 * 参考文档:https://www.freertos.org/RTOS-software-timer-service-daemon-task.html  */
#define configTIMER_TASK_STACK_DEPTH    configMINIMAL_STACK_SIZE

/* configTIMER_QUEUE_LENGTH 设置发送命令到定时器任务的队列长度(即队列可容纳的最大离散项数)。
 * 参考文档:https://www.freertos.org/RTOS-software-timer-service-daemon-task.html  */
#define configTIMER_QUEUE_LENGTH        10
/******************************************************************************/
/* 事件组相关定义 *******************************************/
/******************************************************************************/
/* configUSE_EVENT_GROUPS 设置为 1 时包含事件组功能;
 * 设置为 0 时排除事件组功能。
 * 若启用,需包含 FreeRTOS/source/event_groups.c 文件。
 * 默认未定义(即 1)。 */
#define configUSE_EVENT_GROUPS    1
/******************************************************************************/
/* 流缓冲区相关定义 *****************************************/
/******************************************************************************/
/* configUSE_STREAM_BUFFERS 设置为 1 时包含流缓冲区功能;
 * 设置为 0 时排除流缓冲区功能。
 * 若启用,需包含 FreeRTOS/source/stream_buffer.c 文件。
 * 默认未定义(即 1)。 */
#define configUSE_STREAM_BUFFERS    1
/******************************************************************************/
/* 内存分配相关定义 *************************************/
/******************************************************************************/
/* configSUPPORT_STATIC_ALLOCATION 设置为 1 时,启用基于静态内存分配的 API(如任务、队列创建);
 * 设置为 0 时禁用静态分配功能。
 * 默认未定义(即 0)。
 * 参考文档:https://www.freertos.org/Static_Vs_Dynamic_Memory_Allocation.html  */
#define configSUPPORT_STATIC_ALLOCATION              1

/* configSUPPORT_DYNAMIC_ALLOCATION 设置为 1 时,启用基于动态内存分配的 API;
 * 设置为 0 时禁用动态分配功能。
 * 默认未定义(即 1)。
 * 参考文档:https://www.freertos.org/Static_Vs_Dynamic_Memory_Allocation.html  */
#define configSUPPORT_DYNAMIC_ALLOCATION             1

/* configTOTAL_HEAP_SIZE 设置 heap_1.c/heap_2.c/heap_4.c 的堆内存总大小(单位:字节)。
 * 默认值 4096 字节需根据应用调整。
 * 注意堆内存位于 .bss 段。
 * 参考文档:https://www.freertos.org/a00111.html  */
#define configTOTAL_HEAP_SIZE                        (8*1024)

/* configAPPLICATION_ALLOCATED_HEAP 设置为 1 时,由应用分配 FreeRTOS 堆内存数组;
 * 设置为 0 时由链接器分配堆内存。
 * 默认未定义(即 0)。 */
#define configAPPLICATION_ALLOCATED_HEAP             0

/* configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 设置为 1 时,任务栈从独立于 FreeRTOS 堆的区域分配;
 * 设置为 0 时任务栈来自标准 FreeRTOS 堆。
 * 启用此功能需提供 pvPortMallocStack() 和 vPortFreeStack() 实现。
 * 默认未定义(即 0)。 */
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP    0

/* configENABLE_HEAP_PROTECTOR 设置为 1 时,在 heap_4.c/heap_5.c 中启用边界检查和指针混淆保护,
 * 以防止堆指针损坏。
 * 默认未定义(即 0)。 */
#define configENABLE_HEAP_PROTECTOR                  0
/******************************************************************************/
/* 中断嵌套行为配置 ***************************************/
/******************************************************************************/
/* configKERNEL_INTERRUPT_PRIORITY 设置节拍中断和上下文切换中断的优先级。
 * 并非所有 FreeRTOS 端口支持此功能。
 * 参考 ARM Cortex-M 文档:https://www.freertos.org/RTOS-Cortex-M3-M4.html  */
#define configKERNEL_INTERRUPT_PRIORITY          0

/* configMAX_SYSCALL_INTERRUPT_PRIORITY 设置高于此优先级的中断禁止调用 FreeRTOS API。
 * 高于此优先级的中断不会被内核禁用,因此不会因 RTOS 活动而延迟。
 * 默认值为最高优先级(0)。
 * 并非所有 FreeRTOS 端口支持此功能。
 * 参考 ARM Cortex-M 文档:https://www.freertos.org/RTOS-Cortex-M3-M4.html  */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     0

/* configMAX_API_CALL_INTERRUPT_PRIORITY 是 configMAX_SYSCALL_INTERRUPT_PRIORITY 的别名,
 * 具体名称取决于 FreeRTOS 端口。 */
#define configMAX_API_CALL_INTERRUPT_PRIORITY    0
/******************************************************************************/
/* 钩子函数相关定义 ****************************/
/******************************************************************************/
/* 设置以下 configUSE_* 常量为 1 以包含对应钩子功能;
 * 设置为 0 时排除钩子功能。
 * 应用需提供钩子函数实现。
 * 参考文档:https://www.freertos.org/a00016.html  */
#define configUSE_IDLE_HOOK                   0
#define configUSE_TICK_HOOK                   0
#define configUSE_MALLOC_FAILED_HOOK          0
#define configUSE_DAEMON_TASK_STARTUP_HOOK    0

/* configUSE_SB_COMPLETED_CALLBACK 设置为 1 时,为每个流缓冲区/消息缓冲区实例启用发送/接收完成回调。
 * 启用后可使用 xStreamBufferCreateWithCallback() 等 API 创建带回调的缓冲区。
 * 默认未定义(即 0)。 */
#define configUSE_SB_COMPLETED_CALLBACK       0

/* configCHECK_FOR_STACK_OVERFLOW 设置为 1 或 2 时,在任务上下文切换时检测栈溢出;
 * 设置为 0 时禁用检测。
 * - 1:快速检测栈指针是否越界(有效但不够全面)
 * - 2:检测栈填充标记是否被覆盖(更慢但更可靠)
 * 启用时需提供栈溢出回调函数。
 * 默认未定义(即 0)。
 * 参考文档:https://www.freertos.org/Stacks-and-stack-overflow-checking.html  */
#define configCHECK_FOR_STACK_OVERFLOW        0
/******************************************************************************/
/* 运行时和任务统计相关定义 *********************/
/******************************************************************************/
/* configGENERATE_RUN_TIME_STATS 设置为 1 时收集任务运行时间数据;
 * 设置为 0 时禁用数据收集。
 * 启用时需提供时钟源。
 * 默认未定义(即 0)。
 * 参考文档:https://www.freertos.org/rtos-run-time-stats.html  */
#define configGENERATE_RUN_TIME_STATS           0

/* configUSE_TRACE_FACILITY 设置为 1 时包含跟踪和可视化工具所需的附加任务结构成员;
 * 设置为 0 时排除这些信息。
 * 默认未定义(即 0)。 */
#define configUSE_TRACE_FACILITY                0

/* configUSE_STATS_FORMATTING_FUNCTIONS 设置为 1 时包含 vTaskList() 和
 * vTaskGetRunTimeStats() 函数;
 * 设置为 0 时排除这些函数。
 * 这两个函数依赖字符串格式化函数,因此单独配置。
 * 默认未定义(即 0)。 */
#define configUSE_STATS_FORMATTING_FUNCTIONS    0
/******************************************************************************/
/* 协程相关定义 ********************************************/
/******************************************************************************/
/* configUSE_CO_ROUTINES 设置为 1 时包含协程功能;
 * 设置为 0 时排除协程功能。
 * 启用时需包含 croutine.c 文件。
 * 默认未定义(即 0)。 */
#define configUSE_CO_ROUTINES              0

/* configMAX_CO_ROUTINE_PRIORITIES 设置协程可用优先级数量。
 * 多个协程可共享同一优先级。
 * 默认未定义(即 0)。 */
#define configMAX_CO_ROUTINE_PRIORITIES    1
/******************************************************************************/
/* 调试辅助 ******************************************************/
/******************************************************************************/
/* configASSERT() 行为与标准 C 的 assert() 相同。
 * 可定义为执行动作(如停止执行)或完全移除(注释掉)。
 * 示例:调用带有文件名和行号的函数(如 vAssertCalled(__FILE__, __LINE__)),
 * 或禁用中断并进入死循环以供调试器查看。 */
#define configASSERT( x )         \
    if( ( x ) == 0 )              \
    {                             \
        taskDISABLE_INTERRUPTS(); \
        for( ; ; )                \
        ;                         \
    }
/******************************************************************************/
/* FreeRTOS MPU 特定定义 *****************************************/
/******************************************************************************/
/* configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 设置为 1 时,
 * 应用可提供在特权模式下执行的函数。
 * 参考文档:
 * https://www.freertos.org/a00110.html #configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS
 * 默认未定义(即 0)。仅用于 FreeRTOS Cortex-M MPU 端口,非标准 ARMv7-M Cortex-M 端口。 */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS    0

/* configTOTAL_MPU_REGIONS 设置目标硬件的 MPU 区域数量(通常为 8 或 16)。
 * 仅用于 FreeRTOS Cortex-M MPU 端口,非标准 ARMv7-M Cortex-M 端口。
 * 默认未定义(即 8)。 */
#define configTOTAL_MPU_REGIONS                                   8

/* configTEX_S_C_B_FLASH 允许覆盖 Flash 区域的 TEX/S/C/B 位默认值。
 * 默认值 0x07UL(TEX=000, S=1, C=1, B=1)。
 * 仅用于 FreeRTOS Cortex-M MPU 端口,非标准 ARMv7-M Cortex-M 端口。 */
#define configTEX_S_C_B_FLASH                                     0x07UL

/* configTEX_S_C_B_SRAM 允许覆盖 RAM 区域的 TEX/S/C/B 位默认值。
 * 默认值 0x07UL(TEX=000, S=1, C=1, B=1)。
 * 仅用于 FreeRTOS Cortex-M MPU 端口,非标准 ARMv7-M Cortex-M 端口。 */
#define configTEX_S_C_B_SRAM                                      0x07UL

/* configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 设置为 0 时禁止内核外代码提升特权;
 * 设置为 1 时允许应用任务提升特权。
 * 默认未定义(即 1)。仅用于 FreeRTOS Cortex-M MPU 端口。 */
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY               1

/* configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 设置为 1 时允许非特权任务进入临界区(屏蔽中断);
 * 设置为 0 时禁止此行为。
 * 默认未定义(即 1)。仅用于 FreeRTOS Cortex-M MPU 端口。 */
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS                0

/* FreeRTOS 10.6.0 引入新的 v2 MPU 包装器(mpu_wrappers_v2.c)。
 * 设置 configUSE_MPU_WRAPPERS_V1 为 0 使用新包装器;
 * 设置为 1 使用旧 v1 包装器(mpu_wrappers.c)。
 * 默认未定义(即 0)。 */
#define configUSE_MPU_WRAPPERS_V1                                 0

/* 使用 v2 MPU 包装器时,configPROTECTED_KERNEL_OBJECT_POOL_SIZE 设置应用中内核对象总数
 * (任务、队列等)。
 * 应用任意时刻不能超过此数量的内核对象。 */
#define configPROTECTED_KERNEL_OBJECT_POOL_SIZE                   10

/* 使用 v2 MPU 包装器时,configSYSTEM_CALL_STACK_SIZE 设置系统调用栈大小(以字为单位)。
 * 每个任务静态分配此大小的内存作为系统调用栈。
 * 示例:若设置为 128 且有 10 个任务,则总占用 128*10=1280 字。 */
#define configSYSTEM_CALL_STACK_SIZE                              16

/* 使用 v2 MPU 包装器时,configENABLE_ACCESS_CONTROL_LIST 设置为 1 启用访问控制列表(ACL)功能。
 * 启用后,非特权任务默认无法访问除自身外的其他内核对象。
 * 应用需显式授予访问权限。
 * 默认未定义(即 0)。 */
#define configENABLE_ACCESS_CONTROL_LIST                          1
/******************************************************************************/
/* 对称多处理 (SMP) 特定配置 ***************/
/******************************************************************************/
/* configNUMBER_OF_CORES 设置可用处理器核心数量。
 * 默认未定义(即 1)。 */
/*
 #define configNUMBER_OF_CORES                     [Num of available cores]
 */

/* 使用 SMP(configNUMBER_OF_CORES > 1)时,
 * configRUN_MULTIPLE_PRIORITIES 设置为 0 时,仅当优先级不同时允许多任务并行
 * (保持高优先级任务优先原则);
 * 设置为 1 时,不同优先级任务可在不同核心并行执行。 */
#define configRUN_MULTIPLE_PRIORITIES             0

/* 使用 SMP 时,configUSE_CORE_AFFINITY 设置为 1 启用核心亲和性功能。
 * 启用后可通过 vTaskCoreAffinitySet/Get API 设置/获取任务可运行的核心。
 * 设置为 0 时调度器可自由在任意核心运行任务。 */
#define configUSE_CORE_AFFINITY                   0

/* 启用核心亲和性功能时,configTASK_DEFAULT_CORE_AFFINITY 设置未指定亲和掩码的任务默认核心亲和性。
 * 设置为 1 使任务运行在核心 0,设置为 (1 << portGET_CORE_ID()) 使任务运行在当前核心。
 * 默认未定义(tskNO_AFFINITY)。 */
#define configTASK_DEFAULT_CORE_AFFINITY          tskNO_AFFINITY

/* 使用 SMP 时,configUSE_TASK_PREEMPTION_DISABLE 设置为 1 时,
 * 可通过 vTaskPreemptionDisable/Enable API 设置任务为抢占/协作模式。 */
#define configUSE_TASK_PREEMPTION_DISABLE         0

/* 使用 SMP 时,configUSE_PASSIVE_IDLE_HOOK 设置为 1 允许在被动空闲钩子中添加后台功能,
 * 无需额外任务开销。
 * 默认未定义(即 0)。 */
#define configUSE_PASSIVE_IDLE_HOOK               0

/* 使用 SMP 时,configTIMER_SERVICE_TASK_CORE_AFFINITY 设置定时器服务任务的核心亲和性。
 * 默认未定义(tskNO_AFFINITY)。 */
#define configTIMER_SERVICE_TASK_CORE_AFFINITY    tskNO_AFFINITY
/******************************************************************************/
/* ARMv8-M 安全侧端口相关定义 ******************************/
/******************************************************************************/
/* secureconfigMAX_SECURE_CONTEXTS 定义可调用安全侧(Secure Side)的 ARMv8-M 芯片的任务最大数量。
 * 其他端口不使用此参数。 */
#define secureconfigMAX_SECURE_CONTEXTS        5

/* configKERNEL_PROVIDED_STATIC_MEMORY 设置为 1 时,
 * 内核提供 vApplicationGetIdleTaskMemory() 和 vApplicationGetTimerTaskMemory() 的实现。
 * 应用可通过设置为 0 或未定义来提供自己的实现。 */
#define configKERNEL_PROVIDED_STATIC_MEMORY    1
/******************************************************************************/
/* ARMv8-M 端口特定配置 ***************************/
/******************************************************************************/
/* configENABLE_TRUSTZONE 设置为 1 时,在非安全侧启用 TrustZone 支持
 * (允许非安全任务调用安全侧函数)。 */
#define configENABLE_TRUSTZONE            1

/* 若应用不使用 TrustZone 但硬件无法禁用,可通过设置 configENABLE_TRUSTZONE=0 且
 * configRUN_FREERTOS_SECURE_ONLY=1,使整个应用(包括调度器)运行在安全侧。 */
#define configRUN_FREERTOS_SECURE_ONLY    1

/* configENABLE_MPU 设置为 1 启用内存保护单元(MPU);
 * 设置为 0 禁用 MPU。 */
#define configENABLE_MPU                  1

/* configENABLE_FPU 设置为 1 启用浮点单元(FPU);
 * 设置为 0 禁用 FPU。 */
#define configENABLE_FPU                  1

/* configENABLE_MVE 设置为 1 启用 M-Profile 向量扩展(MVE)支持(仅 Cortex-M55/M85);
 * 设置为 0 禁用 MVE。
 * Cortex-M23/M33/M35P 端口必须未定义或设为 0。 */
#define configENABLE_MVE                  1
/******************************************************************************/
/* ARMv7-M 和 ARMv8-M 端口特定配置 ***************/
/******************************************************************************/
/* configCHECK_HANDLER_INSTALLATION 设置为 1 时,启用额外断言验证应用正确安装
 * FreeRTOS 中断处理程序。
 * 应用可通过以下方式安装中断处理程序:
 * 1. 直接路由:安装 vPortSVCHandler 和 xPortPendSVHandler 作为 SVC 和 PendSV 中断处理函数。
 * 2. 间接路由:安装独立的 SVC/PendSV 处理函数,并在其中调用 vPortSVCHandler/xPortPendSVHandler。
 * 使用间接路由的应用必须设置 configCHECK_HANDLER_INSTALLATION=0。
 * 默认未定义(即 1)。 */
#define configCHECK_HANDLER_INSTALLATION    1
/******************************************************************************/
/* 包含或排除功能的定义 *************************/
/******************************************************************************/
/* 设置以下 configUSE_* 常量为 1 以包含对应功能;
 * 设置为 0 时排除功能。 */
#define configUSE_TASK_NOTIFICATIONS           1
#define configUSE_MUTEXES                      1
#define configUSE_RECURSIVE_MUTEXES            1
#define configUSE_COUNTING_SEMAPHORES          1
#define configUSE_QUEUE_SETS                   0
#define configUSE_APPLICATION_TASK_TAG         0

/* configUSE_POSIX_ERRNO 设置为 1 时启用任务全局变量 FreeRTOS_errno,记录最近错误代码。 */
#define configUSE_POSIX_ERRNO                  0

/* 设置以下 INCLUDE_* 常量为 1 以包含对应 API;
 * 设置为 0 时排除 API。
 * 大多数链接器会自动移除未使用的函数,即使常量为 1。 */
#define INCLUDE_vTaskPrioritySet               1
#define INCLUDE_uxTaskPriorityGet              1
#define INCLUDE_vTaskDelete                    1
#define INCLUDE_vTaskSuspend                   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_xTimerPendFunctionCall         0
#define INCLUDE_xTaskAbortDelay                0
#define INCLUDE_xTaskGetHandle                 0
#define INCLUDE_xTaskResumeFromISR             1

/* 中断服务函数别名定义(上述讲到的用于中断函数替换的宏定义) */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_IRQHandler

#endif /* FREERTOS_CONFIG_H */

示例代码

/* 导入头文件 */
#include "FreeRTOS.h"
#include "task.h"
...

/* 定义任务函数 */
void vTask1(void *pvParameters)
{
    for(;;)
    {
        GPIO_TogglePins(GPIOB, GPIO_Pin_15);
        vTaskDelay(500);
    }
}

int main(void) {
    /* 初始化 */
    IcResourceInit();

    /* 创建任务 */
    xTaskCreate(vTask1, "vTask1", 16, NULL, 1, NULL);

    /* 启动任务 */
    vTaskStartScheduler();

    // 正常情况不会运行到这里
    while(1){
        ...
    }; 
}