STM32第十九课:FreeRTOS移植和使用

目录

  • 需求
  • 一、FreeRtos概要
  • 二、移植FreeRtos
    • 1.复制源码
    • 2.内存空间分配和内核相关接口
    • 3.FreeRTOSConfig.h
    • 4.在工程中添加.c.h
  • 三、任务块操作
    • 1.创建任务
    • 2.任务挂起,恢复,删除
  • 四、需求实现代码


需求

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


一、FreeRtos概要

STM32裸机运行代码:
在这里插入图片描述
加入FreeRtos后:
在这里插入图片描述
由此可见,由于单片机只有一个核心,同一时间下只能处理一件事。如果用户想要实现多个任务并行的效果,可以通过加入FreeRtos(嵌入式实时操作系统),操作系统可以让STM32实现任务的快速切换,从而给人一种多个任务并行的错觉。
在这里插入图片描述

二、移植FreeRtos

  打开想要移植FreeRtos的工程,把主函数清空,只留一个while(1)。由于FreeRtos是任务块操作,所以之前写的程序就没用了。
移植后使用了三个中断服务函数:
1.SVC中断服务函数:上下切换中断,FreeRtos实现任务切换
2.PendSVC中断服务函数:任务挂起中断。
3.SysTick中断服务函数:FreeRtos运行的时间基准

#define vPortSVCHandler SVC_Handler	  //上下切换中断,FreeRtos实现任务切换
#define xPortPendSVHandler PendSV_Handler		//任务挂起中断
#define xPortSysTickHandler SysTick_Handler	//FreeRtos运行的时间基准

1.复制源码

先打开移植的文件夹:

在这里插入图片描述
将源码直接复制到想要移植的工程文件下,改名为FreeRtos:
在这里插入图片描述

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

在这里插入图片描述
在portable文件夹中找到MemMang文件夹,该文件夹放着的就是内存分配文件,我们选择4就行。
在这里插入图片描述
port,就是内核相关的接口文件,是必要添加的。

3.FreeRTOSConfig.h

在这里插入图片描述
打开样例文件夹,找到相对应的芯片,将FReeRTOSconfig.h文件复制过来即可。

4.在工程中添加.c.h

.c
在这里插入图片描述
.h
在这里插入图片描述

其中,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

三、任务块操作

调度
和裸机操作不同,操作系统中执行的是一个一个任务块,通过任务调度器(使用相关的调度算法)来决定当前时刻要执行哪个任务。
调度方式主要有两种:
1.抢占式调度:任务优先级不同时使用。每个任务都有自己的优先级,高优先级的任务会抢占低优先级的任务。
2.时间片调度:任务优先级相同时使用。当多个任务优先级相同时,任务调度器会在每一次系统节拍到的时候切换任务。
其实说白了就是:STM32执行的是线性代码,只有中断能打断。而FreeRtos执行的是不同等级的任务块,等级越高任务块就越先执行相同等级的任务块执行时系统会来回切换
优先级不能设置为0,因为FreeRtos的空闲任务优先级为0,一般情况下我们不去抢。

任务状态

状态含义
运行态CPU正在执行的任务。注意:在STM32中,同一时间仅一个任务处于运行态
就绪态该任务能够被执行,但目前还未被执行,那么该任务就处于就绪态。
阻塞态如果一个任务因延时或等待外部事件发生,那么这个任务就处于阻塞态。
挂起态类似暂停,调用函数 vTaskSuspend() 进入挂起态,需要调用恢复函数vTaskResume()才可以进入就绪态 。

1.创建任务

添加FreeRTOS相关头文件

//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"

创建一个句柄,TaskHandle_t 类型

TaskHandle_t LED_TaskHandle;//LED

写与句柄对应的任务函数,通常要加while(1)每个任务都是1个无限循环程序,内容根据需求来定。

void Led_Task(void *p)
{
	uint8_t i=0;
	while(1)
	{
		i++;
		printf("i=%d\r\n",i);
		Led_Toggle(1);
		Delay_nms(300);
	}
}

定义一个BaseType_t变量

BaseType_t Ret = pdPASS;

使用xTaskCreate()创建任务块,返回值由BaseType_t类型变量承接,返回值为pdPASS(1)时即创建成功

	Ret = xTaskCreate(  Led_Task,
                       "LED1_toggle",
                        50,//栈深度,32位单片机*4
                        NULL,
						2,
                        &LED_TaskHandle
                     );
	if(Ret==pdPASS)
	{
		printf("LED_Task创建成功!\r\n");
	}

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

最后,使用vTaskStartScheduler()函数开始调度就完成了。

vTaskStartScheduler();

2.任务挂起,恢复,删除

挂起
使用vTaskSuspend()函数即可,参数只有一个:想要挂起任务的句柄。
恢复
使用vTaskResume()函数即可,参数只有一个:想要恢复任务的句柄。
删除
使用vTaskDelete()函数即可,参数只有一个:想要删除任务的句柄。

printf("挂起LED\r\n");vTaskSuspend(LED_TaskHandle);//挂起
printf("继续LED\r\n");vTaskResume(LED_TaskHandle);//继续
printf("删除LED\r\n");vTaskDelete(LED_TaskHandle);//删除

四、需求实现代码

在该系统中实现任务的创建、挂起、恢复和删除

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"
#include "usart.h"
#include "key.h"
TaskHandle_t LED_TaskHandle;//LED
TaskHandle_t KEY_TaskHandle;//KEY


void Led_Task(void *p)
{
	uint8_t i=0;
	while(1)
	{
		i++;
		printf("i=%d\r\n",i);
		Led_Toggle(1);
		Delay_nms(300);
	}
}

void KEY_Task(void *p)
{
	while(1)
	{
		switch(key_getvalue())
		{
			case 1:{printf("挂起LED\r\n");vTaskSuspend(LED_TaskHandle);}break;//挂起
			case 2:{printf("继续LED\r\n");vTaskResume(LED_TaskHandle);}break;//继续
			case 3:{printf("删除LED\r\n");vTaskDelete(LED_TaskHandle);}break;
			case 4:{	BaseType_t Ret = pdPASS;	
								Ret = xTaskCreate(  Led_Task, "LED1_toggle",50,NULL,2,&LED_TaskHandle);
								if(Ret==pdPASS)
								{
									printf("LED_Task创建成功!\r\n");
								}
						 };break;
		}
		vTaskDelay(10);
	}
}


int main()
{
	Led_Init();
	key_Init();
	Usart1_Config();
	BaseType_t Ret = pdPASS;
	Ret = xTaskCreate(  Led_Task,
                       "LED1_toggle",
                        50,//栈深度,32位单片机*4
                        NULL,
												2,
                        &LED_TaskHandle
                     );
	if(Ret==pdPASS)
	{
		printf("LED_Task创建成功!\r\n");
	}
	Ret = xTaskCreate(  KEY_Task,
                       "KEY_Task",
                        80,//栈深度,32位单片机*4
                        NULL,
												2,
                        &KEY_TaskHandle
                     );
	if(Ret==pdPASS)
	{
		printf("KEY_Task创建成功\r\n");
	}
	printf("开始调度!\r\n");
	vTaskStartScheduler();
	while(1)
	{
		
	}
}

将之前写的传感器模块的数据获取,移植到FreeRtos(嵌入式实时操作系统)环境下
main.c

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "delay.h"
#include "string.h"
#include "pwm.h"
#include "adc.h"
#include "su03t.h"
#include "dht11.h"
#include "kqm.h"

//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"
#include "usart.h"
#include "key.h"
TaskHandle_t Deal_TaskHandle;//数据处理

void Data_Task(void *p)
{
	while(1)
	{
	Get_Smoke_Light_MidValue();
	DHT11_ReadData();
	Delay_nms(300);
	KQM_DealData();
	Su03tDealData();
	}
}

int main()
{
	RGBpwm_Config();
 	Kqm_U4Config();
 	Su03t_U5Config();
	DHT11_Config();	 
	Adc_Config();
	Led_Init();
	key_Init();
	Usart1_Config();
	BaseType_t Ret = pdPASS;
	Ret = xTaskCreate(  Data_Task,
                       "DealData",
                        100,//栈深度,32位单片机*4
                        NULL,
												2,
                        &Deal_TaskHandle
                     );
	if(Ret==pdPASS)
	{
		printf("语音创建成功!\r\n");
	}
	printf("开始调度!\r\n");
	vTaskStartScheduler();
	while(1)
	{
		
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32 BootLoader 刷新项目 (四) 通信协议

STM32 BootLoader 刷新项目 (四) 通信协议 文章目录 STM32 BootLoader 刷新项目 (四) 通信协议1. 通信流程2. 支持指令3. 通信流程4. 指令结构5. 操作演示 前面几章节,我们已经介绍了BootLoader的整体程序框架,方案设计,以及STM32CubdeMX的配…

Kafka基本原理|特性

Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统 它的最大的特性就是可以实时的处理大量数据以满足各种需求场景…

等保五级分类详解:从自主保护到专控保护的全方位信息安全

等保,即信息安全等级保护,是一项旨在保障电子信息系统安全的重要标准。根据系统所承载的信息重要性和可能遭受的损害程度,等保将信息系统划分为五个不同的安全等级。每个等级都有其特定的安全要求和测评周期,以确保不同规模和类型…

ES13的4个改革性新特性

1、类字段声明 在 ES13 之前,类字段只能在构造函数中声明, ES13 消除了这个限制 // 之前 class Car {constructor() {this.color = blue;this.age = 2

大气热力学(8)——热力学图的应用之一(气象要素求解)

本篇文章源自我在 2021 年暑假自学大气物理相关知识时手写的笔记,现转化为电子版本以作存档。相较于手写笔记,电子版的部分内容有补充和修改。笔记内容大部分为公式的推导过程。 文章目录 8.1 复习斜 T-lnP 图上的几种线8.1.1 等温线和等压线8.1.2 干绝热…

一个老程序员对小浣熊 AI 办公助手的使用体验

我是一个老程序员,今年 42 岁,仍然在一线编程领域工作。 2022 年底以 ChatGPT 为代表的 AI 工具席卷整个业界后,我也使用了不少能提高办公效率的 AI 工具。比如程序员的好帮手,来自微软的 Copilot. 这款名叫小浣熊的 AI 办公工具…

Web 性能入门指南-1.2 分析在线零售 Web 性能及优化方向

让顾客满意是零售业成功的秘诀。事实证明,提供快速、一致的在线体验可以显著提高零售商关心的每项指标——从转化率和收入到留存率和品牌认知度。 本文大纲: 页面速度影响在线零售业务数据 如何将您的网站速度与竞争对手进行比较 性能优化入门&#xf…

怎样在 PostgreSQL 中优化对复合索引的选择性?

🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!📚领书:PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中优化对复合索引的选择性一、理解复合索引的概念二、选择性的重要性三、优化复合索…

神经网络识别数字图像案例

学习资料:从零设计并训练一个神经网络,你就能真正理解它了_哔哩哔哩_bilibili 这个视频讲得相当清楚。本文是学习笔记,不是原创,图都是从视频上截图的。 1. 神经网络 2. 案例说明 具体来说,设计一个三层的神经网络。…

采用自动微分进行模型的训练

自动微分训练模型 简单代码实现: import torch import torch.nn as nn import torch.optim as optim# 定义一个简单的线性回归模型 class LinearRegression(nn.Module):def __init__(self):super(LinearRegression, self).__init__()self.linear nn.Linear(1, 1) …

链接追踪系列-07.logstash安装json_lines插件

进入docker中的logstash 容器内: jelexbogon ~ % docker exec -it 7ee8960c99a31e607f346b2802419b8b819cc860863bc283cb7483bc03ba1420 /bin/sh $ pwd /usr/share/logstash $ ls bin CONTRIBUTORS Gemfile jdk logstash-core modules tools x-pack …

如何预防最新的baxia变种勒索病毒感染您的计算机?

引言 在当今数字化时代,网络安全威胁层出不穷,其中勒索病毒已成为企业和个人面临的重大挑战之一。近期,.baxia勒索病毒以其高隐蔽性和破坏性引起了广泛关注。本文将详细介绍.baxia勒索病毒的特点、传播方式,并给出相应的应对策略…

2024-07-15 Unity插件 Odin Inspector3 —— Button Attributes

文章目录 1 说明2 Button 特性2.1 Button2.2 ButtonGroup2.3 EnumPaging2.4 EnumToggleButtons2.5 InlineButton2.6 ResponsiveButtonGroup 1 说明 ​ 本章介绍 Odin Inspector 插件中有关 Button 特性的使用方法。 2 Button 特性 2.1 Button 依据方法,在 Inspec…

YOLOv8训练自己的数据集(超详细)

一、准备深度学习环境 本人的笔记本电脑系统是:Windows10 YOLO系列最新版本的YOLOv8已经发布了,详细介绍可以参考我前面写的博客,目前ultralytics已经发布了部分代码以及说明,可以在github上下载YOLOv8代码,代码文件夹…

力扣经典题目之->移除值为val元素的讲解,的实现与讲解

一:题目 博主本文将用指向来形象的表示下标位的移动。 二:思路 1:两个整形,一个start,一个end,在一开始都 0,即这里都指向第一个元素。 2:在查到val之前,查一个&…

昇思25天学习打卡营第12天|MindSpore 助力下的 GPT2:数据集加载处理及模型全攻略

环境配置 %%capture captured_output 此乃 Jupyter Notebook 中的一个魔法命令,其作用在于捕获后续单元格中的输出,并将之存储于变量 captured_output 当中,而非直接于输出区域予以显示。如此一来,便可隐匿某些可能存在的输出信息…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(九)-无人机服务区分离

引言 本文是3GPP TR 22.829 V17.1.0技术报告,专注于无人机(UAV)在3GPP系统中的增强支持。文章提出了多个无人机应用场景,分析了相应的能力要求,并建议了新的服务级别要求和关键性能指标(KPIs)。…

小程序里面使用vant ui中的vant-field组件,如何使得输入框自动获取焦点

//.wxml <van-fieldmodel:value"{{ userName }}"placeholder"请输入学号"focus"{{focusUserName}}"/>// .js this.setData({focusUserName: true});vant-field

钡铼ARMxy控制器在智能网关中的应用

随着IoT物联网技术的飞速发展&#xff0c;智能网关作为连接感知层与网络层的枢纽&#xff0c;可以实现感知网络和通信网络以及不同类型感知网络之间的协议转换。钡铼技术的ARMxy系列控制器凭借其高性能、低功耗和高度灵活性的特点&#xff0c;在智能网关中发挥了关键作用&#…

RPC与服务的注册发现

文章目录 1. 什么是远程过程调用(RPC)?2. RPC的流程3. RPC实践4. RPC与REST的区别4.1 RPC与REST的相似之处4.2 RPC与REST的架构原则4.3 RPC与REST的主要区别 5. RPC与服务发现5.1 以zookeeper为服务注册中心5.2 以etcd为服务注册中心 6. 小结参考 1. 什么是远程过程调用(RPC)?…