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

news2024/9/23 3:16:00

目录

  • 需求
  • 一、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)
	{
		
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Visual Studio 2022 + Qt 编写 VTK 程序

Visual Studio 2022 Qt 编写 VTK 程序 Visual Studio 2022 Qt 编写 VTK 程序前期准备创建一个 Qt 程序引入 VTK 库运行项目 Visual Studio 2022 Qt 编写 VTK 程序 前期准备 你需要一个编译好的 VTK 库:使用 Cmake 对 VTK-9.3.0 进行编译 你需要安装 Qt&#x…

<数据集>光伏板缺陷检测数据集<目标检测>

数据集格式:VOCYOLO格式 图片数量:2400张 标注数量(xml文件个数):2400 标注数量(txt文件个数):2400 标注类别数:4 标注类别名称:[Crack,Grid,Spot] 序号类别名称图片数框数1Crack8688922Grid8248843S…

CTF之easyupload

拿到题目发现是文件上传的漏洞&#xff0c;但是这个黑名单过滤的有点严格&#xff0c;无论是文件里还是文件后缀都不能出现php 那我们就用<?eval($_POST[a]);?>来进行绕过&#xff08;注意这里要加个GIF89a或者GIP87a进行欺骗&#xff09; 但是后缀依然不能绕过怎么办&…

我的六天C++外出学习记

第一天 7月7日 星期日 早晨&#xff0c;我早早起来了&#xff0c;穿好衣服吃完饭就出发了。 我从家到学校用了1H&#xff0c;迟到了&#xff01;我急急忙忙去报到。 我们中午和晚上的饭菜虽说有点贵&#xff0c;但实在太美味了&#xff0c;和我们原本初中的饭菜相比&#…

C语言指针超详解——强化篇

C语言指针系列文章目录 入门篇 强化篇 文章目录 C语言指针系列文章目录1. assert 断言2. 指针的使用和传址调用2. 1 strlen的模拟实现2. 2 传值调用和传址调用 3. 数组名的理解4. 使用指针访问数组5. 一维数组传参的本质6. 冒泡排序7. 二级指针8. 指针数组9. 指针数组模拟实现…

【LeetCode力扣】005.最长回文子串(Python)

最直观的做法&#xff0c;时间&#xff0c;空间复杂度都是O(2^n) class Solution:def longestPalindrome(self, s: str) -> str:dp [[0 for i in range(len(s))] for j in range(len(s))]longestSubStr "" # 存储最长回文子串longestLen 0 # 最长回文子串的长…

第一部分:C++入门

目录 前言 1、C关键字(C98) 2、命名空间 2.1、命名空间定义 2.2、命名空间的使用 3、C输入&输出 4、缺省参数 4.1、缺省参数的概念 4.2、缺省参数的分类 5、函数重载 5.1、函数重载的概念 5.2、C支持函数重载的原理 6、引用 6.1、引用的概念 6.2、引用特性 …

职业PDF标准 Python 下载器-CSDN

目的 下载技能人才评价网 - 职业技能标准查询系统 - PDF 打包下载 使用文件 a.json 代码解析 import base64 import requests import json import os import time# 读取JSON文件 with open(a.json, r, encodingutf-8) as f:data json.load(f) # 从名为 a.json 的文件中读…

数据库作业d8

要求&#xff1a; 一备份 1 mysqldump -u root -p booksDB > booksDB_all_tables.sql 2 mysqldump -u root -p booksDB books > booksDB_books_table.sql 3 mysqldump -u root -p --databases booksDB test > booksDB_and_test_databases.sql 4 mysql -u roo…

iPhone数据恢复:如何从iPhone恢复误删除的短信

来自iPhone的意外删除的短信可能很关键。它们可能是来自您常用应用程序、银行交易、付款收据的重要通知&#xff0c;也可能是来自朋友的重要文本、孩子的学校通知等。 如果您也从iPhone丢失了此类消息&#xff0c;我们在这里分享如何在没有备份以及有备份的情况下在iPhone上恢…

frameworks 之FallbackHome

frameworks 之FallbackHome FallbackHome 启动启动 Activity 流程创建进程ActivityThrad 与 AMS启动真正的 Launcher mActivityManagerService 创建后会启动 FallbackHome 再启动桌面程序。因为此时还没解锁&#xff0c;桌面又涉及很多其他应用程序相关&#xff0c;所以要等待用…

项目方案:社会视频资源整合接入汇聚系统解决方案(十)-视频监控汇聚应用案例和解决方案

目录 一、概述 1.1 应用背景 1.2 总体目标 1.3 设计原则 1.4 设计依据 1.5 术语解释 二、需求分析 2.1 政策分析 2.2 业务分析 2.3 系统需求 三、系统总体设计 3.1设计思路 3.2总体架构 3.3联网技术要求 四、视频整合及汇聚接入 4.1设计概述 4.2社会视频资源分…

DevToys-开源免费开发工具箱

个人觉得相较于那些在线的工具箱&#xff0c;这种离线的工具箱客户端更加可信一些。 DevToys 提供了30 个默认工具&#xff1a; 转换器&#xff1a;JSON <> YAML、日期、数字基数......编码器/解码器&#xff1a;HTML、URL、Base64、GZip、JWT、二维码......格式化程序…

【机器学习】随机森林的分类效果及进阶应用

文章目录 一、随机森林概述1.1 Bagging思想1.2 随机森林的定义1.3 随机森林的生成过程投票机制 二、随机森林的性能与优缺点2.1 分类效果的影响因素2.2 优点2.3 缺点 三、随机森林的进阶3.1 缺失值处理3.2 袋外数据&#xff08;OOB&#xff09;OOB计算方法优缺点 3.3 过拟合问题…

Deepin 安装sunix串口卡驱动

折腾了3天&#xff0c;终于搞定&#xff0c;改天上传安装过程&#xff0c;开启用c对串口传感器的编程 这种戴尔拆机卡&#xff0c;芯片用的是sunix&#xff0c;下载sunix 的linux驱动。 串口传感器用的是中盛rs485温湿度串口传感器&#xff0c;加一个rs232 转485接口 串口传感…

安全防御拓扑1

目录 实验的拓扑&#xff1a; 要求&#xff1a; 我搭建的实验拓扑 步骤&#xff1a; 创建vlan&#xff1a; 接口配置&#xff1a; 防火墙&#xff1a; 防火墙配置&#xff1a; 建立安全策略&#xff1a; 防火墙的用户&#xff1a; 办公区的市场部和研发部用户 市场部…

手机删除的文件能恢复吗?删除不等于永别,3个技巧助你找回

安卓手机中的文件&#xff0c;就像是数字世界里的繁星&#xff0c;记录着我们的点点滴滴。然而&#xff0c;有时我们可能会不小心删除了某些重要的文件&#xff0c;让我们感到惋惜和困惑。删除的文件能恢复吗&#xff1f;别担心&#xff0c;删除并不等于永别&#xff0c;我们也…

关于文档理解相关工作的一些总结

过去四年时间&#xff0c;都在处理结构化数据的存储优化相关的工作。最近一段时间在做RAG相关的工作。非结构数据的存储与检索&#xff0c;接触的也越来越多。这篇文章聊聊最近一段时间关于文档理解方面的一些心得。 文档理解 文档理解旨在从非结构化文档中提取信息并将其转化…

DockerSecret+DockerConfig介绍及使用

DockerSecret 查看官网介绍&#xff0c;Secret是daemon API 1.25之后引入的&#xff0c;它运行在swarm上的命令。 生产环境下&#xff0c;为了安全&#xff0c;我们不能把各项目的配置密码写入到配置文件。 我们可以引入docker的secret方式保护密码。 场景&#xff1a; 用…

java数组之——了解十大排序算法(动画版)

详细的冒泡排序和快速排序请查看文章&#xff1a;java数组之冒泡排序、快速排序-CSDN博客https://blog.csdn.net/weixin_44554794/article/details/140361078 一、插入排序 二、希尔排序 三、选择排序 四、堆排序 五、冒泡排序 六、快速排序 七、归并排序 八、计数排序 九、桶…