STM32(F103ZET6)第十九课:FreeRtos的移植和使用

目录

  • 需求
  • 一、FreeRtos简介
  • 二、移植FreeRtos
    • 1.复制代码
    • 2.内存空间分配和内核相关接口
    • 3.FreeRtosConfig
    • 4.添加到工程中
    • 三、任务块操作
    • 1.任务四种状态
    • 2.创建任务过程

需求

1.将FreeRtos(嵌入式实时操作系统)移植到STM32中。
2.在该系统中实现任务的创建、挂起、恢复和删除。
3.将板子上写的传感器模块的数据获取,移植到FreeRtos(嵌入式实时操作系统)环境下。
在这里插入图片描述

一、FreeRtos简介

裸机执行流程:前后台系统
在这里插入图片描述
操作系统执行流程:
在这里插入图片描述
加入操作系统的作用:用户想要实现多个任务并行的效果,但是单片机只有一个核心,同时只能处理一件事,通过加入操作系统,可以实现任务快速的切换,给人一种多个任务同时在执行的错觉。
FreeRtos的概念:
在这里插入图片描述在这里插入图片描述

二、移植FreeRtos

移植之前,找一个工程mian.c清空,然后移植FreeRTOS。因为加上操作系统之后,编程方式就变了,之前的while(1)就不在使用了。

1.复制代码

从官网下载的FreeRTOS 包含 Demo 例程和内核源码(比较重要,我们就需要提取该目录下的大部分文件)。 FreeRTOS 文件夹下的 Source 文件夹里面包含的是 FreeRTOS 内核的源代码,
我们移植 FreeRTOS 的时候就需要这部分源代码; FreeRTOS 文件夹下的 Demo 文件夹里
面包含了 FreeRTOS 官方为各个单片机移植好的工程代码, FreeRTOS 为了推广自己,会
给各种半导体厂商的评估板写好完整的工程程序,这些程序就放在 Demo 这个目录下,这
部分 Demo 非常有参考价值。我们把 FreeRTOS 到 STM32 的时候,FreeRTOSConfig.h 这
个头文件就是从这里拷贝过来的。
在这里插入图片描述
将源码直接复制到想要移植的工程文件下,改名为FreeRtos:
在这里插入图片描述
这里我们再重点分析下 FreeRTOS/ Source 文件夹下的文件,具体见图 13-6。“include”
文件夹和“portable”文件夹包含的是 FreeRTOS 的通用的头文件和 C 文件,这两部分的文
件试用于各种编译器和 include 处理器, 是通用的。需要移植的头文件和 C 文件放在编号
portblle 这个文件夹。
在这里插入图片描述
我们打开 portable 这个文件夹,可以看到里面很多与编译器相关的文件夹, 在不同的
编译器中使用不同的支持文件。文件夹“Keil”就是我们就是我们使用的编译器,当打开 “Keil”
文件夹的时候,你会看到一句话“See-also-the-RVDS-directory.txt”,其实 “Keil” 里面的内容
跟 RVDS 里面的内容一样,所以我们只需要 RVDS 文件夹里面的内容即可。而 MemMang
文件夹下存放的是跟内存管理相关的,我们的重点是RVDS文件夹
在这里插入图片描述
打开 RVDS 文件夹, 下面包含了各种处理器相关的文件夹,从文件夹的名字我们就非
常熟悉了,有 M0、 M3、 M4 等各种系列, FreeRTOS 是一个软件,单片机是一个硬件,
FreeRTOS 要想运行在一个单片机上面,它们就必须关联在一起,那么怎么关联?还是得通
过写代码来关联,这部分关联的文件叫接口文件,通常由汇编和 C 联合编写。这些接口文
件都是跟硬件密切相关的,不同的硬件接口文件是不一样的,但都大同小异。编写这些接口
文件的过程我们就叫移植,移植的过程通常由 FreeRTOS 和 MCU 原厂的人来负责,移植
好的这些接口文件就放在 RVDS 这个文件夹的目录下。
在这里插入图片描述

2.内存空间分配和内核相关接口

MemMang 文件夹下存放的是跟内存管理相关的,总共有五个 heap 文件以及一
个 readme 说明文件,这五个 heap 文件在移植的时候必须使用一个,因为 FreeRTOS 在
创建内核对象的时候使用的是动态分配内存,而这些动态内存分配的函数则在这几个文件里
面实现,不同的分配算法会导致不同的效率与结果,后面在内存管理中我们会讲解每个文件
的区别,由于现在是初学,所以我们选用 heap4.c 即可。
在这里插入图片描述
FreeRTOS 为我们提供了 cortex-m0、m3、m4 和 m7 等内核的单片机的接口文件,
只要是使用了这些内核的 MCU 都可以使用里面的接口文件。我们这里以 ARM_CM3 这个
文件夹为例,看看里面的文件,里面只有“port.c”与“portmacro.h”两个文件, port.c 文件里
面的内容是由 FreeRTOS 官方的技术人员为 Cortex-M3 内核的处理器写的接口文件,里面
核心的上下文切换代码是由汇编语言编写而成;portmacro.h 则是 port.c 文件对应的头文
件,主要是一些数据类型和宏定义。
在这里插入图片描述
首先在我们的 STM32 裸机工程模板根目录下新建一个文件夹,命名为“FreeRTOS”,
并且在 FreeRTOS 文件夹下新建两个空文件夹,分别命名为“src”与“port”,src 文件夹用于
保存 FreeRTOS 中的核心源文件,也就是我们常说的‘.c 文件’, port 文件夹用于保存内存
管理以及处理器架构相关代码,这些代码 FreeRTOS 官方已经提供给我们的,直接使用即可,
在前面已经说了, FreeRTOS 是软件,我们的开发版是硬件,软硬件必须有桥梁来连接,这
些 与 处 理 器 架 构 相 关 的 代 码 , 可 以 称 之 为 RTOS 硬 件 接 口 层 , 它 们 位 于
FreeRTOS/Source/Portable 文件夹下。
在这里插入图片描述
打开 FreeRTOS 源码,在“FreeRTOSvX.X.X\FreeRTOS\Source”目录下找到所有的‘.c 文
件’,将它们拷贝到我们新建的 src 文件夹中。
在这里插入图片描述
打开 FreeRTOS VX.X.X 源码,在“FreeRTOS VX.X.X \FreeRTOS\Source\portable”目录
下找到“ MemMang”文件夹与“ RVDS”文件夹,将它们拷贝到我们新建的 port 文件夹中。
在这里插入图片描述
打开 FreeRTOS VX.X.X 源码,在“FreeRTOS VX.X.X \FreeRTOS\Source” 目录下找到
“include”文件夹,它是我们需要用到 FreeRTOS 的一些头文件,将它直接拷贝到我们新建的
FreeRTOS 文件夹中,完成这一步之后就可以看到我们新建的 FreeRTOS 文件夹已经有 3
个文件夹,这 3 个文件夹就包含 FreeRTOS 的核心文件,至此,FreeRTOS 的源码就提取
完成
在这里插入图片描述

3.FreeRtosConfig

拷贝 FreeRTOSConfig.h 文件到 user 文件夹
FreeRTOSConfig.h 文件是 FreeRTOS 的工程配置文件,因为 FreeRTOS 是可以裁剪的
实时操作内核,应用于不同的处理器平台,用户可以通过修改这个 FreeRTOS 内核的配置头
文件来裁剪 FreeRTOS 的功能,所以我们把它拷贝一份放在 user 这个文件夹下面
在这里插入图片描述
其中,FreeRTOSConfig.h 是直接从 demo 文件夹下面拷贝过来的,该头文件对裁剪整个FreeRTOS 所需的功能的宏均做了定义,有些宏定义被使能,有些宏定义被失能,一开始我们只需要配置最简单的功能即可。要想随心所欲的配置 FreeRTOS 的功能,必须对这些宏定义的功能有所掌握。
比较重要的宏文件:
#define configUSE_TIME_SLICING 1 //使能时间片调度(默认式使能的)
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 //硬件计算前导零指令,如果所使用的, MCU 没有这些硬件指令的话此宏应该设置为 0
#define configUSE_TICKLESS_IDLE 0 //置 1:使能低功耗 tickless 模式;置 0:保持系统节拍(tick)中断一直运行
#define configUSE_QUEUE_SETS 1 //启用队列
#define configUSE_TASK_NOTIFICATIONS 1 //开启任务通知功能,默认开启
#define configUSE_MUTEXES 1 //使用互斥信号量
#define configUSE_RECURSIVE_MUTEXES 1 //使用递归互斥信号量
#define configUSE_COUNTING_SEMAPHORES 1 //为 1 时使用计数信号量
#define configQUEUE_REGISTRY_SIZE 10 //设置可以注册的信号量和消息队列个数
#define configUSE_APPLICATION_TASK_TAG 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1 //支持动态内存申请
#define configUSE_MALLOC_FAILED_HOOK 0 //使用内存申请失败钩子函数
#define configCHECK_FOR_STACK_OVERFLOW 1// 大于 0 时启用堆栈溢出检测功能,如果使用此功能用户必须提供一个栈溢出钩子函数如果使用的话此值可以为 1 或者 2,因为有两种栈溢出检测方法
#define configGENERATE_RUN_TIME_STATS 0 //启用运行时间统计功能
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
#define configUSE_TIMERS 1 //启用软件定时器
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) //软件定时器优先级
#define configTIMER_QUEUE_LENGTH 10 //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) //软件定时器任务堆栈大小
//可选函数配置选项
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 1
//中断服务函数 也可以修改起始文件
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

4.添加到工程中

添加 FreeRTOS 源码到工程组文件夹
在这里插入图片描述
配置 FreeRTOS 头文件路径
在这里插入图片描述

三、任务块操作

1.任务四种状态

在这里插入图片描述
四种形态:
运行态
当任务实际执行时,它被称为处于运行状态。 任务当前正在使用处理器。 如果运行 RTOS 的处理器只有一个内核, 那么在任何给定时间内都只能有一个任务处于运行状态。
就绪态
准备就绪任务指那些能够执行(它们不处于阻塞或挂起状态), 但目前没有执行的任务, 因为同等或更高优先级的不同任务已经处于运行状态。
阻塞态
如果任务当前正在等待时间或外部事件,则该任务被认为处于阻塞状态。 例如,如果一个任务调用vTaskDelay(),它将被阻塞(被置于阻塞状态), 直到延迟结束-一个时间事件。 任务也可以通过阻塞来等待队列、信号量、事件组、通知或信号量 事件。 处于阻塞状态的任务通常有一个"超时"期, 超时后任务将被超时,并被解除阻塞, 即使该任务所等待的事件没有发生。
“阻塞”状态下的任务不使用任何处理时间,不能 被选择进入运行状态。
挂起态
与“阻塞”状态下的任务一样, “挂起”状态下的任务不能 被选择进入运行状态,但处于挂起状态的任务 没有超时。 相反,任务只有在分别通过 vTaskSuspend() 和 xTaskResume() API 调用明确命令时 才会进入或退出挂起状态。
调度机制
和裸机操作不同,操作系统中执行的是一个一个任务块,通过任务调度器(使用相关的调度算法)来决定当前时刻要执行哪个任务。
调度方式主要有两种:
1.抢占式调度:任务优先级不同时使用。每个任务都有自己的优先级,高优先级的任务会抢占低优先级的任务。
2.时间片调度:任务优先级相同时使用。当多个任务优先级相同时,任务调度器会在每一次系统节拍到的时候切换任务。
其实说白了就是:STM32执行的是线性代码,只有中断能打断。而FreeRtos执行的是不同等级的任务块,等级越高任务块就越先执行,相同等级的任务块执行时系统会来回切换。
优先级不能设置为0,因为FreeRtos的空闲任务优先级为0,一般情况下我们不去抢。

2.创建任务过程

1、首先要添加FreeRTOS相关头文件。这是必须的!
在这里插入图片描述
2、创建一个句柄,TaskHandle_t 类型
在这里插入图片描述在这里插入图片描述
3、创建任务

Ret = xTaskCreate(LED_Task, //创建任务的任务函数名"LED1_Toggle",//任务名字50,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL1,//任务优先级&LED_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("LED_Task创建完成\r\n");}Ret = xTaskCreate(KEY_Task, //创建任务的任务函数名"KEY_Task",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL2,//任务优先级&KEY_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("KEY_Task创建完成\r\n");}printf("开启FreeRTOS调度器\r\n");//调度器启动完成之后,FreeRTOS会获取CPU控制权,会按照任务优先级执行创建的任务vTaskStartScheduler();printf("开启FreeRTOS调度器成功\r\n");

创建完成后一定要打开调度器。
4、写与句柄对应的任务函数,通常要加while(1)每个任务都是1个无限循环程序,内容根据需求来定。
在这里插入图片描述在这里插入图片描述
接下来重点了解一下创建函数:

在这里插入图片描述
在这里插入图片描述
简单来说:
参数1:实现任务的函数名
参数2:自己起一个任务名
参数3:分配空间,栈深度(32位单片机*4)
参数4:任务函数传参时使用
参数5:任务优先级(越高优先级越高)
参数6:该任务的句柄

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/416498.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序(KNN分类器)

智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序(KNN分类器) 文章目录 一、基本原理原理流程举个例子总结 二、实验结果三、核心代码四、代码获取五、总结 智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序&#x…

macos MacPort 包管理工具安装和使用

在macos v10.15版本中, xz, python等软件无法使用brew安装, 原因是brew对于旧版本的macos不再支持, 但是我们可以使用另外一个macos下的包管理工具来安装brew无法安装的软件, macport 是一个和brew类似的macos下的一个非常优秀的软件包安装管理工具. MacPort安装前提条件 安…

【qt踩坑】路径含中文导致的报错,以及 OpenGL的链接报错

​ 背景 本来是准备采用VSQt插件的方式来开发Qt的,但是学习过程中发现,这种模式还是没有直接用Qt Creator 开发来的方便,插件这种模式坑多,功能不完善。 不过在直接使用Qt Creator的时候也踩坑了: (最后发现&#x…

SprinBoot+Vue健康管管理微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平…

qt报错 error: undefined reference to `vtable for RelayDevice 解决方法

在 Qt 编程中,当出现错误 undefined reference to ‘vtable for RelayDevice’ 时,通常是因为类的虚函数没有实现,或者未正确实现虚析构函数。以下是一些可能的解决方法: 确保实现所有虚函数: 检查 RelayDevice 类中声…

git clone 别人的项目上传到自己的Gitee或者github仓库

git clone别人的项目 git clone https://github.com/wohuweixiya/yft-design.git 进入该项目内,删除原有的.git信息 rm -r .git 初始化.git git init 将本地代码添加到仓库 git add . git commit -m "提交仓库说明" Github上新建一个和这个clone下来…

Rust多线程编程概述

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust到底值不值得学,之一 -CSDN博客 Rust到底值不值得学,之二-CSDN博客 12.2 多线程编程概述 12.2.1 线程…

基于51单片机的电动机控制系统的设计

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP…

LLM大模型学习:AI时代,敏感词过滤,如何精准且高效,方法+代码实现

前言 自从我开始搞大模型应用,就一直有一个头疼的问题困扰着我的团队,那就是避免敏感信息。 传统的做法是通过一些匹配算法,过滤掉敏感词,这个后面我们再讲。 但大模型的对话中,想要防止他做一些不合法的事情&#…

论文速读|重新审视奖励设计与评估:用于强健人型机器人站立与行走控制的方法

论文地址:https://arxiv.org/pdf/2404.19173 这篇论文为类人机器人站立和行走(SaW)控制器的持续可衡量改进奠定了基础。通过引入一套定量实际基准测试方法,作者展示了现有控制器的优缺点,并通过基准测试指导新控制器的…

Linux malloc内存分配实现原理

目录 一、用户进程虚拟内存空间布局 二、malloc工作原理 2.1 malloc实现流程 2.1.1 brk方式申请内存 2.1.2 mmap方式分配内存 2.2 核心代码 2.3 malloc分配物理内存的时机 2.4 malloc分配的实际内存大小 三、虚拟内存与物理内存 3.1 如何建立映射 3.2 分配物理内存 …

大数据采集与分析实训室解决方案

随着信息技术的飞速发展,大数据已成为推动产业升级、社会进步的重要力量。为了培养适应未来社会需求的大数据专业人才,构建一套科学、先进的大数据采集与分析实训室解决方案显得尤为重要。为此,唯众特推出全面升级的大数据采集与分析实训室解…

使用实例:xxl-job应用在spring cloud微服务下

1、首先下载,从github上下载,选择zip然后直接解压 https://github.com/xuxueli/xxl-job/releases 2、解压完后用idea启动。 启动这个启动类,然后按照路径访问 http://localhost:8080/xxl-job-admin/ 3、在你的项目里编写一个单独的微服务&a…

mac的使用

mac使用python的问题 对于python的虚拟环境,其实是基于已经安装到本地的python来安装不同的包。(之前我的mac上只安装了python3.9.6 ,安装的位置为/usr/bin/python3)然后我在vscode里怎么找都找不到如何弄一个python3.7.6 的版本…

Nginx部署前端vue项目操作步骤和方法~小皮

部署前端Vue.js项目到Nginx上,是开发流程中至关重要的一步,它意味着将静态文件托管在Web服务器上,使应用程序能够被用户访问和交互。下面将详细介绍如何使用Nginx部署前端Vue项目的操作步骤和方法: 准备构建Vue项目 安装Node.js和…

k8s集群环境搭建(一主二从--kubeadm安装)

前置条件 版本:CentOS Linux release 7.5.1804 (Core) 内存:2G CPU:2 主机名解析 vim /etc/hosts 192.168.109.100 master 192.168.109.101 node1 192.168.109.102 node2时间同步,这里直接使用chronyd服务从网络同步时间syste…

2024.9.2

还没写完 #include <iostream> #include <cstring> using namespace std;class myString { private:char *str; //字符串int size; //实际字符长度int len; //字符串容量 public:myString():size(10) //无参构造函数{len siz…

ES6语法详解

以下是ES6常用的一些语法和特性&#xff1a; 声明变量的关键字变化&#xff1a;使用let和const、var来声明变量。 箭头函数&#xff1a;使用箭头&#xff08;>&#xff09;定义函数&#xff0c;简化函数的写法。 模板字符串&#xff1a;使用反引号&#xff08;&#xff0…

学习大数据DAY52 Docker中的Mysql主从配置

Mysql 数据库主从同步 上机练习 1 容器生成命令 压缩包获取镜像 docker image load -i /root/mysql.tar 创建并开启两个镜像&#xff1a; docker run --name mysql1 -d -p 3333:3306 \ -v /opt/mysql1/conf:/etc/mysql/conf.d/ \ -v /opt/mysql1/data:/var/lib/mysql \…

★ 算法OJ题 ★ 力扣1089 - 复写零

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将和大家一起做一道双指针算法题--复写零~ 目录 一 题目 二 算法解析 2.1 算法思路 2.2 算法流程 三 编写算法 一 题目 1089. 复写零 - 力扣&#xff08;LeetCode&#xff09; 二 算法解析 2.1 算法思路 …