FreeRTOS移植针对f103c8t6

背景

将 FreeRTOS v9.0.0 移植到你现有的 STM32F103C8T6 Keil/EIDE 工程中。你的工程使用 AC5 (ARMCC) 编译器,Cortex-M3 内核。

移植 FreeRTOS 主要分为 4 个步骤

  1. 拷贝源文件到工程目录
  2. 创建 FreeRTOSConfig.h 配置文件
  3. 修改中断处理函数(解决冲突)
  4. 在 EIDE/Keil 中添加文件和头文件路径

步骤一:拷贝 FreeRTOS 源文件

在工程根目录下创建 FreeRTOS 文件夹,把以下文件拷贝进去:

1.1 内核源文件(必须)

FreeRTOSv9.0.0/FreeRTOS/Source/ 拷贝以下 5 个 .c 文件FreeRTOS/src/

文件名作用
tasks.c任务管理(核心)
queue.c队列(消息队列/信号量基础)
list.c链表(内核数据结构)
timers.c软件定时器
event_groups.c事件标志组

1.2 头文件(必须)

FreeRTOSv9.0.0/FreeRTOS/Source/include/ 拷贝 所有头文件FreeRTOS/include/

1.3 移植层文件(必须)

你用的是 ARMCC (AC5) 编译器 + Cortex-M3,所以需要从 FreeRTOSv9.0.0/FreeRTOS/Source/portable/RVDS/ARM_CM3/ 拷贝以下 2 个文件到 FreeRTOS/portable/RVDS/ARM_CM3/

文件名作用
port.cCortex-M3 的上下文切换、SysTick 配置等
portmacro.h移植层的宏定义

[!NOTE]
RVDS 和 Keil (ARMCC/AC5) 使用相同的 port 文件,所以用 RVDS/ARM_CM3 目录下的文件即可。

1.4 内存管理文件(必须,选一个)

FreeRTOSv9.0.0/FreeRTOS/Source/portable/MemMang/ 拷贝 一个 heap 文件到 FreeRTOS/portable/MemMang/

文件名特点推荐场景
heap_1.c只能分配不能释放任务数固定,永不删除
heap_2.c可分配可释放,不合并碎片简单场景
heap_3.c直接封装 malloc/free需要标准库支持
heap_4.c可分配可释放,自动合并碎片⭐ 推荐,最常用
heap_5.c支持多个不连续内存区域有外部 SRAM 时使用

[!IMPORTANT]
推荐使用 heap_4.c,它是最通用的选择,支持动态创建和删除任务。

最终目录结构

rtos学习/
├── CORE/
├── FWLIB/
├── HARDWARE/
├── USER/
│   ├── main.c
│   ├── FreeRTOSConfig.h     ← 新增
│   ├── stm32f10x_it.c       ← 需修改
│   └── ...
└── FreeRTOS/                 ← 新增整个目录
    ├── src/
    │   ├── tasks.c
    │   ├── queue.c
    │   ├── list.c
    │   ├── timers.c
    │   └── event_groups.c
    ├── include/
    │   ├── FreeRTOS.h
    │   ├── task.h
    │   ├── queue.h
    │   └── ... (所有头文件)
    └── portable/
        ├── RVDS/ARM_CM3/
        │   ├── port.c
        │   └── portmacro.h
        └── MemMang/
            └── heap_4.c

步骤二:创建 FreeRTOSConfig.h

USER/ 目录下创建 FreeRTOSConfig.h,这是 FreeRTOS 的核心配置文件。

[!IMPORTANT]
关键配置说明(针对 STM32F103C8T6 的 20KB RAM):

  • configTOTAL_HEAP_SIZE 设为 10 * 1024(10KB),因为 C8T6 只有 20KB RAM,留一半给栈和全局变量
  • configCPU_CLOCK_HZ 设为 72000000(72MHz),这是 F103 的标准主频
  • configMINIMAL_STACK_SIZE 设为 128 字(512 字节),每个任务最少的栈空间
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * FreeRTOS 配置文件 - STM32F103C8T6 (72MHz, 20KB RAM, 64KB Flash)
 *----------------------------------------------------------*/

/* 基本配置 */
#define configUSE_PREEMPTION            1       /* 1: 抢占式调度, 0: 合作式调度 */
#define configUSE_IDLE_HOOK             0       /* 空闲任务钩子函数 */
#define configUSE_TICK_HOOK             0       /* 时钟节拍钩子函数 */
#define configCPU_CLOCK_HZ              ((unsigned long)72000000)  /* CPU 主频 72MHz */
#define configTICK_RATE_HZ              ((TickType_t)1000)         /* 系统节拍频率 1000Hz = 1ms */
#define configMAX_PRIORITIES            (5)     /* 最大优先级数量 */
#define configMINIMAL_STACK_SIZE        ((unsigned short)128)      /* 空闲任务栈大小(单位:字, 即 512 字节) */
#define configTOTAL_HEAP_SIZE           ((size_t)(10 * 1024))      /* FreeRTOS 堆大小 10KB (C8T6 总共 20KB RAM) */
#define configMAX_TASK_NAME_LEN         (16)    /* 任务名最大长度 */
#define configUSE_TRACE_FACILITY        0       /* 跟踪功能 */
#define configUSE_16_BIT_TICKS          0       /* 0: 32位tick计数器, 1: 16位 */
#define configIDLE_SHOULD_YIELD         1       /* 空闲任务是否让出 CPU */

/* 软件定时器 */
#define configUSE_TIMERS                0       /* 0: 不使用软件定时器 */
#define configTIMER_TASK_PRIORITY       (configMAX_PRIORITIES - 1)
#define configTIMER_QUEUE_LENGTH        5
#define configTIMER_TASK_STACK_DEPTH    (configMINIMAL_STACK_SIZE * 2)

/* 协程 (一般不用) */
#define configUSE_CO_ROUTINES           0
#define configMAX_CO_ROUTINE_PRIORITIES (2)

/* 可选 API 函数开关: 1=包含, 0=排除 */
#define INCLUDE_vTaskPrioritySet        1
#define INCLUDE_uxTaskPriorityGet       1
#define INCLUDE_vTaskDelete             1
#define INCLUDE_vTaskCleanUpResources   0
#define INCLUDE_vTaskSuspend            1
#define INCLUDE_vTaskDelayUntil         1
#define INCLUDE_vTaskDelay              1

/*-----------------------------------------------------------
 * Cortex-M3 中断优先级配置
 *
 * STM32 使用 4 位优先级 (0~15), NVIC 中左移 4 位变成 0x00~0xF0
 * FreeRTOS 使用的是 NVIC 原始值 (0~255)
 *----------------------------------------------------------*/

/* 内核中断优先级 (最低优先级) */
#define configKERNEL_INTERRUPT_PRIORITY         255

/* 可管理的最高中断优先级
 * 优先级数值 >= 此值的中断可以调用 FreeRTOS API (FromISR 系列)
 * 优先级数值 < 此值的中断不受 FreeRTOS 管理, 响应更快但不能调用 FreeRTOS API
 * 191 = 0xBF, 对应优先级 11 (4位有效位时) */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    191

/* 用于 ST 标准库中断优先级设置时的参考值 (0~15) */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15

/*-----------------------------------------------------------
 * 将 FreeRTOS 的中断处理函数映射到 STM32 的中断向量名
 * 这样 port.c 中定义的函数能正确对应到中断向量表
 *----------------------------------------------------------*/
#define vPortSVCHandler     SVC_Handler
#define xPortPendSVHandler  PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */

步骤三:修改 stm32f10x_it.c(解决中断冲突)

[!CAUTION]
这是最关键的一步! FreeRTOS 的 port.c 中已经定义了 SVC_HandlerPendSV_HandlerSysTick_Handler 这三个中断处理函数。如果 stm32f10x_it.c 中也有这三个函数,编译时会报 重复定义错误

需要做的修改:

  1. 注释掉 stm32f10x_it.c 中的 SVC_Handler()
  2. 注释掉 stm32f10x_it.c 中的 PendSV_Handler()
  3. 注释掉 stm32f10x_it.c 中的 SysTick_Handler()(或改为在 FreeRTOSConfig.h 中用 hook 回调)

对于你的 SysTick_Handler 中的 g_SystemTick++,可以通过 FreeRTOS 的 Tick Hook 机制来保留这个功能(在 config 中设置 configUSE_TICK_HOOK 为 1,然后实现 vApplicationTickHook() 函数)。


步骤四:修改 EIDE 工程配置

需要在 eide.yml 中:

4.1 添加头文件包含路径

incList 中添加:

  • FreeRTOS/include
  • FreeRTOS/portable/RVDS/ARM_CM3

4.2 添加源文件到虚拟文件夹

virtualFolder 中新增 FreeRTOS 分组,包含所有 .c 文件。


步骤五:修改 main.c 添加测试任务

修改 main.c 来创建 FreeRTOS 任务,用两个 LED 闪烁任务来验证移植是否成功。


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇