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


需求

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


一、FreeRtos概要

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

二、移植FreeRtos

  打开想要移植FreeRtos的工程,把主函数清空,只留一个while(1)。由于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)
	{
		
	}
}

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32嵌入式系统开发实战指南:FreeRTOS和lwIP联合移植》是一本关于嵌入式系统开发的实战指南。本书介绍了如何在STM32微控制器上使用FreeRTOS实时操作系统和lwIP网络协议栈进行嵌入式系统开发。通过本书的学习,读者可以了解到如何基于STM32开发板搭建嵌入式系统开发环境,学习STM32微控制器和FreeRTOS操作系统的基本概念和原理,以及如何使用lwIP网络协议栈进行网络通信。 该书内容分为多个章节,每个章节都有详细的实例和代码进行讲解。首先,介绍了STM32微控制器的硬件架构和开发环境的搭建。然后,详细介绍了FreeRTOS使用,包括任务、信号量、消息队列等基本概念和操作方法。接着,介绍了lwIP网络协议栈的基础知识和使用方法,包括网络套接字编程、TCP/IP通信、UDP广播等内容。最后,通过一个完整的示例项目,展示了如何将FreeRTOS和lwIP联合移植STM32微控制器上,实现一个简单的TCP/IP网络通信应用程序。 本书适合嵌入式系统开发初学者或已有基础的开发者学习使用。通过学习本书,读者可以全面了解STM32的基本知识和嵌入式系统开发的流程,同时深入学习FreeRTOS和lwIP的使用方法,能够独立进行嵌入式系统开发和网络通信的实际项目。整本书结合理论和实践,具有很强的实用性,是学习STM32嵌入式系统开发的重要参考资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值