因公司项目使用STM32F407的网络功能,虽然已经使用UCOSII作为TCP客户端成功链接网络,但是UCOS毕竟可能会涉及版权问题,不得不改用FreeRTOS+LWIP作项目开发。
(一) 资料链接:
1.FreeRTOS源码下载网址:https://sourceforge.net/projects/freertos/files/FreeRTOS/
2.FreeRTOS中文实用教程,这是英文原文下载地址http://www.FreeRTOS.org
(二) 移植过程
1.找一个标准库的F407标准工程(正点原子串口实验),网上有很多教程,在此并非主要内容。

2.下载FreeRTOS并解压,在此说明本文使用的版本为FreeRTOSv10.0.1。

FreeRTOS目录介绍
├─FreeRTOS │ ├─Demo // 各种开发工具的完整Demo,开发者可以方便的以此搭建出自己的项目,甚至直接使用 │ │ ├─Common // 所有例程都可以使用的演示例程文件 │ │ └─其他 // 对应平台和开发工具的项目例程(命名:平台_开发工具,例如:CORTEX_M4F_M0_LPC43xx_Keil) │ ├─License // 使用修改过的GPL │ └─Source // FreeRTOS的源码 │ ├─include // 源码对应的头文件 │ └─portable // 每个支持的处理器架构需要一小段与处理器架构相关的RTOS代码。该目录下即为和开发平台相关的代码 │ ├─MemMang // FreeRTOS内存管理方案(一般要根据平台来选择以下5个之一) │ │ heap_1.c │ │ heap_2.c │ │ heap_3.c │ │ heap_4.c │ │ heap_5.c │ └─其他 // 其他开发工具相关的代码,需要根据自己的开发工具进行选择 │ croutine.c // 协线程(协程)文件,和任务类似,在系统资源比较缺乏下使用 │ event_groups.c // 事件标志组 │ list.c // 列表结构描述,在内核整体控制上都使用了列表格式数据处理,一切数据结构的基础 │ queue.c // 队列,任务和任务之间的通讯处理 │ tasks.c // 所有任务相关函数 │ timers.c // 软件定时器,以任务形式存在 │ stream_buffer.c // 10.0.0 之后开始新增 └─FreeRTOS-Plus // FreeRTOS+组件和演示例程
详细介绍
- list.c、tasks.c、queue.c必不可少,这三个文件是FreeRTOS最基本的源文件。至于同目录下的timer.c、event_groups.c等文件,根据需要添加即可。
- /FreeRTOS/Source/portable/MemMang下的heap_x.c也是必不可少的,表示不同的内存管理模式,根据需要选择其中一个,STM32系列一般用heap_4.c。
- /FreeRTOS/Source/portable/下根据开发工具选择对应目录下的文件。例如:若使用Keil,对应目录下只有一个文件,让直接用RVDS目录下对应的文件。根据芯片选择对应目录下文件port.c、portmacro.h即可。
- 对应的头文件当然也是必不可少。/FreeRTOS/Source/include下的文件可根据需要删除不需要的文件!
- FreeRTOSConfig.h位于/FreeRTOS/Demo/对应的平台下,这个文件其实就相当于STM32标准库中的stm32fxx_conf.h(使用标准外设库时,通过该文件进行配置)。
3.文件拷贝
在STM32F407裸板工程根目录下新建一个"FreeRTOS"文件夹,并将下载的官方移植工程FreeRTOSv10.0.1\FreeRTOSv10.0.1\FreeRTOS\Source下的所有文件,全部拷贝到该文件下;


此时就要用到FreeRTOS的一些demo程序找到官方对于407的移植工程FreeRTOSv10.0.1\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK下的FreeRTOSConfig.h拷贝到工程(USER)中。

4.将头文件路径和文件添加到工程中
"..\FreeRTOS\include"和"..\FreeRTOS\portable\RVDS\ARM_CM4F"添加入头文件路径

将FreeRTOS文件夹下"croutine.c"、"event_groups.c"、"list.c"、"queue.c"、"tasks.c"、"timers.c"添加到工程

将FreeRTOS\portable\RVDS\ARM_CM4F文件夹下"port.c"和FreeRTOS\portable\MemMang文件夹下"heap_4.c"添加到工程

5.编译调试-解决问题
错误1
..\FreeRTOS\portable\RVDS\ARM_CM4F\port.c(712): error: #20: identifier "SystemCoreClock" is undefined
解决问题1:
打开FreeRTOSConfig.h可以看到这样一段代码
#ifdef __ICCARM__ #include <stdint.h> extern uint32_t SystemCoreClock; #endif
将其改成如下部分就可以去除这个错误
#if defined (__ICCARM__)||defined(__CC_ARM)||defined(__GNUC__) #include <stdint.h> extern uint32_t SystemCoreClock; #endif
解决SYStemCoreClock问题后,提示三个函数有重复定义。
错误2
..\OBJ\USART.axf: Error: L6200E: Symbol PendSV_Handler multiply defined (by port.o and stm32f4xx_it.o). ..\OBJ\USART.axf: Error: L6200E: Symbol SVC_Handler multiply defined (by port.o and stm32f4xx_it.o). ..\OBJ\USART.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 load addresses in the image map. Finished: 2 information, 0 warning and 3 error messages. "..\OBJ\USART.axf" - 3 Error(s), 0 Warning(s).
解决问题2:
其中SysTick_Handler再FreeRTOS中被重新定义成系统心跳处理中断函数,PendSV_Handler,SVC_Handler也被在FreeRTOS中重新定义用于任务切换,所以需要注释掉stm32F4xxx_it.c中的这三个中断函数。
解决重复定义的问题后,又出现新问题
错误3
..\OBJ\USART.axf: Error: L6218E: Undefined symbol vApplicationIdleHook (referred from tasks.o). ..\OBJ\USART.axf: Error: L6218E: Undefined symbol vApplicationStackOverflowHook (referred from tasks.o). ..\OBJ\USART.axf: Error: L6218E: Undefined symbol vApplicationTickHook (referred from tasks.o). ..\OBJ\USART.axf: Error: L6218E: Undefined symbol vApplicationMallocFailedHook (referred from heap_4.o). Not enough information to list image symbols. Not enough information to list load addresses in the image map. Finished: 2 information, 0 warning and 4 error messages. "..\OBJ\USART.axf" - 4 Error(s), 0 Warning(s).
解决问题3:
其中是关于stasks.c和heap_.c的错误,但是问题关键可以从FreeRTOSConfig.h中改变,因为该文件才是配置FreeRTOS系统最重要的文件。HOOK钩子函数未定义的错误,在FreeRTOSConfig.h中改为如下即可解决:
#define configUSE_PREEMPTION 1 //调度器采用抢占式还是协程式 #define configUSE_IDLE_HOOK 0 //空闲任务狗子函数 #define configUSE_TICK_HOOK 0 //时间片钩子函数 #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 //空闲任务是否会为同等优先级的任务让出CPU使用权 #define configUSE_MUTEXES 1 #define configQUEUE_REGISTRY_SIZE 8 #define configCHECK_FOR_STACK_OVERFLOW 0 //堆栈溢出检测 #define configUSE_RECURSIVE_MUTEXES 1 //递归互斥信号量 #define configUSE_MALLOC_FAILED_HOOK 0 //内存分配失败钩子函数 #define configUSE_APPLICATION_TASK_TAG 0 #define configUSE_COUNTING_SEMAPHORES 1 #define configGENERATE_RUN_TIME_STATS 0 //运行时间统计功能
至此编译成功,工程模板程序已移植错误,可按FreeRTOS正常使用了。
本文如有错误欢迎指正,谢谢。

浙公网安备 33010602011771号