赞
踩
FreeRTOS实时操作系统移植到STM32平台的优点
(1)FreeRTOS是一个实时操作系统,提供了可预测的任务调度和响应时间。这对于需要实时性能的应用程序至关重要。
(2)FreeRTOS允许您在STM32上同时运行多个任务,这些任务可以并行执行。可以更好地组织和管理代码,提高系统的模块化和可维护性。
(3)FreeRTOS提供了任务、队列、信号量等机制,使操作人员更有效地管理STM32的资源。可以防止资源竞争和死锁等常见问题,提高系统的稳定性和可靠性。
上述众多优点表明,移植可以给STM32平台提供可靠的实时性能、多任务支持和资源管理。
实时操作系统(RTOS)是一种专为实时应用程序设计的操作系统,它能够确保任务在特定的时间约束内完成,并提供可预测的响应时间。RTOS 通常用于嵌入式系统,其中任务的时间敏感性非常重要。实时操作系统分为硬实时和软实时两种类型,硬实时要求任务必须在规定的时间内完成,而软实时则允许偶尔的任务延迟。
FreeRTOS 是一个流行的实时操作系统,专为嵌入式系统设计。它提供了轻量级的内核,适用于资源有限的设备,并具有高度可移植性。FreeRTOS 的内核提供了任务调度、信号量、消息队列等基本功能,同时也支持实时内存管理和软件定时器等扩展功能。
FreeRTOS 是一个流行的实时操作系统,专为嵌入式系统设计。它提供了轻量级的内核,适用于资源有限的设备,并具有高度可移植性。FreeRTOS 的内核提供了任务调度、信号量、消息队列等基本功能,同时也支持实时内存管理和软件定时器等扩展功能。
a、FreeRTOS 使用基于优先级的抢占式调度算法。每个任务都有一个优先级,并且具有最高优先级的任务将始终运行,直到它阻塞、让出 CPU,或者被更高优先级的任务抢占。这种调度算法确保了高优先级任务的及时响应,同时也允许低优先级任务在必要时执行。
b、当任务被阻塞时,调度器会选择下一个最高优先级的就绪任务来执行。这种方式实现了任务之间的并发执行,从而提供了多任务操作系统的功能。任务的状态转换由任务调度器负责管理,确保任务的执行顺序符合预期。
FreeRTOS移植首先需要从官网下载FreeRTOS数据包,对于一下多余的文件进行删除,仅使用所需文件,减少内存使用,官网链接如下。FreeRTOS - Free RTOS Source Code Downloads, the official FreeRTOS zip file release download
从官网下载得到的FreeRTOS数据包,需要进行解压,以Keil工具下STM32F103芯片为例,解压之后,它的FreeRTOS的目录如下:
(1)可以获得一个内核文件Source,也就是源代码文件,里面包含了include、portable等文件夹,还有task.c-用于任务操作文件,list.c-用于使用列表,queue-用于使用对列以及信号量操作。portable文件夹里包含RVDS文件-可以选择架构、MemMang文件-用于内存管理。
(2)还有一个Demo文件,里面包含了一个STM32F103的工程实例,CORTEX_STM32F103_Keil,已经移植完成的,里面包含一个FreeRTOSConfig.h配置文件,移植时也会用到。
(1)经过解压之后,就可以进行复制所需文件,首先在自己需要移植的项目文件中创建一个FreeRTOS文件目录,然后需要将解压之后的内核文件Source中的7个.c文件和include、portable文件复制到该文件夹下,如下图所示。
(2)对于portable文件夹下,仅保留MemMang和RVDS文件夹,其中MemMang里有5个内存管理模块,heap_1.c至heap_5.c五个文件,其中heap_4.c可以动态分配内存,使相邻空间内存合并处理,其余内存删除,解决了碎片化问题。因此,仅保留heap_4.c文件。对于RVDS文件夹,保留需要的ARM系列即可,仅保留ARM-CM3即可。
(1)在项目文件中创建分组文件,都是属于FreeRTOS的,一个是Source文件用于存放源文件,一个是other文件用于存放heap_4.c和port.c文件,port.c文件在ARM_CM3中,如图所示
(2)接下来就是如何操作,导入这些文件,以Keil软件为例,下图是导入文件的步骤。
(3)导入文件之后,需要包含各文件的头文件,如下图所示,按照步骤操作即可。
此时直接编译之后,将会报错,主要是因为缺少配置文件FreeRTOSConfig.h
在解压之后的工程实例CORTEX_STM32F103_Keil,包含一个FreeRTOSConfig.h配置文件,需要将其添加到FreeRTOS文件夹下,并在USER文件夹中添加该.h文件,然后包含头文件FreeRTOS,因为这是放在该文件夹中,添加步骤与上述一致。
此时直接编译之后,不会出现错误 !
此时虽然运行之后,并没有出现编译错误,但是还有一些与中断有关的重要函数需要修改,在FreeRTOSConfig.h添加① #define xPortPendSVHandler ② #define xPortSysTickHandler,③ #define vPortSVCHandler三个宏定义,这三个分别对应 PendSV_Handler-用于出发任务切换操作,SysTick_Handler-用于实现定时功能,SVC_Handler-用于实现系统用调用三个中断函数,当运行之后,会出现函数重定义错误,因为在stm32f10x_it.c文件中已经包含了这三个函数,需要进行删除如下图所示。
注意:一般经过上面修改之后,就相当于移植成功,可以直接使用了,但是,有的可能并没有实现自己需要的功能,因为上面的中断函数有一些小问题。可以通过下面方法进行改进。
上述的三个宏定义中①和③可以直接使用port.c中自带的中断函数,其实上面的原理就是使用的port.c自带的函数,此时但是运行结果并不理想,可以采用自定义第②个函数的方式解决这个问题,具体代码如下。就是在stm32f10x_it.c文件中的函数里自动修改即可。
这样便可以实现程序正常运行。
- extern void xPortSysTickHandler(void);
-
- //systick中断服务函数
- void SysTick_Handler(void)
- {
- #if (INCLUDE_xTaskGetSchedulerState == 1 )
- if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
- {
- #endif /* INCLUDE_xTaskGetSchedulerState */
- xPortSysTickHandler();
- #if (INCLUDE_xTaskGetSchedulerState == 1 )
- }
- #endif /* INCLUDE_xTaskGetSchedulerState */
- }
通过上述步骤之后,便可以使用实时操作系统(FreeRTOS)实现多任务运行,下面代码适用于实现LED灯循环执行的两个任务,可以将程序烧录到开发板查看效果。
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "LED.h"
-
- #include "FreeRTOS.h"
- #include "task.h"
- #include "queue.h" // 使用队列的头文件
- #include "stdio.h" // c函数标准库的头文件
-
- int task1flagrun = 0;
- int task2flagrun = 0;
-
- void vTask1(void *pvParameters)
- {
- for(;;)
- {
- task1flagrun = 1;
- task2flagrun = 0;
- GPIO_SetBits(GPIOA,GPIO_Pin_1);
- vTaskDelay(1000);
- GPIO_ResetBits(GPIOA,GPIO_Pin_1);
- vTaskDelay(1000);
-
- }
- }
-
- void vTask2(void *pvParameters)
- {
- for(;;)
- {
- task1flagrun = 0;
- task2flagrun = 1;
- GPIO_ResetBits(GPIOB,GPIO_Pin_1);
- vTaskDelay(500);
- GPIO_SetBits(GPIOB,GPIO_Pin_1);
- vTaskDelay(500);
- }
- }
-
-
-
- int main(void){
-
-
- LED_Init();
-
-
-
- xTaskCreate(vTask1,"LED1",128,NULL,1,NULL);
- xTaskCreate(vTask2,"LED2",128,NULL,1,NULL);
-
- //启动任务调度器
- vTaskStartScheduler();
-
- // 4、设置低电平,LED灯亮起
- // GPIO_ResetBits(GPIOA,GPIO_Pin_1);
- // 5、也可以GPIO_WriteBit()函数设置高低电平
- // 前两个参数和Set和Reset一样,第三个参数用于清除端口值,和设置端口值
- // 如果参数=Bit_RESET,清除端口值,设置为低电平,灯亮;反之参数=Bit_SET,为高电平,灯灭
- // GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
-
- // 6、若是需要实现LED灯闪烁的命令,就需要在While死循环中进行一些设置
- while(1){
- // 点亮 两个函数都可以
- // GPIO_ResetBits(GPIOA,GPIO_Pin_0);
- // Delay_ms(500); // 延时函数直接调用即可
- // GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
- // GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0); // 0为低电平
- // 7、这里加延时函数
- // Delay_ms(500);
-
- // 熄灭
- // GPIO_SetBits(GPIOA,GPIO_Pin_0);
- // Delay_ms(500);
- // GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET); 如果这里想要直接使用自己定义的参数代替第三个参数,
- // GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1); // 1为高电平
- // (BitAction)0 需要加
-
- // Delay_ms(500);
-
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。