FreeRTOS基本教程零:STM32 FReeRTOS 移植流程

article/2025/4/27 1:32:17

一、资料准备

FreeRTOS源码下载地址:

https://github.com/FreeRTOS/FreeRTOShttps://github.com/FreeRTOS/FreeRTOS我移植的是FreeRTOSv9.0.0

stm32裸机程序:

二、FreeRTOS目录

 一共有三个文件夹

其中Demo文件夹中是FreeRTOS的例程,License文件夹是与FreeRTOS相关的许可信息,Source是FreeRTOS的源码。

 include文件夹是移植需要的头文件,下面的croutine.c等C文件是FreeRTOS的源码文件,移植时需要。Protable文件夹是将软件(FreeRTOS)与硬件(不同MCU)连接的文件,

我们使用的Keil平台,硬件为stm32f103,属于CM3内核。

所以我们需要Keil文件夹,而文件夹中的See-also-the-RVDS-directory.txt提示参考RVDS,我们选用RVDS/ARM_CM3文件夹的文件。

MemMang是与内存管理相关关的,移植时是需要的。

 FreeRTOS-Plus文件夹不是源码,是在源码上加了一些功能的代码。

二、移植

2.1 文件的添加

将FreeRTOS文件夹添加到工程文件夹中,保留License和Demo文件夹保留,将其他文件删除,License文件夹与FreeRTOS相关的许可信息,要做产品的需要注意,这里作为学习,所以未做详细介绍。

Source\portable中只保留Keil、MemMang、RVDS文件夹,其他文件夹均删除。

RVDS文件夹中只保留ARM_CM3文件夹,其他均删除。

打开工程,新建FreeRTOS_CORE和FreeRTOS_PROTABLE两个分组

 将源文件添加到这两个分组中,如下图所示:

将文件路径添加到工程里

 添加完之后,进行编译。

 报错:..\FreeRTOS\Source\include\FreeRTOS.h(98): error:  #5: cannot open source input file "FreeRTOSConfig.h": No such file or directory

表示找不到FreeRTOSConfig.h,我们从官方移植好的工程拷贝到include文件夹中,用于系统的裁剪和配置功能,为系统的配置文件。

2.2 文件修改

再编译:

 将stm32f10x_it.c文件中的 SVC_Handler 和 PendSV_Handler 屏蔽掉,再编译编译通过。

修改sys.h文件

//0,不支持ucos
//1,支持ucos
#define SYSTEM_SUPPORT_OS		0		//定义系统文件夹是否支持UCOS

修改为

//0,不支持ucos
//1,支持ucos
#define SYSTEM_SUPPORT_OS		1		//定义系统文件夹是否支持UCOS

修改usart.c

 将

//如果需要使用OS,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif

修改为

//如果需要使用OS,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"					//ucos 使用	  
#endif

删除

#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntEnter();    
#endif#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntExit();  											 
#endif

修改delay.c修改比较大,最终为

#include "delay.h"
// 	 
//如果需要使用OS,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"					//FreeRTOS使用		  
#include "task.h"
#endifstatic u8  fac_us=0;							//us延时倍乘数			   
static u16 fac_ms=0;							//ms延时倍乘数,在ucos下,代表每个节拍的ms数extern void xPortSysTickHandler(void);//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行{xPortSysTickHandler();	}
}//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init()
{u32 reload;SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟  HCLKfac_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    
}								    //延时nus
//nus:要延时的us数.	
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)	    								   
void delay_us(u32 nus)
{		u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD;				//LOAD的值	    	 ticks=nus*fac_us; 						//需要的节拍数 told=SysTick->VAL;        				//刚进入时的计数器值while(1){tnow=SysTick->VAL;	if(tnow!=told){	    if(tnow<told)tcnt+=told-tnow;	//这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told;	    told=tnow;if(tcnt>=ticks)break;			//时间超过/等于要延迟的时间,则退出.}  }										    
}  
//延时nms
//nms:要延时的ms数
//nms:0~65535
void delay_ms(u16 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));				//普通方式延时
}//延时nms,不会引起任务调度
//nms:要延时的ms数
void delay_xms(u32 nms)
{u32 i;for(i=0;i<nms;i++) delay_us(1000);
}

编译报错:

..\OBJ\LED.axf: Error: L6200E: Symbol SysTick_Handler multiply defined (by delay.o and stm32f10x_it.o).

 将stm32f10x_it.c文件中的 SysTick_Handler 屏蔽掉,编译通过,stm32f10x_it.c最终如下

 2.3 测试

//main.c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "FreeRTOS.h"
#include "task.h"
/************************************************ALIENTEK Mini STM32F103开发板 FreeRTOS实验2-1FreeRTOS移植实验-库函数版本技术支持:www.openedv.com淘宝店铺:http://eboard.taobao.com 关注微信公众平台微信号:"正点原子",免费获取STM32资料。广州市星翼电子科技有限公司  作者:正点原子 @ALIENTEK
************************************************///任务优先级
#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       //50*4个字节 = 200字节    含寄存器和任务的变量
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 	 delay_init();	    				//延时函数初始化	  uart_init(115200);					//初始化串口LED_Init();		  					//初始化LED//创建开始任务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();          //开启任务调度
}//开始任务任务函数
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();            //退出临界区
}//LED0任务函数 
void led0_task(void *pvParameters)
{while(1){LED0=~LED0;vTaskDelay(500);}
}   //LED1任务函数
void led1_task(void *pvParameters)
{while(1){LED1=0;vTaskDelay(200);LED1=1;vTaskDelay(800);}
}


http://chatgpt.dhexx.cn/article/52OQCj6Q.shtml

相关文章

基于STM32的实时操作系统FreeRTOS移植教程(手动移植)

前言&#xff1a;此文为笔者FreeRTOS专栏下的第一篇基础性教学文章&#xff0c;其主要目的为&#xff1a;帮助读者朋友快速搭建出属于自己的公版FreeRTOS系统&#xff0c;实现后续在实时操作系统FreeRTOS上的开发与运用。操作系统的学习与运用可以说是每位嵌入式开发工程师必须…

STM32F103--移植FreeRTOS完整教程

最近按照正点原子教程开始学习FreeRTOS&#xff0c;发现其手册的移植教程中有些地方可能不是那么详细&#xff0c;在此基于正点原子做一期最完整的FreeRTOS移植教程给大家。 小b将本次教程整理的资料放在网盘&#xff0c;以下链接供各位小伙伴下载和学习&#xff1a; 链接&…

FreeRTOS 正点原子教程学习笔记

正点原子视频教程 FreeRTOS(教程非常详细&#xff09; 小知识 如果创建了任务却完全空着&#xff0c;没有while&#xff08;1&#xff09;{延时}的话&#xff0c;整个程序会卡住&#xff0c;其他正常的任务无法运行。如果任务里单单有赋值之类的操作也会卡死在这个任务&#…

FreeRTOS入门教程(堆和栈)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、FreeRTOS操作系统介绍二、堆1.概念介绍2.简单实现 三、栈总结 前言 本篇文章正式学习FreeRTOS操作系统&#xff0c;我打算编写一系列文章带大家轻松快速入…

FreeRTOS移植到STM32

一、找一个STM32的裸机工程模板 我们以STM32F103裸机程序为例 随便找的一个裸机程序 二、去官网上下载FreeRTOS V9.0.0 源码 在移植之前&#xff0c;我们首先要获取到 FreeRTOS 的官方的源码包。这里我们提供两个下载 链 接 &#xff0c; 一 个 是 官 网 &#xff1a; http:…

韦东山freeRTOS系列教程之【第一章】FreeRTOS概述与体验

文章目录 教程目录1.1 FreeRTOS目录结构1.1 FreeRTOS目录结构1.2 核心文件1.3 移植时涉及的文件1.4 头文件相关1.4.1 头文件目录1.4.2 头文件 1.5 内存管理1.6 Demo1.7 数据类型和编程规范1.7.1 数据类型1.7.2 变量名1.7.3 函数名1.7.4 宏的名 1.8 安装Keil1.8.1 下载Keil1.8.2…

freeRTOS中文实用教程1

资料转载出处 https://www.cnblogs.com/smartjourneys/p/7073450.html 1.前言 FreeRTOS是小型多任务嵌入式操作系统&#xff0c;硬实时性。本章主要讲述任务相关特性及调度相关的知识。 任务的总体特点 任务的状态 &#xff08;1&#xff09;任务有两个状态&#xff0c;运行态…

FreeRTOS入门

目录 一、简介 二、堆的概念 三、栈的概念 四、从官方源码中精简出第一个FreeRTOS程序 五、修改官方源码增加串口打印 一、简介 FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统&#xff0c;功能包括&#xff1a;任务管理、时间管理、信号量、消息队列、…

freeRTOS系列教程之【第一章】FreeRTOS概述与体验

文章目录 教程目录1.1 FreeRTOS目录结构1.1 FreeRTOS目录结构1.2 核心文件1.3 移植时涉及的文件1.4 头文件相关 1.4.1 头文件目录1.4.2 头文件 1.5 内存管理1.6 Demo1.7 数据类型和编程规范 1.7.1 数据类型1.7.2 变量名1.7.3 函数名1.7.4 宏的名 1.8 安装Keil 1.8.1 下载Keil1.…

【机器学习】3-4-2 流行学习

#3-4-2流行学习 import mglearn import numpy as np import matplotlib.pyplot as plt import pandas as pd from sklearn.datasets import load_breast_cancer from sklearn.datasets import make_moons from sklearn.datasets import make_blobs from sklearn.datasets impor…

【机器学习】(十八)用t-SNE进行流行学习:手写数字分类

PCA是用于变换数据的首选方法&#xff0c;也可以进行可视化&#xff0c;但它的性质&#xff08;先旋转然后减少方向&#xff09;限制了有效性。 流行学习算法&#xff1a;是一类用于可视化的算法&#xff0c;它允许进行更复杂的映射&#xff0c;通常也可以给出更好的可视化。t-…

用Python实现流行机器学习算法

对于此库的Octave/MatLab版本&#xff0c;请检查machine-learning-octave项目。 该库包含在Python中实现的流行机器学习算法的示例&#xff0c;其中包含数学背后的解释。 每个算法都有交互式Jupyter Notebook演示&#xff0c;允许您使用训练数据&#xff0c;算法配置&#xff0…

【流行学习】局部线性嵌入(Locally Linear Embedding)

一、前言 局部线性嵌入&#xff08;LLE&#xff09;假设数据在较小的局部是线性的&#xff0c;也就是说&#xff0c;某一个样本可以由它最近邻的几个样本线性表示&#xff0c;离样本远的样本对局部的线性关系没有影响&#xff0c;因此相比等距映射算法&#xff0c;降维的时间复…

流行-Manifold学习理解与应用

流行-Manifold【1】 流形&#xff0c;也就是 Manifold 。 1. 比较好的形象理解 流形学习的观点是认为&#xff0c;我们所能观察到的数据实际上是由一个低维流形映射到高维空间上的&#xff0c;即这些数据所在的空间是“嵌入在高维空间的低维流形。”。由于数据内部特征的限制&a…

【流行学习】拉普拉斯映射(Laplacian Eigenmaps)

一、前言 拉普拉斯特征映射是一种基于图的降维算法&#xff0c;它希望在原空间中相互间有相似关系的点&#xff0c;在降维后的空间中尽可能的靠近&#xff0c;从而在降维后仍能保持原有的数据结构信息。 二、主要步骤 拉普拉斯特征映射通过构建邻接矩阵为 W W W&#xff08;…

7个流行的强化学习算法及代码实现

目前流行的强化学习算法包括 Q-learning、SARSA、DDPG、A2C、PPO、DQN 和 TRPO。 这些算法已被用于在游戏、机器人和决策制定等各种应用中&#xff0c;并且这些流行的算法还在不断发展和改进&#xff0c;本文我们将对其做一个简单的介绍。 1、Q-learning Q-learning&#xff1…

流行学习,比较好的一篇博客

转载自&#xff1a;https://blog.csdn.net/sinat_32043495/article/details/78997758 嵌入在高维空间的低维流形 流形&#xff1a;局部具有欧几里得空间性质的空间 1.较好的描述转载 作者&#xff1a;暮暮迷了路 链接&#xff1a;https://www.zhihu.com/question/2401548…

深度学习—近年来流行的卷积神经网络(一)

近年来流行的卷积神经网络 1. 回顾与目标2. 近年来流行的卷积神经网络2.1 VGGNet2.1.1 感受野的概念2.1.2 感受野的计算 2.2 GooleNet2.3 ResNet 3. 结尾参考资料 1. 回顾与目标 前面几讲&#xff0c;我们以LeNet和AlexNet为例&#xff0c;详细讲解了卷积神经网络的结构。从20…

流行学习常用算法

Isomap&#xff1a;等距映射。前提假设为低维空间中的欧式距离等于高维空间中的侧地线距离&#xff0c;当然该算法具体实施时是高维空间中较近点之间的测地线距离用欧式距离代替&#xff0c;较远点距离用测地线距离用最短路径逼近。 LLE:局部线性嵌入。前提假设是数据所在的低维…

流行学习与拉普拉斯变换的推导

参考&#xff1a;拉普拉斯矩阵 参考&#xff1a;流行学习