02_FreeRTOS移植

目录

获取FreeRTOS源码

 FreeRTOS源码内容

FreeRTOS内核

Demo文件夹

Source文件夹

portable文件夹

FreeRTOS移植

移植步骤

移植详解

实验源码:

获取FreeRTOS源码

FreeRTOS官网:https://www.freertos.org/

 FreeRTOS源码内容

FreeRTOS内核

 

 

Demo文件夹

Demo文件夹里面就是FreeRTOS的演示例程,如下所示:

 支持多种芯片架构,支持多种不同型号芯片,对于入门学习FreeRTOS是十分有帮助的,在学习移植FreeRTOS的过程中就可以参考这些演示工程。

 

Source文件夹

 FreeRTOS源码本尊

 

 

portable文件夹

FreeRTOS操作系统归根到底是一个软件层面的东西,那FreeRTOS是如何跟硬件联系在一起的呢?portable文件夹里面的东西就是连接桥梁

由于使用MDK开发,最后只需要一下3个文件夹

 

FreeRTOS移植

移植步骤

1.添加FreeRTOS源码,将FreeRTOS源码添加至基础工程、头文件路径等

2.FreeRTOSConfig.h,添加FreeRTOSConfig.h配置文件

3.修改SYSTEM文件,修改SYSTEM文件中的sys.c、delay.c、usart.c

4.修改中断相关文件,修改Systick中断、SVC中断、PendSV中断

5.添加应用程序,验证移植是否成功

移植详解

1.准备好一个基础例程,在基础例程里面,新建立一个FreeRTOS文件夹,并把官网下载好的FreeRTOS源码放到文件夹里。

 2.在根据具体使用情况把portable文件夹里面不需要的文件删掉,留下自己想想要的

 

 3.在基础工程中创建2个FreeRTOS文件夹,一个存放源码,一个端口文件夹,并添加文件。

 4.添加FreeRTOS所需要的头文件

 5.添加FreeRTOSConfig.h文件

FreeRTOSConfig.h 是 FreeRTOS 操作系统的配置文件, FreeRTOS 操作系统是可裁剪的,用户可以根据需求对FreeRTOS进行裁剪,裁剪掉不需要用到的FreeRTOS功能,以此来节约MCU内存资源。获取途径可以在Demo文件夹下示例复制一个。

6.修改中断相关文件

这三个函数分别为滴答定时器中断服务函数、SVC 中断服务函数和 PendSV 中断服务函数,将 stm32f10x_it.c 中的三个函数屏蔽掉,SysTick中断函数自己修改成FreeRTOS的心跳(也可以不屏蔽,直接在stm32f10x_it.cSysTick中断函数里面写,这里是在外面写了所以屏蔽掉),SCVC和PendSV在FreeRTOS里面也定义了,所以屏蔽这3个函数就是为了不重复。

 

 7.修改delay_ms()其实就是对 FreeRTOS 中的延时函数 vTaskDelay()的简单封装,所以在使用 delay_ms()的时候就会导致任务切换。

void delay_ms(u32 nms)
{	
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
	{		
		if(nms>=fac_ms)						//延时的时间大于OS的最少时间周期 
		{ 
   			vTaskDelay(nms/fac_ms);	 		//FreeRTOS延时
		}
		nms%=fac_ms;						//OS已经无法提供这么小的延时了,采用普通方式延时    
	}
	delay_us((u32)(nms*1000));				//普通方式延时
}

8.修改systick中断服务函数,FreeRTOS 的心跳就是由滴答定时器产生的,根据 FreeRTOS 的系统时钟节拍设置好滴答定 时器的周期,这样就会周期触发滴答定时器中断了。在滴答定时器中断服务函数中调用 FreeRTOS API 函数 xPortSysTickHandler()

void SysTick_Handler(void)
{	
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        xPortSysTickHandler();	
    }
}

9.延时函数修改FreeRTOS 的系统时钟是由滴答定时器提供的,那么肯定要根据 FreeRTOS 的系统时钟节拍来初始化滴答定时器了,delay_init()就是来完成这个功能的。FreeRTOS 的系统时钟节拍由宏 configTICK_RATE_HZ 来设置,这个值我们可以自由设置,但是一旦设置好以后根据这个值来初始化滴答定时器,其实就是设置FreeRTOS的心跳,通过设置systick几个时钟周期中断一次,相当于几个systick中短周期代表一个FreeRTOS心跳1次。

void delay_init()
{
	uint32_t  reload;
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟  HCLK
	fac_us=SystemCoreClock/1000000;				//不论是否使用OS,fac_us都需要使用
	reload=SystemCoreClock/1000000;				//每秒钟的计数次数 单位为M  
	reload*=1000000/configTICK_RATE_HZ;			//根据configTICK_RATE_HZ设定溢出时间
												//reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右	
	fac_ms=1000/configTICK_RATE_HZ;				//代表OS可以延时的最少单位	   

	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
	SysTick->LOAD=reload; 						//每1/configTICK_RATE_HZ秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//开启SYSTICK    
}

实验源码:

/**
  ******************************************************************************
  * @file           : user_mian.h
  * @brief          : V1.00
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdbool.h>
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"

/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*/

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);


//任务优先级
#define LED0_TASK_PRIO		2
//任务堆栈大小	
#define LED0_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);


//任务优先级
#define LED1_TASK_PRIO		3
//任务堆栈大小	
#define LED1_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);



 int main(void)
 {	

	/*配置系统中断分组为4位抢占*/
	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	 /*延时函数初始化*/
	 delay_init();
	/*RCC配置*/
	 Rcc_config();
	/*GPIO初始化*/ 
	 Gpio_Init();
	/*USART1初始化*/
	 Uart1_Init(9600);
	/*创建开始任务*/
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
		

}
 

/*!
	\brief		开始任务函数
	\param[in]	传递形参,创建任务时用户自己传入
	\param[out]	none
	\retval 	none
*/
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);         
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}


/*!
	\brief		led0_task任务函数
	\param[in]	传递形参,创建任务时用户自己传入
	\param[out]	none
	\retval 	none
*/
void led0_task(void *pvParameters)
{
    while(1)
    {
		/*进入临界去*/
		taskENTER_CRITICAL();     
		/*串口打印*/
        printf("led0_task\r\n");   
		/*退出临界区*/
        taskEXIT_CRITICAL();           
		//引脚拉低,GPIOE LED亮
		GPIO_ResetBits(GPIOE,GPIO_Pin_5);
        vTaskDelay(500);
		//引脚拉高,GPIOE LED灭		
		GPIO_SetBits(GPIOE,GPIO_Pin_5);
		vTaskDelay(500);
    }
} 


/*!
	\brief		led1_task任务函数
	\param[in]	传递形参,创建任务时用户自己传入
	\param[out]	none
	\retval 	none
*/
void led1_task(void *pvParameters)
{
    while(1)
    {
		/*进入临界去*/
		taskENTER_CRITICAL();     
		/*串口打印*/
        printf("led1_task\r\n");   
		/*退出临界区*/
        taskEXIT_CRITICAL();   
		//引脚拉低,GPIOB LED亮
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);
        vTaskDelay(100);
		//引脚拉高,GPIOB LED灭		
		GPIO_SetBits(GPIOB,GPIO_Pin_5);
		vTaskDelay(100);
    }
}

 /************************************************************** END OF FILE ****/

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeRTOS是一个开源的实时操作系统。移植FreeRTOS到特定平台可以使该平台上的应用程序能够使用FreeRTOS提供的任务调度、内存管理、同步机制等功能。根据引用和引用的内容,要在STM32F407上移植FreeRTOS,可以参考相关的移植教程和源码。 首先,你可以在FreeRTOS的官方移植工程中寻找FreeRTOSConfig.h文件,该文件是移植过程中需要的配置文件。你可以打开FreeRTOS针对STM32F103的移植工程文件,该文件夹通常命名为CORTEX_STM32F103_Keil,并找到FreeRTOSConfig.h文件。 移植FreeRTOS的步骤可以分为准备工作、移植移植验证实验。在准备工作中,你需要准备基础工程,包括设置编译环境、导入FreeRTOS文件和配置硬件等。 在移植过程中,你需要根据特定的平台和需求进行一些修改和配置,例如设置堆栈大小、任务优先级等。具体的移植过程可以参考相关的移植教程和源码。 最后,在移植验证实验中,你可以通过编写一个简单的流水灯功能的应用程序来验证FreeRTOS移植是否成功。通过该实验可以检查任务调度是否正常、内存管理是否可靠等。 总结起来,要在STM32F407上移植FreeRTOS,你可以参考相关的移植教程和源码,找到FreeRTOSConfig.h文件,并根据特定的平台和需求进行配置和修改。完成移植后,你可以通过验证实验来检查移植是否成功。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [FREERTOS移植STM32F407.rar](https://download.csdn.net/download/qq_36914987/18974026)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [FreeRTOS学习笔记【二】——FreeRTOS 移植](https://blog.csdn.net/weixin_46545987/article/details/127558188)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值