STM32移植FreeRTOS操作系统

news/2024/11/9 4:57:14/

一、FreeRTOS源码下载

(1)移植钱得准备前菜对吧,我们先来去官网瞄一瞄

网址:https://freertos.org/zh-cn-cmn-s/

第一步:点击下载FreeRTOS

第二步:选择版本下载(我选择稳定版本)

注:我们下载的稳定版本不包含DEMO例程,可以自己下载上面的那个最新版本,有官方移植好的DEMO,那么最新版本下载过程如下图:

但是,这时候下载完成的压缩波其实并不包含FreeRTOS的子模块。所以,在该页面向下翻找。

第三步:回到我们下载稳定版本的路上,选择GitHub,复制网址可

到这里前菜算是准备完毕了。

二、添加内核文件

第一步:准备一个STM32工程,这里工程越简洁越好(可以参考之前写的创建工程理论与实践偏:

https://blog.csdn.net/qq_38295600/article/details/129372829

https://blog.csdn.net/qq_38295600/article/details/129372829)

第二步:准备好工程后,创建一个FreeRTOS文件夹

第三步:打开刚才下载好的稳定版本文件,路径:FreeRTOS-LTS\FreeRTOS\FreeRTOS-Kernel将里面内容复制出来

第四步:将内容粘贴到工程中得FreeRTOS文件中

为了简洁好看,我们在创建个source文件夹把这些.c文件放到这里面

外部这些文件有删除或者留着看自己

现在FreeRTOS源码被我们分成了三个目录,分别是①include目录;②portable目录;③source目录

这里 分析一下 FreeRTOS源码结构,①和③包含的是FreeRTOS核心功能源文件及头文件 .c和.h,这两部分的文件试用于各种编译器和处理器,是通用的,基本不需要修改,②为需要移植修改的目录,这与编译器和所使用的CPU有关,属于RTOS硬件接口层。

我们知道 FreeRTOS 是个系统,归根结底就是个纯软件的东西,它是怎么和硬件

联系在一起的呢?软件到硬件中间必须有一个桥梁,portable 文件夹里面的东西就是 FreeRTOS

系统和具体的硬件之间的连接桥梁!不同的编译环境,不同的 MCU,其桥梁应该是不同的,打

开 portable 文件夹,我们现在用的MDK,所以我们只需要

最终保留如下这三个文件

第五步:文件添加到工程

注:MemMang 是跟内存管理相关的,里面有 5 个 c 文件:heap_1.c、heap_2.c、heap_3.c、heap_4.c 和 heap_5.c。

这 5 个 c 文件是五种不同的内存管理方法,就像从北京到上海你可以坐火车、坐飞机,如果心情好的话也可以走路,反正有很多种方法,只要能到上海就行。这里也一样的,这 5 个文件都可以用来作为FreeRTOS 的内存管理文件,只是它们的实现原理不同,各有利弊。这里我们选择 heap_4.c,具体可以看看原子的讲解内存视频。

然后由于我用的是stm32f1内核是M3,所以选择如下

第六步:编译工程

直接编译(出现9个错误)这是因为缺少 FreeRTOSConfig.h 文件

FreeRTOS的裁剪主要依靠FreeRTOSConfig.h中的宏定义去完成,需要什么功能就打开对应的宏就可以了。

现在我们需要一个FreeRTOSConfig.h文件。但在源码FreeRTOS-Kernel目录下没有提供config文件。

那么哪里找呢?

我们打开最开始下载好的FreeRTOS文件(最开始下载我们下载了三个文件)

打开第一个FreeRTOS->路径:FreeRTOS\FreeRTOS\Demo

在demo目录下找到对应内核目录下的demo(可能是其它MCU,不要紧)拷贝一个FreeRTOSConfig.h文件到本地source\FreeRTOS\include目录内

重新编译没有错

三、修改工程

虽然没有错误了,但是我们的移植没有完成,还有一些小步骤需要完成,的确有些繁琐,好在逻辑性还是比较强的,理解起来相对容易。

第一步:

在FreeRTOSConfig.h中添加#define xPortPendSVHandler PendSV_Handler

在FreeRTOSConfig.h中添加#define vPortSVCHandler SVC_Handler

编译,还是报错,重复定义

第二步:处理错误: 进入对应的文件stm32f1xx_it.c屏蔽重复的3个函数

把SysTick_Handler也屏蔽起来是因为,等下我们要建立一个Bsp_SysTick.c,到时候这个中断函数也会放在这里面,所以我在这里也给他屏蔽了

重新编译

到这里,算移植成功了!!!,后面还需要做配置操作

四、滴答时钟配置

SysTick中断服务函数是一个非常重要的函数,FreeRTOS所有跟时间相关的事情都在里面处理,SysTick就是FreeRTOS的一个心跳时钟,驱动着FreeRTOS的运行,如果FreeRTOS没有了心跳,那么它就会卡死在某个地方,不能进行任务调度,不能运行任何的东西,因此我们需要实现一个FreeRTOS的心跳时钟

所以我们创建一个

BSP_SysTick.h 和一个BSP_SysTick.c

.c直接上代码块:

#include "BSP_SysTick.h"
#include "FreeRTOS.h"
#include "task.h"
static 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);//选择外部时钟  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    
}

.h代码块

#ifndef _BSP_SYSTICK_H
#define _BSP_SYSTICK_H
#include "stm32f10x.h"
#include "stdio.h"//0,不支持os
//1,支持os
#define SYSTEM_SUPPORT_OS        1        //定义系统文件夹是否支持OSvoid BSP_SysTickInit(void);#endif

然后我们编译下:成功报错,说明还有问题

这里显示“xTaskGetSchedulerState”这个找不到,可是我们明明声明了头文件

#include "FreeRTOS.h"//FreeRTOS使用

#include "task.h"

这两个,还是报错,那么经过查找关键点在于“FreeRTOSCongfig.h”的配置

新增上这一句,编译就通过了

那么说明一个问题,我们的FreeRTOSCongfig.h配置不完善,得改良,早这里先引用原子的配置,我们先以这个配置进行更新,后面在专门写一篇关于FreeRTOSCongfig.h的功能介绍

更新“FreeRTOSCongfig.h”

/*FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.All rights reservedVISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.This file is part of the FreeRTOS distribution.FreeRTOS is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License (version 2) as published by theFree Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.***************************************************************************>>!   NOTE: The modification to the GPL is included to allow you to     !<<>>!   distribute a combined work that includes FreeRTOS without being   !<<>>!   obliged to provide the source code for proprietary components     !<<>>!   outside of the FreeRTOS kernel.                                   !<<***************************************************************************FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE.  Full license text is available on the followinglink: http://www.freertos.org/a00114.html****************************************************************************                                                                       **    FreeRTOS provides completely free yet professionally developed,    **    robust, strictly quality controlled, supported, and cross          **    platform software that is more than just the market leader, it     **    is the industry's de facto standard.                               **                                                                       **    Help yourself get started quickly while simultaneously helping     **    to support the FreeRTOS project by purchasing a FreeRTOS           **    tutorial book, reference manual, or both:                          **    http://www.FreeRTOS.org/Documentation                              **                                                                       ****************************************************************************http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by readingthe FAQ page "My application does not run, what could be wrong?".  Have youdefined configASSERT()?http://www.FreeRTOS.org/support - In return for receiving this top qualityembedded software for free we request you assist our global community byparticipating in the support forum.http://www.FreeRTOS.org/training - Investing in training allows your team tobe as productive as possible as early as possible.  Now you can receiveFreeRTOS training directly from Richard Barry, CEO of Real Time EngineersLtd, and the world's leading authority on the world's leading RTOS.http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,including FreeRTOS+Trace - an indispensable productivity tool, a DOScompatible FAT file system, and our tiny thread aware UDP/IP stack.http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to HighIntegrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOSlicenses offer ticketed support, indemnification and commercial middleware.http://www.SafeRTOS.com - High Integrity Systems also provide a safetyengineered and independently SIL3 certified version for use in safety andmission critical applications that require provable dependability.1 tab == 4 spaces!
*/#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H#include "BSP_Uart.h"      
//针对不同的编译器调用不同的stdint.h文件
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)#include <stdint.h>extern uint32_t SystemCoreClock;
#endif//断言
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)/***************************************************************************************************************/
/*                                        FreeRTOS基础配置配置选项                                              */
/***************************************************************************************************************/
#define configUSE_PREEMPTION                    1                       //1使用抢占式内核,0使用协程
#define configUSE_TIME_SLICING                    1                        //1使能时间片调度(默认式使能的)
#define configUSE_PORT_OPTIMISED_TASK_SELECTION    1                       //1启用特殊方法来选择下一个要运行的任务//一般是硬件计算前导零指令,如果所使用的//MCU没有这些硬件指令的话此宏应该设置为0!
#define configUSE_TICKLESS_IDLE                    0                       //1启用低功耗tickless模式
#define configUSE_QUEUE_SETS                    1                       //为1时启用队列
#define configCPU_CLOCK_HZ                        (SystemCoreClock)       //CPU频率
#define configTICK_RATE_HZ                        (1000)                  //时钟节拍频率,这里设置为1000,周期就是1ms
#define configMAX_PRIORITIES                    (32)                    //可使用的最大优先级
#define configMINIMAL_STACK_SIZE                ((unsigned short)130)   //空闲任务使用的堆栈大小
#define configMAX_TASK_NAME_LEN                    (16)                    //任务名字字符串长度#define configUSE_16_BIT_TICKS                    0                       //系统节拍计数器变量数据类型,//1表示为16位无符号整形,0表示为32位无符号整形
#define configIDLE_SHOULD_YIELD                    1                       //为1时空闲任务放弃CPU使用权给其他同优先级的用户任务
#define configUSE_TASK_NOTIFICATIONS            1                       //为1时开启任务通知功能,默认开启
#define configUSE_MUTEXES                        1                       //为1时使用互斥信号量
#define configQUEUE_REGISTRY_SIZE                8                       //不为0时表示启用队列记录,具体的值是可以//记录的队列和信号量最大数目。
#define configCHECK_FOR_STACK_OVERFLOW            0                       //大于0时启用堆栈溢出检测功能,如果使用此功能//用户必须提供一个栈溢出钩子函数,如果使用的话//此值可以为1或者2,因为有两种栈溢出检测方法。
#define configUSE_RECURSIVE_MUTEXES                1                       //为1时使用递归互斥信号量
#define configUSE_MALLOC_FAILED_HOOK            0                       //1使用内存申请失败钩子函数
#define configUSE_APPLICATION_TASK_TAG            0                       
#define configUSE_COUNTING_SEMAPHORES            1                       //为1时使用计数信号量/***************************************************************************************************************/
/*                                FreeRTOS与内存申请有关配置选项                                                */
/***************************************************************************************************************/
#define configSUPPORT_DYNAMIC_ALLOCATION        1                       //支持动态内存申请
#define configTOTAL_HEAP_SIZE                    ((size_t)(20*1024))     //系统所有总的堆大小/***************************************************************************************************************/
/*                                FreeRTOS与钩子函数有关的配置选项                                              */
/***************************************************************************************************************/
#define configUSE_IDLE_HOOK                        0                       //1,使用空闲钩子;0,不使用
#define configUSE_TICK_HOOK                        0                       //1,使用时间片钩子;0,不使用/***************************************************************************************************************/
/*                                FreeRTOS与运行时间和任务状态收集有关的配置选项                                 */
/***************************************************************************************************************/
#define configGENERATE_RUN_TIME_STATS            0                       //为1时启用运行时间统计功能
#define configUSE_TRACE_FACILITY                1                       //为1启用可视化跟踪调试
#define configUSE_STATS_FORMATTING_FUNCTIONS    1                       //与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数//prvWriteNameToBuffer(),vTaskList(),//vTaskGetRunTimeStats()/***************************************************************************************************************/
/*                                FreeRTOS与协程有关的配置选项                                                  */
/***************************************************************************************************************/
#define configUSE_CO_ROUTINES                     0                       //为1时启用协程,启用协程以后必须添加文件croutine.c
#define configMAX_CO_ROUTINE_PRIORITIES         ( 2 )                   //协程的有效优先级数目/***************************************************************************************************************/
/*                                FreeRTOS与软件定时器有关的配置选项                                            */
/***************************************************************************************************************/
#define configUSE_TIMERS                        1                               //为1时启用软件定时器
#define configTIMER_TASK_PRIORITY                (configMAX_PRIORITIES-1)        //软件定时器优先级
#define configTIMER_QUEUE_LENGTH                5                               //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH            (configMINIMAL_STACK_SIZE*2)    //软件定时器任务堆栈大小/***************************************************************************************************************/
/*                                FreeRTOS可选函数配置选项                                                      */
/***************************************************************************************************************/
#define INCLUDE_xTaskGetSchedulerState          1                       
#define INCLUDE_vTaskPrioritySet                1
#define INCLUDE_uxTaskPriorityGet                1
#define INCLUDE_vTaskDelete                        1
#define INCLUDE_vTaskCleanUpResources            1
#define INCLUDE_vTaskSuspend                    1
#define INCLUDE_vTaskDelayUntil                    1
#define INCLUDE_vTaskDelay                        1
#define INCLUDE_eTaskGetState                    1
#define INCLUDE_xTimerPendFunctionCall            1/***************************************************************************************************************/
/*                                FreeRTOS与中断有关的配置选项                                                  */
/***************************************************************************************************************/
#ifdef __NVIC_PRIO_BITS#define configPRIO_BITS               __NVIC_PRIO_BITS
#else#define configPRIO_BITS               4                  
#endif#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY            15                      //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5                       //系统可管理的最高中断优先级
#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )/***************************************************************************************************************/
/*                            移植添加的,FreeRTOS与中断服务函数有关的配置选项                                  */
/***************************************************************************************************************/
#define xPortPendSVHandler     PendSV_Handler
#define vPortSVCHandler     SVC_Handler#endif /* FREERTOS_CONFIG_H */

到这里我们总体的移植算是完成了!

五、创建任务,点灯实验启动

上代码块:

#include "main.h"
#include "BSP_SysTick.h"    
#include "BSP_Gpio.h"
#include "BSP_Uart.h"     
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"#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);    //任务函数void BoardInit(void)
{BSP_SysTickInit();BSP_GpioInit();BSP_UartInit(115200);
}//开始任务任务函数
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();            //退出临界区
}int main(void)
{    
//  BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */BoardInit();printf("Welcome to FreeRTOS,CoreClock:%d\r\n",SystemCoreClock);//创建开始任务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();                                                     //开启任务调度   
}//LED0任务函数 
void led0_task(void *pvParameters)
{while(1){BSP_SetLed0(2);vTaskDelay(500);}
}   //LED1任务函数
void led1_task(void *pvParameters)
{while(1){BSP_SetLed1(2);vTaskDelay(800);}
}

编译完成

可以看到输出信息正常,同时开发板指示灯在循环闪烁

到此整个FreeRTOS移植完成!!!

六、附录:完整的工程代码

链接:https://pan.baidu.com/s/1DDstmG_wbpAjl8WUP2SxiQ

提取码:c518


http://www.ppmy.cn/news/31125.html

相关文章

Java进阶(下篇2)

Java进阶&#xff08;下篇2&#xff09;一、IO流01.File类的使用1.1、File类的实例化1.2、File类的常用方法11.3、File类的常用方法21.4、课后练习02、IO流原理及流的分类2.1、IO流原理2.2、流的分类2.3、IO 流体系03、节点流(或文件流)3.1、FileReader读入数据的基本操作3.2、…

ESLint、Prettier插件的安装与使用

在统一代码风格这一块&#xff0c;通常大家都会用到ESLint。虽然 ESLint 本身具备自动格式化代码的功能&#xff0c;但ESLint 的主要优势在于代码的风格检查并给出提示&#xff0c;而在代码格式化这一块 Prettier 做的更加专业&#xff0c;因此在实际项目开发中我们经常将 ESLi…

JAVA架构与开发(JAVA架构是需要考虑的几个问题)

在企业中JAVA架构师主要负责企业项目技术架构&#xff0c;企业技术战略制定&#xff0c;技术框架搭建&#xff0c;技术培训和技术攻坚的工作。 在JAVA领域&#xff0c;比较多的都是web项目。用于解决企业的数字化转型。对于JAVA架构师而言&#xff0c;平时对项目的架构主要考虑…

如何成为一名全栈工程师:专业建议与技能要求

作为一名全栈工程师&#xff0c;你需要拥有跨越前端、后端、数据库等多个领域的技能&#xff0c;并能够将它们整合起来构建出完整的应用程序。因此&#xff0c;成为一名全栈工程师需要你掌握多种技术&#xff0c;具备较强的编程能力和系统设计能力。下面&#xff0c;我将从以下…

低代码开发平台是什么意思?低代码开发平台优势!

大多数企业都在寻求尽可能地改善客户体验。因此&#xff0c;企业和开发人员正在转向低代码开发平台&#xff0c;以在没有传统方法的情况下提供有针对性的应用程序。关键是尽可能消除手动编程过程。 低代码开发平台是什么意思&#xff1f; 低代码是开发应用程序的现代方式。它…

如何做SpringBoot单元测试?

前言单元测试&#xff08;unit testing&#xff09;&#xff0c;是指对项目中的最⼩可测试单元进⾏检查和验证的过程就叫单元测试&#xff0c;对于Java来说或者是在SpringBoot项目中&#xff0c;最小的可测试单元就是一个方法。做单元测试就是为了证明某段代码的执⾏结果是否符…

面向对象设计模式:结构型模式之装饰器模式

文章目录一、引入二、装饰器模式2.1 Intent 意图2.2 Applicability 适用性2.3 类图2.4 优缺点2.5 应用实例&#xff1a;Java IO 类2.6 应用实例&#xff1a;咖啡馆订购系统一、引入 咖啡馆订购系统 Initial 初始 4 种咖啡 House blend (混合咖啡)Dark Roast (深度烘培)Decaf (…

Vue3做出B站【bilibili】 Vue3+TypeScript+ant-design-vue【快速入门一篇文章精通系列(一)前端项目案例】

本项目分为二部分 1、后台管理系统&#xff08;用户管理&#xff0c;角色管理&#xff0c;视频管理等&#xff09; 2、客户端&#xff08;登录注册、发布视频&#xff09; Vue3做出B站【bilibili】 Vue3TypeScriptant-design-vue【快速入门一篇文章精通系列&#xff08;一&…