FreeRTOS源码结构分析与移植(基于STM32F407)

码农爱学习 发表于 2021/08/15 14:38:54 2021/08/15
【摘要】 本文主要介绍FreeRTOS的源码结构,以及如何将FreeRTOS移植到STM32F407单片机中

1 FreeRTOS简介

FreeRTOS,全称Free Real Time Operating System,即免费的实时操作系统。相比于计算机中用到的Windows,MacOS,Linux等操作系统,实时操作系统(RTOS)是一种轻量级的操作系统,适用于嵌入式硬件中,用于解决单片机类裸机轮询方式在处理多个任务时的实时性不高的问题。

目前的实时操作系统有好多种,除FreeRTOS外,还有μCOS、RT-Thread、RTX、Alios Things、Huawei LiteOS等。

2 什么是RTOS?

实时操作系统(RTOS)的主要特点是可以实现多任务,与多任务系统相对的是裸机系统。

裸机系统

裸机系统就是最初我们学习单片机编程时接触的那种编程方式,main函数中一个while大循环依次处理各个模块的任务,对于需要及时检测的事件会使用中断。这种使用大循环的程序运行方式也叫轮询系统,加上中断处理函数后又称前后台系统,中断处理称作前台,无限循环称作后台。

多任务系统

多任务系统是将各个处理模块编写为单独的任务,每个任务本身是个无限循环,程序运行初期会创建各个子任务,通过任务调度的方式,利用各任务的阻塞时刻不断切换运行各个任务,达到一种看起来是多个任务在同时运行的一种效果。并且,通过中断标志以及任务间通信的相关机制,可以实现任务之间的快速响应。

3 FreeRTOS特点

  • 使用免费!

  • 系统简单小巧、文件数量少、通常情况下内核占用4~9k字节空间

  • 抢占式内核

  • 代码主要由C编写,可移植性高,已实现在30多种架构的芯片上移植

  • 任务与任务,任务与中断间的通信方式包括:信号量、消息队列、事件标志组、任务通知

  • 具有优先级继承特性的互斥信号令,避免优先级反转问题

  • 高效的软件定时器

4 FreeRTOS源码目录结构

这里以FreeRTOS v9.0.0版本为例,代码包含FreeRTOS和FreeRTOS-Plus文件夹,后者是一些补充文件,初学者用不到,可以先忽略。在FreeRTOS文件夹中主要关注source文件夹,这里是FreeRTOS的全部源码,包括6个c文件和include文件夹下的多个h文件。另外,在portable文件夹下,是针对不同硬件平台的单独区分使用的代码,目前考虑使用Keil开发STM32F407,所以portable文件夹只需使用RVDS的ARM_CM4F以及MemMang。

关于各个c文件的主要用途:

  • port.c : 针对不同硬件平台的接口

  • heap_4.c : 内存管理相关

  • croutine.c : 协程相关

  • event_groups.c : 事件标志组相关

  • list.c : 列表,FreeRTOS的一种基础数据结构

  • queue.c : 队列相关

  • tasks.c : 任务创建、挂起、恢复、调度相关

  • timers.c : 软件定时器相关

另外在Demo文件夹下还需要用到一个FreeRTOSConfig.h,该文件中通过各种宏定义的方式来配置FreeRTOS需要使用哪些资源。

5 FreeRTOS移植(基于STM32F407)

首先新建或找一个基于Keil的STM32基础工程,这里我已经创建好了一个STM32F407VET6的工程模板,工程结构如下图的第1步的矩形框内所示。

下面需要移植FreeRTOS了,将FreeRTOS的源码文件复制到工程文件夹中,一些用不到的文件可删除(哪些文件需要用到可参考上一篇的源码结构分析部分),然后在Keil中也创建一个FreeRTOS目录,将c文件添加进工程,注意port.c来自于RDVS的ARM_CM4F,对应于移植到的SMT32F407硬件。

添加完c文件后,还要添加对应的h文件的搜寻路径,具体如下:

然后就可以编译了,先进行第1次编译:

......(省略显示若干行)
FreeRTOS\portable\RVDS\ARM_CM4F\port.c: 0 warnings, 1 error
compiling heap_4.c...
.\FreeRTOS\include\FreeRTOS.h(98): error:  #5: cannot open source input file "FreeRTOSConfig.h": No such file or directory
  #include "FreeRTOSConfig.h"
FreeRTOS\portable\MemMang\heap_4.c: 0 warnings, 1 error
".\Objects\Template_FreeRTOS.axf" - 8 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed:  00:00:23

有一个错误,找不到"FreeRTOSConfig.h",这个文件在FreeRTOS源码的Demo文件中,

将Demo中的"FreeRTOSConfig.h"文件放到FreeRTOS文件夹下的include文件夹下, 进行第2次编译:

......(省略显示若干行)
compiling tasks.c...
compiling timers.c...
compiling port.c...
FreeRTOS\portable\RVDS\ARM_CM4F\port.c(713): error:  #20: identifier "SystemCoreClock" is undefined
                
ortNVIC_SYSTICK_LOAD_REG = ( 
onfigSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
FreeRTOS\portable\RVDS\ARM_CM4F\port.c: 0 warnings, 1 error

又提示"SystemCoreClock" 未定义,因为在"FreeRTOSConfig.h" : 中使用了SysyemCoreClock来标记MCU的频率,

在"FreeRTOSConfig.h" :的87~95行:

#ifdef __ICCARM__
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif
​
#define configUSE_PREEMPTION            1
#define configUSE_IDLE_HOOK             1
#define configUSE_TICK_HOOK             1
#define configCPU_CLOCK_HZ              ( SystemCoreClock )

将条件编译

#ifdef __ICCARM__

修改为

#if defined(__ICCARM__)||defined(__CC_ARM)||defined(__GNU__)

再次进行第3次编译:

......(省略显示若干行)
compiling port.c...
compiling heap_4.c...
linking...
.\Objects\Template_FreeRTOS.axf: Error: L6200E: Symbol SVC_Handler multiply defined (by port.o and stm32f4xx_it.o).
.\Objects\Template_FreeRTOS.axf: Error: L6200E: Symbol PendSV_Handler multiply defined (by port.o and stm32f4xx_it.o).
.\Objects\Template_FreeRTOS.axf: Error: L6200E: Symbol SysTick_Handler multiply defined (by port.o and stm32f4xx_it.o).
Not enough information to list image symbols.
Not enough information to list the image map.
Finished: 2 information, 0 warning and 3 error messages.
".\Objects\Template_FreeRTOS.axf" - 3 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed:  00:00:02

又提示port.o与stm32f4xx_it.o有重复定义(.o为编译的目标文件,其实就是对应的.c文件出了问题)

注释掉stm32f4xx_it.c中的SVC_Handler() PendSV_Handler() SysTick_Handler()即可

修改后的stm32f4xx_it.c的110~145行:

/**
 \* @brief This function handles SVCall exception.
 \* @param None
 \* @retval None
 */
//void SVC_Handler(void)
//{
//}
​
/**
 \* @brief This function handles Debug Monitor exception.
 \* @param None
 \* @retval None
 */
void DebugMon_Handler(void)
{
}
​
/**
 \* @brief This function handles PendSVC exception.
 \* @param None
 \* @retval None
 */
//void PendSV_Handler(void)
//{
//}
​
/**
 \* @brief This function handles SysTick Handler.
 \* @param None
 \* @retval None
 */
//void SysTick_Handler(void)
//{
// 
//}

再次进行第4次编译:

......(省略显示若干行)
linking...
.\Objects\Template_FreeRTOS.axf: Error: L6218E: Undefined symbol vApplicationIdleHook (referred from tasks.o).
.\Objects\Template_FreeRTOS.axf: Error: L6218E: Undefined symbol vApplicationStackOverflowHook (referred from tasks.o).
.\Objects\Template_FreeRTOS.axf: Error: L6218E: Undefined symbol vApplicationTickHook (referred from tasks.o).
.\Objects\Template_FreeRTOS.axf: Error: L6218E: Undefined symbol vApplicationMallocFailedHook (referred from heap_4.o).
Not enough information to list image symbols.
Finished: 1 information, 0 warning and 4 error messages.
".\Objects\Template_FreeRTOS.axf" - 4 Error(s), 0 Warning(s).

又提示4个hook函数未定义,

这是因为在"FreeRTOSConfig.h"中定义了这些钩子函数,但未找到函数定义,我们先注释掉这些定义,

就是将configUSE_IDLE_HOOK之类的宏定义定义为0即可,

查看"FreeRTOSConfig.h"的93~108行:

#define configUSE_IDLE_HOOK             1
#define configUSE_TICK_HOOK             1
#define configCPU_CLOCK_HZ              ( SystemCoreClock )
#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES            ( 5 )
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 75 * 1024 ) )
#define configMAX_TASK_NAME_LEN         ( 10 )
#define configUSE_TRACE_FACILITY        1
#define configUSE_16_BIT_TICKS          0
#define configIDLE_SHOULD_YIELD         1
#define configUSE_MUTEXES               1
#define configQUEUE_REGISTRY_SIZE       8
#define configCHECK_FOR_STACK_OVERFLOW  2
#define configUSE_RECURSIVE_MUTEXES     1
#define configUSE_MALLOC_FAILED_HOOK    1

修改93 94 106 108行的数值为0,即:

#define configUSE_IDLE_HOOK             0
#define configUSE_TICK_HOOK             0
......(省略显示11行)
#define configCHECK_FOR_STACK_OVERFLOW  0
......(省略显示1行)
#define configUSE_MALLOC_FAILED_HOOK    0

再次进行第5次编译:

......(省略显示若干行)
compiling port.c...
compiling heap_4.c...
linking...
Program Size: Code=1880 RO-data=424 RW-data=68 ZI-data=2036  
".\Objects\Template_FreeRTOS.axf" - 0 Error(s), 0 Warning(s).
Build Time Elapsed:  00:00:01

终于编译ok了,这样基本上算移植成功了,下一篇写个FreeRTOS的基础例程测试一下是否可以正常使用。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。