FreeRTOS之静态创建任务

1.在前面的文章中介绍了FreeRTOS的动态创建方法,本文介绍一下FreeRTOS的静态任务创建方法xTaskCreateStatic()。相比较动态任务创建过程,静态创创建任务的过程稍显复杂。主要步骤为:

(1)配置相关的宏定义:configSUPPORT_STATIC_ALLOCATION。

(2)实现部分接口函数,用来给空闲任务的任务堆栈和任务控制块分配内存。

(3)配置静态创建任务函数的入口参数。

2.配置相关的宏定义:

将支持静态内存分配的宏定义configSUPPORT_STATIC_ALLOCATION设置为1:

配置静态任务相关的宏定义:

本文开启软件定时器任务,所以需要将软件定时器的宏定义configUSE_TIMERS设置为1:

3.实现接口函数:

(1)重写空闲任务堆栈和任务控制块内存分配的API函数vApplicationGetIdleTaskMemory:

(2)重写软件定时器任务堆栈和任务控制块内存分配的API函数vApplicationGetTimerTaskMemory:

4.配置静态创建任务函数的入口参数:

此处注意的是,静态创建任务时需要用户自己提供任务堆栈,本文自行定义了一个数组作为任务堆栈,堆栈数组为 StackType_t 类型。任务控制块的类型为StaticTask_t。

5.代码:

因为本文和前面动态创建任务实现的功能是相同的,所以本文不再展示所有的代码,仅展示main函数中代码。与前面的动态创建任务相比较,除了上述的宏定义配置外,本文只main函数有修改的地方。

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"
#include "sys.h"static StaticTask_t IdleTaskTCB;																		//¿ÕÏÐÈÎÎñ¿ØÖÆ¿é
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];					//¿ÕÏÐÈÎÎñ¶ÑÕ»/*ÖØд¿ÕÏÐÈÎÎñ¶ÑÕ»ºÍÈÎÎñ¿ØÖÆ¿éÄÚ´æ*/
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &IdleTaskTCB;														//ÈÎÎñ¿ØÖÆ¿éÄÚ´æ*ppxIdleTaskStackBuffer = IdleTaskStack;												//ÈÎÎñ¶ÑÄÚ´æ*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;								//ÈÎÎñ¶ÑÕ»´óС
}static StaticTask_t TimerTaskTCB;																	//¶¨Ê±Æ÷ÈÎÎñ¿ØÖÆ¿é
static StackType_t  TimerTaskStack[configTIMER_TASK_STACK_DEPTH];	//¶¨Ê±Æ÷·þÎñº¯Êý¶ÑÕ»
/*ÖØд¶¨Ê±Æ÷·þÎñÈÎÎñµÄ¶ÑÕ»ºÍÈÎÎñ¿ØÖÆ¿éÄÚ´æ*/
void vApplicationGetTimerTaskMemory( 	StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
{*ppxTimerTaskTCBBuffer = &TimerTaskTCB;													//ÈÎÎñ¿ØÖÆ¿éÄÚ´æ	*ppxTimerTaskStackBuffer = TimerTaskStack;											//ÈÎÎñ¶ÑÕ»ÄÚ´æ*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;					//ÈÎÎñ¶ÑÕ»´óС
}//¶¨Òåstart_taskµÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 64
StackType_t StartTaskStack[START_TASK_STACK_SIZE];							//ÈÎÎñ¶ÑÕ»
StaticTask_t StartTaskTCB;																			//ÈÎÎñ¿ØÖÆ¿é
TaskHandle_t start_handler;
void start_task(void);//¶¨ÒåÈÎÎñ1µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define LED0_TASK_PRIO 2
#define LED0_TASK_STACK_SIZE 64
StackType_t Task1Static[LED0_TASK_STACK_SIZE];										//ÈÎÎñ¶ÑÕ»
StaticTask_t Task1TCB;																			//ÈÎÎñ¿ØÖÆ¿é
TaskHandle_t led0_handler;
void led0(void);//¶¨ÒåÈÎÎñ2µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define LED1_TASK_PRIO 3
#define LED1_TASK_STACK_SIZE 64
StackType_t Task2Static[LED1_TASK_STACK_SIZE];										//ÈÎÎñ¶ÑÕ»
StaticTask_t Task2TCB;																			//ÈÎÎñ¿ØÖÆ¿é
TaskHandle_t led1_handler;
void led1(void);//¶¨ÒåÈÎÎñ3µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define KEY_TASK_PRIO 4
#define KEY_TASK_STACK_SIZE 64
StackType_t Task3Static[KEY_TASK_STACK_SIZE];										//ÈÎÎñ¶ÑÕ»
StaticTask_t Task3TCB;																			//ÈÎÎñ¿ØÖÆ¿é
TaskHandle_t key_handler;
void key_task(void);int flag = 0;int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é2LED_Init();KEY_Init();delay_init();start_handler = xTaskCreateStatic(	(TaskFunction_t) start_task,										//ÈÎÎñº¯Êý(const char *) "start_task",										//ÈÎÎñÃû³Æ(	 uint32_t) START_TASK_STACK_SIZE,							//ÈÎÎñ¶ÑÕ»´óС(void *) NULL,																	//ÈÎÎñº¯ÊýÈë¿Ú²ÎÊý(UBaseType_t) START_TASK_PRIO,									//ÈÎÎñÓÅÏȼ¶(StackType_t *) StartTaskStack,									//ÈÎÎñ¶ÑÕ»(StaticTask_t *) &StartTaskTCB );								//ÈÎÎñ¿ØÖÆ¿évTaskStartScheduler();																															//¿ªÊ¼ÈÎÎñµ÷¶È
}/*´´½¨¿ªÊ¼ÈÎÎñ£º*/
void start_task(void)
{
//	taskENTER_CRITICAL();	/*´´½¨ÈÎÎñ*/if(flag == 0){led0_handler = xTaskCreateStatic(	(TaskFunction_t) led0,										(const char *) "led0",										( uint32_t) LED0_TASK_STACK_SIZE,					(void *) NULL,																	(UBaseType_t) LED0_TASK_PRIO,									(StackType_t *) Task1Static,									(StaticTask_t *) &Task1TCB );								led1_handler = xTaskCreateStatic(	(TaskFunction_t) led1,										(const char *) "led1",										( uint32_t) LED1_TASK_STACK_SIZE,					(void *) NULL,																	(UBaseType_t) LED1_TASK_PRIO,									(StackType_t *) Task2Static,									(StaticTask_t *) &Task2TCB );key_handler = xTaskCreateStatic(	(TaskFunction_t) key_task,										(const char *) "key_task",										( uint32_t) KEY_TASK_STACK_SIZE,					(void *) NULL,																	(UBaseType_t) KEY_TASK_PRIO,									(StackType_t *) Task3Static,									(StaticTask_t *) &Task3TCB );							flag = 1;}vTaskDelay(500);vTaskDelete(NULL);											//ɾ³ýµ±Ç°ÈÎÎñ
//	 taskEXIT_CRITICAL();
}void led0(void)
{while(1){GPIO_ResetBits(GPIOA,GPIO_Pin_8);			//´ò¿ªLEDvTaskDelay(500);//delay_ms(500);GPIO_SetBits(GPIOA,GPIO_Pin_8);			//´ò¿ªLEDvTaskDelay(500);}
}void led1(void)
{while(1){GPIO_ResetBits(GPIOD,GPIO_Pin_2);			//´ò¿ªLEDvTaskDelay(500);//delay_ms(500);GPIO_SetBits(GPIOD,GPIO_Pin_2);			//´ò¿ªLEDvTaskDelay(500);}
}/*´´½¨°´¼üÈÎÎñ£º*/
void key_task(void)
{//uint8_t key = 0;while(1){//printf("task3ÕýÔÚÔËÐУ¡£¡£¡\r\n");//key = KEY_Scan(0);if(KEY_0 == 0){if(led0_handler != NULL){delay_us(2000000);//printf("ɾ³ýtask1ÈÎÎñ\r\n");vTaskDelete(led0_handler);led0_handler = NULL;}}vTaskDelay(10);}
}

6.运行结果:

7.总结:

本文介绍了FreeRTOS的静态创建任务方法xTaskCreateStatic()。在使用静态方法创建任务时,需要配置相关的宏定义,并实现空闲任务的堆栈和任务控制块内存分配函数vApplicationGetIdleTaskMemory()。

静态创建任务需要用户自行提供堆栈,通常用数组来实现。此外,函数xTaskCreateStatic创建任务成功时的返回值即为任务句柄,创建任务失败时返回值为NULL。

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

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

相关文章

16.4 冒泡排序

题目简介 排序动画模拟网站 phttps://www.cs.usfca.edugalles/visualization/ComparisonSort.htm 简洁版 #include <stdio.h> int main() {int a[10]{9,3,6,5,8,2,4,1,7,0};int n sizeof(a)/sizeof(int);int temp 0;for(int j0;j<n-1;j){ //外层循环循环9轮即可f…

怎么在本地debug使用idea计算对象内存

在工作的过程中&#xff0c;我们遇到一个觉得比较大的对象的时候&#xff0c;经常需要判断一个对象大小&#xff0c;以此来决定是将数据放在内存还是缓存来提升性能&#xff0c;我看到现在很多文章介绍的要么是不完善&#xff0c;要么是不够准确&#xff0c;因此打算自己写一篇…

48-PCIE转串口和并口电路设计

视频链接 PCIE转串口和并口电路设计01_哔哩哔哩_bilibili PCIe转串口和并口电路设计 1、PCIe转串并口电路设计基本介绍 2、PCIe转串口和并口的方案(京东) 2.1、PCIe转串口 2.1.1、ASIX (亚信)MCS9922-PCIe转2路RS232扩展卡 2.1.2、ASIX (亚信)MCS9900-PCIe转4路RS232扩展卡…

【Java基础】19.继承(面向对象的三大特征:封装、继承、多态)

文章目录 前言一、继承的概念二、继承的步骤1.类的继承格式2.继承的实例3.继承类型 三、继承的特性四、继承的关键字1.extends关键字2.implements关键字3.super 与 this 关键字4.final 关键字 五、构造器 前言 一、继承的概念 继承是java面向对象编程技术的一块基石&#xff…

适合生产制造企业用的ERP系统有哪些?

适合生产制造企业用的ERP系统有哪些&#xff1f; 想选择适合生产制造企业的ERP&#xff0c;首先了解市面上有哪些ERP系统 市面上的ERP系统主要分为三大类&#xff1a; 1、垂直领域的ERP系统&#xff1a;这些系统是针对特定行业或垂直市场定制的ERP解决方案&#xff0c;通常具…

功能测试前景揭秘:会被淘汰吗?

在当今快速发展的信息时代&#xff0c;软件已经成为我们工作、学习乃至生活中不可或缺的一部分。随着技术的不断进步和应用的广泛普及&#xff0c;软件测试作为保障软件质量和功能实现的关键步骤&#xff0c;其职业发展路径也受到了广泛的关注。特别是针对功能测试这一细分领域…

我与C++的爱恋:隐式类型转换

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;我与C的爱恋 朋友们大家好&#xff0c;本篇内容我们来介绍初始化列表&#xff0c;隐式类型转换以及explicit的内容 一、初始化列表 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器…

etcd campaign

1. 引言 本文主要讲解使用etcd进行选举的流程&#xff0c;以及对应的缺陷和使用场景 2. etcd选举流程 流程如以代码所示&#xff0c;流程为&#xff1a; clientv3.New 创建client与etcd server建立连接 concurrency.NewSession 创建选举的session&#xff0c;一般会配置ses…

java:Java中的接口

什么是接口 概念&#xff1a; 官方解释&#xff1a;Java接口是一系列方法的声明&#xff0c;是一些方法特征的集合&#xff0c;一个接口只有方法的特征没有方法的实现&#xff0c;因此这些方法可以在不同的地方被不同的类实现&#xff0c;而这些实现可以具有不同的行为&#x…

Java Maven项目推送到 Maven 中央仓库

准备阶段 namespace 域名认证 当需要在 sonatype 认证 com.xxx命名空间时&#xff0c;需要将 .xxx.com 配置域名解析。 记录类型&#xff1a;TXT 文本内容&#xff1a;验证的 key。 GPG 公私钥生成 GPG 下载地址&#xff1a;https://www.gnupg.org/download/index.html M…

零代码编程:用kimichat将mp4视频批量转为mp3音频

一个文件夹里面有多个子文件夹&#xff0c;里面的视频需要转成为mp3音频格式。可以在kimichat中键入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个Python脚本的编写任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;D:\CHATGPT For TikT…

SpringBoot中异步执行事务REQUIRED和REQUIRED_NEW的区别

springboot中事务的使用方式 在spring的bean中&#xff0c;要开启数据库事务只需要在方法中标注注解 Transactional 注解常用的参数有 Class[] rollbackFor() default {} 指定回滚异常Propagation propagation() default Propagation.REQUIRED 事务的传播机制Isolation iso…

【Spring进阶】基于注解的面向切面编程(AOP)详解

hi&#xff0c;我是程序员王也&#xff0c;一个资深Java开发工程师&#xff0c;平时十分热衷于技术副业变现和各种搞钱项目的程序员~&#xff0c;如果你也是&#xff0c;可以一起交流交流。 今天我们聊一聊Spring中的AOP~ AOP的核心概念 面向切面编程&#xff08;AOP&#xff…

【一】ECharts----【基本概念、基本实例】

目录 零.前言 一.ECharts的安装 1.1独立版本的安装 1.2CDN的安装 1.3NPM的安装 二.ECharts实例 三.系列(series) 四.创建一个ECharts图表的基本步骤 4.1创建一个DOM容器 4.2使用DOM节点初始化ECharts对象 4.3设置配置信息 4.3.1图表标题 4.3.2提示信息 4.3.3图例组…

提取点云-------PCL

提取点云 /// <summary> /// VoxelGrid滤波下采样 /// </summary> /// <param name"cloud">需要滤波的点云</param> /// <param name"lx">三维体素栅格的x</param> /// <param name"ly">三维体素栅格…

全新Linux教程-驱动大全-PCI和PCIe子系统-P2-PCI设备的访问方法-非桥设备

主要讲PCI设备的硬件访问方法。 1、PCI的硬件结构 CPU发出的地址是CPU地址&#xff0c;可能是访问底下任何一个设备。地址范围不一样&#xff0c;访问到的外设就不一样。在嵌入式中&#xff0c;通常将4G内存地址空间分成好几个区域&#xff0c;不同的访问分给不同的地址。桥内…

Github首页美化(updating)

Github首页美化 一、新建仓库二、美化Github首页主页访问量统计仓库状态统计常用语言占比统计社交链接 界面展示 一、新建仓库 对Github首页进行美化&#xff0c;需要新建一个仓库名和自己 Github 用户名相同的仓库&#xff1b;并且需要添加一个 README.md自述文件即可。 如果…

nVisual在线网络规划设计软件

●01● nVisual在线网络规划设计软件 在信息化快速发展的今天&#xff0c;网络基础设施的建设与优化变得尤为关键。为了满足现代通信行业对高效、精准的网络规划需求&#xff0c;nVisual在线网络规划设计软件应运而生&#xff0c;它通过集成先进的GIS技术和网络规划工具&#…

sprinboot+vue集成neo4j图数据库

一 、java后台 1.1 package com.admin.domain;/*** 功能描述&#xff1a;** author wangwei* date 2024-01-15 22:13*/ public class ConnectWeb {private String connectWebId;private String connectWebName;private String connectWebInfo;private String personWebIdAlph…

Vue.js------Vue组件基础

能够理解Vue组件概念和作用能够掌握封装创建组件能力能够使用组件之间通信能够完成todo案例 一.Vue组件创建和使用 1.折叠面板-实现多个 创建一个文件夹demo 具体步骤请参考vue.js---vue基础 ⚫ 解决方案: 采用vue提供的单.vue文件-组件方式来封装一套然后复用 在component…