基于STM32F107的FreeRTOS移植
- 格式:pdf
- 大小:232.23 KB
- 文档页数:6
在MDK中为STM32移植FreeRTOS/***************************************************************************** FreeRTOS版本是V7.0.1。
STM32本人用的是大容量的stm32f103zgt6,故启动文件使用startup_stm32f10x_hd.s。
固件库版本V3.5.0。
编译环境用的是MDK Verson:4.22。
注:用户在移植FreeRTOS操作系统前最好先移植好STM32的固件库,调试好确保固件库能成功运行后,再进行操作系统的移植。
*****************************************************************************/ 1、在Project里新建一个文件夹并命名为FreeRTOS。
复制FreeRTOS解压包里的Source文件夹里的croutine.c,timers.c,list.c,queue.c,tasks.c以及Source->portable->RVDS->ARM_CM3->port.c以及Source->portable->MemMang->heap_2.c到自建的FreeRTOS文件夹。
按新建FreeRTOS组并添加相应文件。
如下图:2、在FreeRTOS文件夹里再新建一个文件夹include。
在include里面加入如下文件:①FreeRTOS解压包里的Source文件下include文件夹中的所有.h文件;②Source->portable->RVDS->ARM_CM3->portmacro.h;③FreeRTOS解压缩包里的Demo 文件下找到CORTEX_STM32F103_Keil文件夹(用户根据自己的开发平台选择相应文件夹),找到FreeRTOSConfig.h文件加入到include中。
基于STM32的FreeRTOS应用问题解答1、如何将FreeRTOS 移植到不同的Cortex-M 内核?答:如果要将FreeRTOS 移植到正确的Cortex-M 产品,你必须从正确的目录导入port.c 文件。
例如,若微控制器是带有IAR 工具的Cortex-M0 内核,则您必须从FreeRTOS\Source\portable\IAR\ARM_CM0 获取port.c。
2、FreeRTOS 使用需要ROM/RAM?答:这取决于您的编译器、代码架构,以及RTOS 内核配置。
一般来说,RTOS 内核本身需要大约 5 到10 K 字节ROM 空间。
如果创建的线程或队列数增加,RAM 使用量就会上升。
3、怎样设置CPU 时钟?答:CPU 时钟由FreeRTOSConfig.h 中的configCPU_CLOCK_HZ 定义,比如在STM32CubeF4”>STM32CubeF4固件内它由SystemCoreClock 提供,表示HCLK 时钟(AHB 总线),通过调用SystemClock_Config() 函数配置RCC 时钟时会设置此值。
4、怎样设置中断优先级?答:任何使用RTOS API 函数的中断服务程序,其优先级必须手动设置为大于等于FreeRTOSConfig.h 文件中configMAX_SYSCALL_INTERRUPT_PRIORITY 的设置值。
这确保其中断的逻辑优先级低于等于configMAX_SYSCALL_INTERRUPT_PRIORITY 设置的优先级。
5、怎样使用非SysTick 时钟生成时间片中断?答:用户可选择性地自己提供时间片中断源,方法是使用非SysTick 的定时器生成中断:提供vPortSetupTimerInterrupt() 的实现,它会以FreeRTOSConfig.h 文件中定义的configTICK_RATE_HZ 常量指定的频率产生中断。
FreeRTOS移植到STM32F103步骤与注意事项年05月29日 11:16:36•1496原文地址:前言:由于之前听过太多人抱怨移植FreeRTOS到STM32有各种各样的问题,小灯经过一年多对FreeRTOS的研究并在公司产品中应用,多少有些心得,接下来就由小灯以最新版的FreeRTOS为例一步一步移植到STM32F103上,并提醒大家某些需要注意的事项。
本文档为非正式技术文档,故排版会有些凌乱,希望大家能提供宝贵意见以供小灯参考改进。
下面先以IAR移植为例,说明移植过程中的诸多注意事项,最后再以MDK移植时不再重复说明,所以还是建议大家先花些时间看IAR的移植过程,哪怕你不使用IAR,最好也注意下那一大堆注意事项!一、从官网下载最新版的FreeRTOS源码下面的网址是官方最新源码的下载地址:目前官方提供的最新版本是v9.0.0, FreeRTOS源码在解压目录下的路径为FreeRTOS_V9.0.0rc2\FreeRTOS\SourceFreeRTOS组织为了抢用户也是拼了命的,不信你打开Demo文件夹看看,里面提供了FreeRTOS在各种单片机上已经移植好的工程,如果建工程时遇到什么问题,可以参考下这些Demo。
不过小灯现在着重于自己动手移植FreeRTOS,考虑到原子哥@正点原子的用户比较多,绝大多数习惯了使用MDK来开发STM32,因此小灯分别以IAR和MDK两种使用比较广泛的开发环境来移植FreeRTOS。
说到IAR和MDK,不得不提的是小灯自从用了IAR之后就果断放弃了MDK,相信很多人有这个经历,哈哈!在开始移植FreeRTOS之前,先介绍下FreeRTOS的源码:FreeRTOS的源码比较少,源文件也远没有UCOS多,不过麻雀虽小五脏俱全,FreeRTOS的短小精悍也是最令小灯着迷的,虽然缺少了很多组成部分,例如GUI、网络协议栈、文件系统等,不过这些统统都不是问题,因为完全可以移植第三方的组件!一不小心牛逼又吹大了,哈哈!回归正题,FreeRTOS的源码核心部分是tasks.c和list.c,其余的几个文件功能都是可选的,例如软件定时器、队列、协程等等,小灯就不介绍了,有兴趣的话可以到官网上看介绍。
FreeRTOS 移植此部分介绍移植FreeRTOS的基本步骤。
▪修改范例是用于不同的编译器或运行于不同的硬件▪FreeRTOS移植向导修改范例是用于不同的编译器或运行于不同的硬件这篇文章有什么用?FreeRTOS已经包含很多范例程序——每一个均用于:1. 一个特定的微控制器2. 一个特定的开发工具(编译器,调试器,等等)3. 一个特定的硬件平台(原型或评估板)在官方主页左边的’RTOS Ports‘菜单下有大量的文档。
然而不可能为每一个微控制器、编译器和评估板的组合提供一个范例工程——因此有可能没有一个范例程序与你的需求完全吻合。
这个文档就是指导你如何修改与组合范例程序来更好的符合你的要求。
十分容易就可以使用一个现有的评估板范例经过修改然后用在另外一个上——如果是从一个编译器修改到另外一个可能会复杂一点。
这个文档提供相似平台的移植指引。
然而把FreeRTOS从一个平台移植到另外一个完全不同的、还未被支持的处理器内核体系并不是一件容易的工作。
因此这个文档不会包括建立一个全新的FreeRTOS平台的内容。
转换一个范例用于不同的评估板这部分描述把一个已有的范例程序从一个原型板转换到另一个的步骤,没有改变使用的微控制器与编译器。
作为例子,这些指引将用来把运行于SAM7S硬件上的IAR SAM7S的范例转换为运行于Olimex SAM7-P64原型板。
在进行下一步前要保证前面的步骤完全成功:1. 初始编译:应该使用一个现有的范例程序来进行移植练习,因此首先要检查你能否成功的编译一个已有的范例程序——在进行任何修改之前。
多数情况下,范例程序可以正常编译而不会有任何的错误或警告。
官方网站上包含有下载的每个范例程序的完整文档,包含编译向导。
请完整的阅读这些文档。
2. 修改LED IO:LED提供一个最简单的可视化方式来反馈范例程序正在运行,因此尽快的使led在新的硬件平台上运行起来是非常有用的。
可能将要移植的硬件平台与范例程序硬件平台的LED并不是处于同一个IO端口上——因此需要做一些小的修改。
FreeRTOS移植到STM32F103步骤与注意事项前言:由于之前听过太多人抱怨移植FreeRTOS到STM32有各种各样的问题,小灯经过一年多对FreeRTOS的研究并在公司产品中应用,多少有些心得,接下来就由小灯以最新版的FreeRTOS为例一步一步移植到STM32F103上,并提醒大家某些需要注意的事项。
本文档为非正式技术文档,故排版会有些凌乱,希望大家能提供宝贵意见以供小灯参考改进。
下面先以IAR移植为例,说明移植过程中的诸多注意事项,最后再以MDK移植时不再重复说明,所以还是建议大家先花些时间看IAR的移植过程,哪怕你不使用IAR,最好也注意下那一大堆注意事项!一、从官网下载最新版的FreeRTOS源码下面的网址是官方最新源码的下载地址:https:///projects/freertos/files/latest/download?source=files目前官方提供的最新版本是v9.0.0, FreeRTOS源码在解压目录下的路径为FreeRTOS_V9.0.0rc2\FreeRTOS\SourceFreeRTOS组织为了抢用户也是拼了命的,不信你打开Demo文件夹看看,里面提供了FreeRTOS在各种单片机上已经移植好的工程,如果建工程时遇到什么问题,可以参考下这些Demo。
不过小灯现在着重于自己动手移植FreeRTOS,考虑到原子哥@正点原子的用户比较多,绝大多数习惯了使用MDK来开发STM32,因此小灯分别以IAR和MDK两种使用比较广泛的开发环境来移植FreeRTOS。
说到IAR和MDK,不得不提的是小灯自从用了IAR之后就果断放弃了MDK,相信很多人有这个经历,哈哈!在开始移植FreeRTOS之前,先介绍下FreeRTOS的源码:FreeRTOS的源码比较少,源文件也远没有UCOS多,不过麻雀虽小五脏俱全,FreeRTOS的短小精悍也是最令小灯着迷的,虽然缺少了很多组成部分,例如GUI、网络协议栈、文件系统等,不过这些统统都不是问题,因为完全可以移植第三方的组件!一不小心牛逼又吹大了,哈哈!回归正题,FreeRTOS的源码核心部分是tasks.c和list.c,其余的几个文件功能都是可选的,例如软件定时器、队列、协程等等,小灯就不介绍了,有兴趣的话可以到官网上看介绍。
1、首先在官网下载freeRtos9.0的原文件【不太好找下载地址,慢慢找】
2、在eclipse中建立起正常的STM32工程,以STM32f103RBT6为例,可以正常编译并烧录
3、下面需要复制一些文件到STM32工程当中,看截图
源文件存在于freeRtos源文件当中,具体位置请自行体悟,这个开动一下脑筋即可
3、下面把新添加的源文件和头文件包含到工程当中【具体操作自行百度】
4、最核心的部分是修改STM32工程里面的文件,只需要改动三个地方即可,就是把滴答中断时钟等指向freeRTOS当中,修改“”,添加头引用#include "port.h" 下面的如图
就是把vPortSVCHandler 代替SVCall handler
xPortPendSVHandler 代替 PendSV handler
xPortSysTickHandler 代替 The SysTick handler
5、最后就是配置工程打开FreeRTOSConfig.h,如图主要是配置时钟,栈空间大小等信息,这个自行体会,STM32F030F4P6的内存只有4K,可以按照下图配置,可以正常跑三四个小线程
在main.c中就可以建立线程进行测试了,
另外提示一下,如果OS运行异常,请检查堆栈、时钟组配置相关。
STM32F407的FreeRTOS多机通信系统设计一、引言在现代嵌入式系统设计领域,多机通信系统起到了至关重要的作用。
STM32F407是一款性能强大的微控制器,搭配FreeRTOS操作系统,能够实现高效稳定的多机通信。
本文将详细介绍如何设计一个基于STM32F407和FreeRTOS的多机通信系统。
二、系统架构设计1. 系统硬件设计- 使用STM32F407微控制器作为系统的核心控制单元。
- 添加相应的外设,如串口通信模块、网络模块等,以满足通信需求。
2. 系统软件设计- 使用FreeRTOS作为操作系统,为系统提供多任务管理和任务调度的功能。
- 利用FreeRTOS的队列机制实现不同任务之间的数据传输和同步。
- 使用适当的通信协议,如UART、SPI等,进行多机之间的通信。
三、任务设计1. 任务分配设计合理的任务分配是一个高效多机通信系统设计的关键。
根据系统需求,可以将任务分为以下几类:- 通信任务:负责与其他机器进行通信,接收和发送数据。
- 控制任务:负责系统的实时控制和调度。
- 数据处理任务:负责接收数据后的处理和分析。
- 显示任务:负责将数据显示在相应的界面上。
2. 任务实现- 每个任务可作为一个独立的FreeRTOS任务进行编写,使用任务优先级和任务挂起等机制进行任务管理。
- 使用队列进行任务间的数据传输和同步。
四、通信协议设计1. 数据帧格式- 设计合适的数据帧格式以确保数据在多机间的传输的可靠性和可解析性。
- 数据帧包括数据长度、数据类型、数据内容等字段。
2. 通信流程- 在系统启动时,各机器进行初始化,建立通信通道。
- 通过适当的通信协议进行数据的打包和解包,并完成数据的传输。
- 接收方进行数据解析和处理,并根据需要进行相应的回应或者操作。
五、系统性能评估与优化1. 性能评估- 对系统进行性能测试,包括任务切换时间、数据传输时间等指标的量化评估。
- 结合实际应用场景,对系统的可靠性、稳定性等进行评估。
STM32F103的FreeRTOS项目案例可以是一个使用FreeRTOS操作系统来管理任务的简单应用程序。
以下是一个可能的案例:一、项目需求1.使用STM32F103开发板。
2.使用Keil5作为开发环境。
3.移植FreeRTOSv10.2.1到STM32F103上。
4.创建两个任务:Task1和Task2。
5.Task1每秒打印字符"1",Task2每秒打印字符"2"。
二、项目步骤1.新建一个基于STM32F103的固件库工程。
2.复制FreeRTOSv10.2.1相关文件到工程目录,包括:o FreeRTOS\Source\include目录下的所有.h文件。
o FreeRTOS\Source\portable\RVDS\ARM_CM3下的portmacro.h文件。
o FreeRTOS\Demo\CORTEX_STM32F103_Keil下的FreeRTOSConfig.h文件。
3.配置FreeRTOSConfig.h文件,设置合适的任务堆栈大小、任务优先级等参数。
4.编写Task1和Task2的函数实现,使用无限循环打印字符。
5.在main函数中创建Task1和Task2,并开启任务调度。
三、代码示例以下是Task1和Task2的函数实现示例:c复制代码void Task1Function(void *param) {while(1) {printf("1");vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1秒}}void Task2Function(void *param) {while(1) {printf("2");vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1秒}}在main函数中创建任务并开启任务调度:c复制代码int main(void) {xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);vTaskStartScheduler(); // 开启任务调度while(1); // 防止编译器优化掉main函数}。
第8章基于STM32F107的FreeRTOS移植本章以FreeRTOS在STM32F107上的移植为主要内容,介绍移植的主要工作内容,及移植过程需要注意的事项。
8.1 概述FreeRTOS的实现主要由list.c、queue.c、croutine.c和tasks.c 4个文件组成。
list.c 是一个链表的实现,主要供给内核调度器使用;queue.c 是一个队列的实现,支持中断环境和信号量控制;croutine.c 和task.c是两种任务的组织实现。
协程(英文为croutine)是采用各任务共享同一个堆栈,使RAM的需求进一步缩小,但也正因如此,他的使用受到相对严格的限制。
而task则是传统的实现,各任务使用各自的堆栈,支持完全的抢占式调度。
FreeRTOS的主要功能可以归结为以下几点:优先级调度、相同优先级任务的轮转调度,同时可设成可剥夺内核或不可剥夺内核任务可选择是否共享堆栈(co-routines & tasks),并且没有任务数限制消息队列,二值信号量,计数信号量,递归互斥体时间管理内存管理与UC/OS-II一样,FreeRTOS在STM32的移植大致由3个文件实现,一个.h文件定义编译器相关的数据类型和中断处理的宏定义;一个.c文件实现任务的堆栈初始化、系统心跳的管理和任务切换的请求;一个.s文件实现具体的任务切换。
在本次移植中,使用的编译软件为IAR EWARM 6.3。
8.2 FreeRTOS移植8.2.1 portmacro.h头文件PORTMACRO.H头文件主要包括两部分内容。
第一部分定义了一系列内核代码中用到的数据类型。
FreeRTOS与uC/OS-II一样,并不直接使用char、int 等这些原生数据类型,而是将其重新定义为一系列以port开头的新类型。
这样的好处在于,在不同架构的处理器移植时,仅需针对处理器的位宽对这些数据类型做相应的调整,而无需繁琐地从头至尾修改源代码。
第二部分包含了实现FreeRTOS移植所需要定义的函数。
包括与架构相关的定义、内核调度、临界区管理、任务优化等。
1.数据类型定义定义编译器相关的各种数据类型。
在uC/OS-II的移植代码中,通常采用 typedef 来定义新的类型,而FreeRTOS的作者似乎更喜欢用宏定义#define。
虽然typedef和#define能够实现相同的功能,但也有细微的区别,typedef由编译器解释,而非预处理器执行,并且仅限于对数据类型进行定义。
尽管如此,typedef在其受限范围内比#define更为灵活。
下面是相应的代码片段。
#define portCHAR char#define portFLOAT float#define portDOUBLE double#define portLONG long#define portSHORT short#define portSTACK_TYPE unsigned portLONG#define portBASE_TYPE long2.架构相关的定义定义与处理器或控制器架构相关的宏定义。
条件编译中的代码是针对处理器的字长为16位,工程配置时应在FreeRTOSConfig.h中将宏定义改为“#define configUSE_16_BIT_TICKS 1”,若处理器字长为32位,宏定义为“#define configUSE_16_BIT_TICKS 0”。
宏portSTACK_GROWTH定义了堆栈的生长方向。
对于不同的嵌入式操作系统,堆栈的生长方向定义可能不同,在移植时应予以明确。
portSTACK_GROWTH定义为1表示堆栈是正向生长的,-1为逆向生长的。
一般来说堆栈都是倒生的。
Cortex-M3的堆栈增长方向为高地址向低地址增长,因此这里定义为 -1。
portTICK_RATE_MS表示的是Tick 间间隔多少ms,只在应用代码中可能会用到。
如使用vTaskDelay延时函数可实现任务定时间间隔地执行,调用方法如下。
vTaskDelay( 250 / portTICK_RATE_MS );vTaskDelay传递参数中的250表示系统使当前任务处于阻塞态,并维持250ms。
portBYTE_ALIGNMENT 在uC/OS-II 是不需要的,FreeRTOS的代码中在分配任务堆栈空间时实现SRAM访问的字节对齐。
/* SYSTEM TICK的长度。
如果是16位以下的处理器置1;如果是32位处理器,则置0。
*/ #if( configUSE_16_BIT_TICKS == 1 )16位处理器及16位以下处理器 *//*typedef unsigned portSHORT portTickType;#define portMAX_DELAY ( portTickType ) 0xffff#else/* 32位处理器 */typedef unsigned portLONG portTickType;#define portMAX_DELAY ( portTickType ) 0xffffffff#endif/* Cortex-M3的堆栈增长方向为高地址向低地址增长 */#define portSTACK_GROWTH ( -1 )/*定义心跳时钟周期,表示的是相邻Tick间间隔多少ms */#define portTICK_RATE_MS((portTickType)1000/configTICK_RATE_HZ)/* 访问SRAM的字节对齐 */#define portBYTE_ALIGNMENT 83.内核调度函数portYIELD()等同于vPortYieldFromISR()实现的是任务切换。
vPortYieldFromISR()函数在PORT.C文件中实现。
相当于 uC/OS-II中的 OS_TASK_SW()。
/* 声明该函数定义在其它文件中,实现强制上下文切换,用在任务环境中调用 */extern void vPortYieldFromISR( void );#define portYIELD() vPortYieldFromISR()/* 强制上下文切换,在中断处理环境中调用 */#define portEND_SWITCHING_ISR(xSwitchRequired) if(xSwitchRequired)\ vPortYieldFromISR()4.临界区管理函数定义临界区的管理函数。
vPortSetInterruptMask和vPortClearInterruptMask在portasm.s中定义,实现中断屏蔽位的清除或置位。
vPortEnterCritical和vPortExitCritical函数在port.c文件中定义,实现临界区的进入与退出。
而下面代码中的最后两个宏定义则是用于在中断环境的中断屏蔽和开启,即是否允许中断嵌套。
/* 声明以下4个函数在其它文件中定义,临界区的进入与退出、中断的允许和关闭 */extern void vPortEnterCritical( void );extern void vPortExitCritical( void );extern void vPortSetInterruptMask( void );extern void vPortClearInterruptMask( void );/* 中断允许和关闭 */#define portDISABLE_INTERRUPTS() vPortSetInterruptMask()#define portENABLE_INTERRUPTS() vPortClearInterruptMask()/* 临界区进入和退出 */#define portENTER_CRITICAL() vPortEnterCritical()#define portEXIT_CRITICAL() vPortExitCritical()/* 用于在中断环境的中断屏蔽和开启 */#define portSET_INTERRUPT_MASK_FROM_ISR() 0;vPortSetInterruptMask() #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) \vPortClearInterruptMask();(void)x5.任务优化函数以下两个宏定义是为了利用某些C编译器的扩展功能对任务函数进行更好的优化。
portNOP() 顾名思义就是对空操作定义了个宏。
/* 预留扩展函数,用于对任务函数的优化 */#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void \ vFunction( void *pvParameters )#define portTASK_FUNCTION( vFunction, pvParameters ) void \vFunction( void *pvParameters )/*消耗一个机器周期,用来延时或空操作*/#define portNOP()8.2.2 port.c源文件1.堆栈初始化进行堆栈的初始化,使堆栈处于预知的确定状态。
下面是堆栈初始化的代码实现,其模拟了一个由中断引起的上下文切换导致的堆栈操作序列。
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack,pdTASK_CODE pxCode,void *pvParameters ) {/* 计算存储程序状态寄存器xPSR的堆址,用于MCU在进入或退出中断时恢复现场*/pxTopOfStack--;/* 程序状态寄存器的值保存于堆栈中 */*pxTopOfStack = portINITIAL_XPSR;pxTopOfStack--;/* 任务的入口点 */*pxTopOfStack = ( portSTACK_TYPE ) pxCode;pxTopOfStack--;/* LR */*pxTopOfStack = 0;/* R12, R3, R2 and R1. */pxTopOfStack -= 5;/* 任务的参数 */*pxTopOfStack = ( portSTACK_TYPE ) pvParameters;/* R11, R10, R9, R8, R7, R6, R5 and R4. */pxTopOfStack -= 8;return pxTopOfStack;}2.启动任务调度portBASE_TYPE xPortStartScheduler( void ){/* 让任务切换中断和心跳中断位于最低的优先级,使更高优先级可以抢占MCU */*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;/* 启动定时器,开始产生系统的心跳时钟,此处中断已被关闭 */prvSetupTimerInterrupt();/* 初始化临界区的嵌套的个数,准备启动第一个任务 */uxCriticalNesting = 0;/* 启动第一个任务 */vPortStartFirstTask();/* 执行到vPortStartFirstTask函数,内核已经开始正常的调度 */return 0;}3.主动释放MCU使用权通过设置中断控制及状态寄存器触发PendSV系统服务中断,请求一次上下文切换,中断到来时由汇编函数xPortPendSVHandler()处理。