STM32F103C8T6 移植 FreeRTOS 全流程+正版/盗版芯片差异+致命踩坑总结
一:前期准备
FreeRTOS源码(我用的是FreeRTOS v202107.00)和成功编译的工程模板(越简单越好)。
源码文件夹如图:
工程文件夹如图:

二:完整移植步骤
1.新建工程文件夹,存放FreeRTOS内核文件
在基础工程中,新建一个名为“FreeRTOS”的文件夹,在文件夹目录下再分别新建src、inc、port文件夹:其中,src文件夹用来存放源码,inc文件夹用来存放头文件,port文件夹用来存放移植平台的相关文件。
FreeRTOS/
├── src/ // 存放内核核心.c文件
├── inc/ // 存放内核核心.h文件
└── port/ // 存放移植层相关文件
建好的文件夹如图所示:

2.复制FreeRTOS核心源码到工程目录
其中,inc文件夹包括:
源码路径:FreeRTOSv202107.00\FreeRTOS\Source\include
include文件夹里全部都是FreeRTOS的头文件,将其全部复制到新建的inc文件夹中(不包括readme)。
移植完成的inc文件应如图:

port文件夹包括:
源文件路径1:FreeRTOSv202107.00\FreeRTOS\Source\portable\MemMang
源文件路径2:FreeRTOSv202107.00\FreeRTOS\Source\portable\RVDS\ARM_CM3
复制路径1目录下的“heap_4.c”到port文件夹,路径2目录下的“port.c”和“port.h”两个文件到port文件夹。
复制完成后,port文件夹下仅保留heap_4.c、port.c、port.h三个文件,如图所示:

src文件夹包括:
源文件路径:FreeRTOSv202107.00\FreeRTOS\Source
将Source文件夹下所有的.c文件全部复制到src文件夹中,如图所示:

添加配置文件:
源文件路径:FreeRTOSv202107.00\FreeRTOS\Demo\CORTEX_STM32F103_Keil
在文件夹中的FreerRTOSConfig.h文件到新建的FreeRTOS文件夹中,如图所示:

3.建立工程组
打开工程,新建三个工程分组(FreeRTOS_SRC、FreeRTOS_INC、FreeRTOS_PORT),与FreeRTOS文件夹下的src、inc、port对应,分别用于存放不同类型的文件,避免与STM32标准库文件混淆,同时保持工程结构清晰,建好的组如图所示:

4.将对应文件加入组
添加src文件夹的6个核心c文件(除去stream_buffer之外的六个文件)到FreeRTOS_SRC组。
添加inc文件夹的所有头文件和配置文件FreeRTOSConfig.h到FreeRTOS_INC组。
添加port文件夹的2个c文件(heap_4.c、port.c)到FreeRTOS_PORT组。
全部添加完成应如图所示:

5.添加头文件路径
在工程中,打开“Options for Target”→“C/C++”→“Include Paths”,添加以下头文件路径:
- ./FreeRTOS
- ./FreeRTOS/src
- ./FreeRTOS/inc
- ./FreeRTOS/port
添加完成应如图所示:

6.修改核心文件
FreeRTOSConfig.h(核心配置文件)
完成中断函数的重定义,在文件夹顶部加入下面三行代码:
// 中断重定向(核心,必须重定向)
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
stm32f10x_it.c(中断服务函数,避免冲突)
stm32f10x_it.c是STM32的中断服务函数文件,其中SVC_Handler、PendSV_Handler、SysTick_Handler三个中断函数,与FreeRTOS v202107.00的移植层冲突,必须修改,否则编译报错或死机:
打开stm32f10x_it.c,注释掉上面所说三个函数的空定义代码,如图所示:

修改main.c(创建测试任务,验证移植成功)
在main.c中添加头文件,并创建一个简单的LED闪烁任务,用于验证移植是否成功,代码如下:
#include "stm32f10x.h"
#include "Delay.h"
#include "FreeRTOS.h"
#include "task.h"
TaskHandle_t task1Handler;
static void task1(void *arg)
{
while(1)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
vTaskDelay(500);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
vTaskDelay(500);
}
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
xTaskCreate(task1,"task1",100,NULL,2,&task1Handler);
vTaskStartScheduler();
while(1);
}
编译无报错、无警告,下载到开发板后:
-
LED按设定频率(500ms)闪烁
-
调试器查看,程序不进入HardFault_Handler死循环
-
任务调度正常,无死机、无跑飞现象
三:正/盗版芯片的差异(已解决)
目前,有个现象就是盗版芯片(0X2B开头)能正常跑程序现象,正版芯片(0X1B)无法跑,会卡死在HardFault_Handler函数中:
解决办法:不是芯片不兼容,而是堆空间开太大!
STM32F103C8T6 仅有 20KB RAM,堆空间设置过大会直接内存溢出。
FreeRTOSConfig.h堆空间设置正确配置(正版/盗版都能跑)!
#define configTOTAL_HEAP_SIZE ((size_t)(8 * 1024))
四:坑点
中断优先级配置
STM32F103移植FreeRTOS v202107.00,优先级必须配置为configKERNEL_INTERRUPT_PRIORITY=255、configMAX_SYSCALL_INTERRUPT_PRIORITY=191,优先级分组必须为Group4,不能乱改。
C8T6 堆空间建议不超过 8KB,正版 ST 对内存溢出零容忍,国产芯片相对宽松。
五:常见报错及解决
L6200E 重复定义:stm32f10x_it.c 中 SVC_Handler、PendSV_Handler 未注释。
进入 HardFault:99% 是 configTOTAL_HEAP_SIZE 设置过大,RAM 溢出。
卡在 vTaskStartScheduler:SysTick 未正常工作,检查中断重定向与优先级分组。
六:重点
SVC_Handler、PendSV_Handler必须重定向,由FreeRTOS v202107.00移植层实现,stm32f10x_it.c中必须注释,不能重复实现。
SysTick的两种实现方式(宏重定向/手动调用)不能同时使用,否则会导致中断冲突,v202107.00版本同样适用。
移植过程中,每修改一处配置,就编译一次,逐步排查,不要一次性修改多处,避免无法定位问题;v202107.00版本编译报错与旧版本一致,可按常规方法排查。
FreeRTOS v202107.00版本无需额外修改移植层文件,核心配置与旧版本一致,直接复用本文配置即可,无需额外适配;文件存放需严格遵循src、inc、port的文件夹划分,便于后续维护。
FreeRTOSConfig.h文件需放在inc文件夹下,与其他核心头文件放在一起,避免路径混乱导致配置文件无法识别。
七:源码及写在后面
FreeRTOSConfig.h
/*
* FreeRTOS V202107.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
// 中断重定向(核心,必须重定向)
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#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
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */
/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15. This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
#endif /* FREERTOS_CONFIG_H */
本文所有代码均在STM32F103C8T6上实测通过,可直接复制到 工程中使用,无需修改任何参数。
本博客仅记录自己的学习进程,无任何商业用途,基于论坛上已经存在的内容结合自己实操过程完成了此博客,自己也做了一些细节验证,在此记录下来作为学习沉淀。如有侵权,联系速删。
更多推荐



所有评论(0)