1、FreeRTOS之任务管理

void vTask1( void *pvParameters ) 
{ 
	const char *pcTaskName = "Task 1 is running\r\n"; 
	volatile unsigned long ul; 
	/* 和大多数任务一样,该任务处于一个死循环中。 */ 
	for( ;; ) 
	{ 
		/* Print out the name of this task. */ 
		vPrintString( pcTaskName ); 
		/* 延迟,以产生一个周期 */ 
	for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ ) 
	{ 
		/* 这个空循环是最原始的延迟实现方式。在循环中不做任何事情。后面的示例程序将采用
		delay/sleep函数代替这个原始空循环。 */ 
	} 
	} 
}

void vTask2( void *pvParameters ) 
{ 
	const char *pcTaskName = "Task 2 is running\r\n"; 
	volatile unsigned long ul; 
	/* 和大多数任务一样,该任务处于一个死循环中。 */ 
	for( ;; ) 
	{ 
		/* Print out the name of this task. */ 
		vPrintString( pcTaskName ); 
		/* 延迟,以产生一个周期 */ 
	for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ ) 
	{ 
		/* 这个空循环是最原始的延迟实现方式。在循环中不做任何事情。后面的示例程序将采用
		delay/sleep函数代替这个原始空循环。 */ 
	} 
	} 
}

int main( void ) 
{ 
	/* 创建第一个任务。需要说明的是一个实用的应用程序中应当检测函数xTaskCreate()的返回值,以确保任
	务创建成功。 */ 
	xTaskCreate( vTask1, /* 指向任务函数的指针 */ 
	"Task 1", /* 任务的文本名字,只会在调试中用到 */ 
	1000, /* 栈深度 – 大多数小型微控制器会使用的值会比此值小得多 */ 
	NULL, /* 没有任务参数 */ 
	1, /* 此任务运行在优先级1上. */ 
	NULL ); /* 不会用到任务句柄 */ 
	/* Create the other task in exactly the same way and at the same priority. */ 
	xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL ); 
	/* 启动调度器,任务开始执行 */ 
	vTaskStartScheduler(); 
	/* 如果一切正常,main()函数不应该会执行到这里。但如果执行到这里,很可能是内存堆空间不足导致空闲
	任务无法创建。第五章有讲述更多关于内存管理方面的信息 */ 
	for( ;; ); 
}

 在任务1种创建任务2

void vTask1( void *pvParameters ) 
{ 
	const char *pcTaskName = "Task 1 is running\r\n"; 
	volatile unsigned long ul; 
	/* 如果已经执行到本任务的代码,表明调度器已经启动。在进入死循环之前创建另一个任务。 */ 
	xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL ); 
	for( ;; ) 
	{ 
		/* Print out the name of this task. */ 
		vPrintString( pcTaskName ); 
		/* Delay for a period. */ 
	for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ ) 
	{ 
		/* This loop is just a very crude delay implementation. There is 
		nothing to do in here. Later examples will replace this crude 
		loop with a proper delay/sleep function. */ 
	} 
	} 
}

 用一个任务函数代替任务1任务2

void vTaskFunction( void *pvParameters ) 
{ 
	char *pcTaskName; 
	volatile unsigned long ul; 
	/* 需要打印输出的字符串从入口参数传入。强制转换为字符指针。 */ 
	pcTaskName = ( char * ) pvParameters; 
	/* As per most tasks, this task is implemented in an infinite loop. */ 
	for( ;; ) 
	{ 
		/* Print out the name of this task. */ 
		vPrintString( pcTaskName ); 
		/* Delay for a period. */ 
	for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ ) 
	{ 
		/* This loop is just a very crude delay implementation. There is 
		nothing to do in here. Later exercises will replace this crude 
		loop with a proper delay/sleep function. */ 
	} 
	} 
}

/* 定义将要通过任务参数传递的字符串。定义为const,且不是在栈空间上,以保证任务执行时也有效。 */ 
static const char *pcTextForTask1 = “Task 1 is running\r\n”; 
static const char *pcTextForTask2 = “Task 2 is running\t\n”; 
int main( void ) 
{ 
	/* Create one of the two tasks. */ 
	xTaskCreate( vTaskFunction, /* 指向任务函数的指针. */ 
	"Task 1", /* 任务名. */ 
	1000, /* 栈深度. */ 
	(void*)pcTextForTask1, /* 通过任务参数传入需要打印输出的文本. */ 
	1, /* 此任务运行在优先级1上. */ 
	NULL ); /* 不会用到此任务的句柄. */ 
	/* 同样的方法创建另一个任务。至此,由相同的任务代码(vTaskFunction)创建了多个任务,仅仅是传入
	的参数不同。同一个任务创建了两个实例。 */ 
	xTaskCreate( vTaskFunction, "Task 2", 1000, (void*)pcTextForTask2, 1, NULL ); 
	/* Start the scheduler so our tasks start executing. */ 
	vTaskStartScheduler(); 
	/* If all is well then main() will never reach here as the scheduler will 
	now be running the tasks. If main() does reach here then it is likely that 
	there was insufficient heap memory available for the idle task to be created. 
	CHAPTER 5 provides more information on memory management. */ 
	for( ;; ); 
}

void vTaskFunction( void *pvParameters ) 
{ 
	char *pcTaskName; 
	/* The string to print out is passed in via the parameter. Cast this to a 
	character pointer. */ 
	pcTaskName = ( char * ) pvParameters; 
	/* As per most tasks, this task is implemented in an infinite loop. */ 
	for( ;; ) 
	{ 
		/* Print out the name of this task. */ 
		vPrintString( pcTaskName ); 
		/* 延迟一个循环周期。调用vTaskDelay()以让任务在延迟期间保持在阻塞态。延迟时间以心跳周期为
		单位,常量portTICK_RATE_MS可以用来在毫秒和心跳周期之间相换转换。本例设定250毫秒的循环周
		期。 */ 
		vTaskDelay( 250 / portTICK_RATE_MS ); 
	} 
}

vTaskDelayUntil函数的使用 

void vTaskFunction( void *pvParameters ) 
{ 
	char *pcTaskName; 
	portTickType xLastWakeTime; 
	/* The string to print out is passed in via the parameter. Cast this to a 
	character pointer. */ 
	pcTaskName = ( char * ) pvParameters; 
	/* 变量xLastWakeTime需要被初始化为当前心跳计数值。说明一下,这是该变量唯一一次被显式赋值。之后,
	xLastWakeTime将在函数vTaskDelayUntil()中自动更新。 */ 
	xLastWakeTime = xTaskGetTickCount(); 
	/* As per most tasks, this task is implemented in an infinite loop. */ 
	for( ;; ) 
	{ 
		/* Print out the name of this task. */ 
		vPrintString( pcTaskName ); 
		/* 本任务将精确的以250毫秒为周期执行。同vTaskDelay()函数一样,时间值是以心跳周期为单位的,
		可以使用常量portTICK_RATE_MS将毫秒转换为心跳周期。变量xLastWakeTime会在
		vTaskDelayUntil()中自动更新,因此不需要应用程序进行显示更新。 */ 
		vTaskDelayUntil( &xLastWakeTime, ( 250 / portTICK_RATE_MS ) ); 
	} 
}

 

定义一个空闲任务钩子函数

/* Declare a variable that will be incremented by the hook function. */ 
unsigned long ulIdleCycleCount = 0UL; 
/* 空闲钩子函数必须命名为vApplicationIdleHook(),无参数也无返回值。 */ 
void vApplicationIdleHook( void ) 
{ 
	/* This hook function does nothing but increment a counter. */ 
	ulIdleCycleCount++; 
}

改变任务优先级

  通过调用 vTaskPrioritySet() API 函数来改变两个任务的相对优先级 

void vTask1( void *pvParameters ) 
{ 
	unsigned portBASE_TYPE uxPriority; 
	/* 本任务将会比任务2更先运行,因为本任务创建在更高的优先级上。任务1和任务2都不会阻塞,所以两者要
	么处于就绪态,要么处于运行态。
	查询本任务当前运行的优先级 – 传递一个NULL值表示说“返回我自己的优先级”。 */ 
	uxPriority = uxTaskPriorityGet( NULL ); 
	for( ;; ) 
	{ 
		/* Print out the name of this task. */ 
		vPrintString( "Task1 is running\r\n" ); 
		/* 把任务2的优先级设置到高于任务1的优先级,会使得任务2立即得到执行(因为任务2现在是所有任务
		中具有最高优先级的任务)。注意调用vTaskPrioritySet()时用到的任务2的句柄。程序清单24将展示
		如何得到这个句柄。 */ 
		vPrintString( "About to raise the Task2 priority\r\n" ); 
		vTaskPrioritySet( xTask2Handle, ( uxPriority + 1 ) ); 
		/* 本任务只会在其优先级高于任务2时才会得到执行。因此,当此任务运行到这里时,任务2必然已经执
		行过了,并且将其自身的优先级设置回比任务1更低的优先级。 */ 
	} 
}

void vTask2( void *pvParameters ) 
{ 
	unsigned portBASE_TYPE uxPriority; 
	/* 任务1比本任务更先启动,因为任务1创建在更高的优先级。任务1和任务2都不会阻塞,所以两者要么处于
	就绪态,要么处于运行态。
	查询本任务当前运行的优先级 – 传递一个NULL值表示说“返回我自己的优先级”。 */ 
	uxPriority = uxTaskPriorityGet( NULL ); 
	for( ;; ) 
	{ 
		/* 当任务运行到这里,任务1必然已经运行过了,并将本身务的优先级设置到高于任务1本身。 */ 
		vPrintString( "Task2 is running\r\n" ); 
		/* 将自己的优先级设置回原来的值。传递NULL句柄值意味“改变我己自的优先级”。把优先级设置到低
		于任务1使得任务1立即得到执行 – 任务1抢占本任务。 */ 
		vPrintString( "About to lower the Task2 priority\r\n" ); 
		vTaskPrioritySet( NULL, ( uxPriority - 2 ) ); 
	} 
}

/* 声明变量用于保存任务2的句柄。 */ 
xTaskHandle xTask2Handle; 
int main( void ) 
{ 
	/* 任务1创建在优先级2上。任务参数没有用到,设为NULL。任务句柄也不会用到,也设为NULL */ 
	xTaskCreate( vTask1, "Task 1", 1000, NULL, 2, NULL ); 
	/* The task is created at priority 2 ______^. */ 
	/* 任务2创建在优先级1上 – 此优先级低于任务1。任务参数没有用到,设为NULL。但任务2的任务句柄会被
	用到,故将xTask2Handle的地址传入。 */ 
	xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, &xTask2Handle ); 
	/* The task handle is the last parameter _____^^^^^^^^^^^^^ */ 
	/* Start the scheduler so the tasks start executing. */ 
	vTaskStartScheduler(); 
	/* If all is well then main() will never reach here as the scheduler will 
	now be running the tasks. If main() does reach here then it is likely that 
	there was insufficient heap memory available for the idle task to be created. 
	CHAPTER 5 provides more information on memory management. */ 
	for( ;; ); 
}

删除任务

其行为如下:

任务 1 main() 创建在优先级 1 上。任务 1 运行时,以优先级 2 创建任务 2 。现
在任务 2 具有最高优先级,所以会立即得到执行。
任务 2 什么也没有做,只是删除自己。可以通过传递 NULL 值以 vTaskDelete()
来删除自己,但是为了纯粹的演示,传递的是任务自己的句柄。
当任务 2 被自己删除之后,任务 1 成为最高优先级的任务,所以继续执行,调用
vTaskDelay() 阻塞一小段时间。
当任务 1 进入阻塞状态后,空闲任务得到执行的机会。空闲任务会释放内核为已
删除的任务 2 分配的内存。
任务 1 离开阻塞态后,再一次成为就绪态中具有最高优先级的任务,因此会抢占
空闲任务。又再一次创建任务 2 ,如此往复。
int main( void ) 
{ 
	/* 任务1创建在优先级1上 */ 
	xTaskCreate( vTask1, "Task 1", 1000, NULL, 1, NULL ); 
	/* The task is created at priority 1 ______^. */ 
	/* Start the scheduler so the tasks start executing. */ 
	vTaskStartScheduler(); 
	/* main() should never reach here as the scheduler has been started. */ 
	for( ;; ); 
}

void vTask1( void *pvParameters ) 
{ 
	const portTickType xDelay100ms = 100 / portTICK_RATE_MS; 
	for( ;; ) 
	{ 
		/* Print out the name of this task. */ 
		vPrintString( "Task1 is running\r\n" ); 
		/* 创建任务2为最高优先级。 */ 
		xTaskCreate( vTask2, "Task 2", 1000, NULL, 2, &xTask2Handle ); 
		/* The task handle is the last parameter _____^^^^^^^^^^^^^ */ 
		/* 因为任务2具有最高优先级,所以任务1运行到这里时,任务2已经完成执行,删除了自己。任务1得以
		执行,延迟100ms */ 
		vTaskDelay( xDelay100ms ); 
	} 
}

void vTask2( void *pvParameters ) 
{ 
	/* 任务2什么也没做,只是删除自己。删除自己可以传入NULL值,这里为了演示,还是传入其自己的句柄。 */ 
	vPrintString( "Task2 is running and about to delete itself\r\n" ); 
	vTaskDelete( xTask2Handle ); 
}

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

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

相关文章

腾讯云图形验证码的PHP示例

需要准备的 1.API密钥 SecretId 及 SecretKey 两部分&#xff0c; SecretId 用于标识 API 调用者的身份&#xff0c; SecretKey 用于加密签名字符串和服务器端验证签名字符串的密钥。 前往API密钥管理页面&#xff0c;即可进行获取 https://console.cloud.tencent.com/cam/ca…

切面条-蓝桥杯?-Lua 中文代码解题第1题

切面条-蓝桥杯&#xff1f;-Lua 中文代码解题第1题 一根高筋拉面&#xff0c;中间切一刀&#xff0c;可以得到2根面条。 如果先对折1次&#xff0c;中间切一刀&#xff0c;可以得到3根面条。 如果连续对折2次&#xff0c;中间切一刀&#xff0c;可以得到5根面条。 那么&#xf…

【二】【单片机】有关独立按键的实验

自定义延时函数Delay 分别用Delay.c文件存储Delay函数。用Delay.h声明Delay函数。每次将这两个文件复制到工程中&#xff0c;直接使用。 //Delay.c void Delay(unsigned int xms) //11.0592MHz {while(xms--){unsigned char i, j;i 2;j 199;do{while (--j);}…

web高可用集群(nginx负载均衡+keepalived实现调度器HA)

web高可用集群(nginx负载均衡keepalived实现调度器HA&#xff09; 主机IP地址代理服务器192.168.88.66代理服务器192.168.88.38Real server192.168.88.10Real server192.168.88.20 配置俩台Real server [rootweb1 ~]# vim /etc/yum.repos.d/nginx.repo [rootweb1 ~]# cat /e…

图解缓存淘汰算法 LRU、LFU | 最近最少使用、最不经常使用算法 | go语言实现

写在前面 无论是什么系统&#xff0c;在研发的过程中不可避免的会使用到缓存&#xff0c;而缓存一般来说我们不会永久存储&#xff0c;但是缓存的内容是有限的&#xff0c;那么我们如何在有限的内存空间中&#xff0c;尽可能的保留有效的缓存信息呢&#xff1f; 那么我们就可以…

AI毕业论文降重GPTS,避免AI检测,高效完成论文

视频演示 AI毕业论文降重GPTS&#xff0c;避免AI检测&#xff0c;高效完成论文&#xff01; 开发目的 “毕业论文降重”GPTS应用&#xff0c;作用为&#xff1a;重新表述学术论文&#xff0c;降低相似性评分&#xff0c;避免AI检测。 使用地址 地址&#xff1a;毕业论文降重…

浏览器如何进行静态资源缓存?—— 强缓存 协商缓存

在平时使用浏览器排查问题的过程中&#xff0c;我们有时会看到浏览器网络请求中出现304状态码&#xff0c;那么是什么情况下出现304呢&#xff1f;下面是关于这一现象的解释&#xff1a; 浏览器如何进行静态资源缓存&#xff1f;—— 强缓存 & 协商缓存 状态码 304浏览器如…

springboot基于spring boot的在线答题微信小程序

摘 要 在线答题微信小程序是考试中重要的一环&#xff0c;在线答题是学生获取任务信息的主要渠道。为了方便学生能够在网站上查看任务信息、考试&#xff0c;于是开发了基于 springboot框架设计与实现了一款简洁、轻便的在线答题微信小程序。本微信小程序解决了在线答题事务中的…

linux源配置:ubuntu、centos

1、ubuntu源配置 1&#xff09;先查电脑版本型号: lsb_release -c2&#xff09;再编辑源更新&#xff0c;源要与上面型号对应 参考&#xff1a;https://midoq.github.io/2022/05/30/Ubuntu20-04%E6%9B%B4%E6%8D%A2%E5%9B%BD%E5%86%85%E9%95%9C%E5%83%8F%E6%BA%90/ /etc/apt/…

HTTPS(超文本传输安全协议)工作过程

一、简述HTTPS HTTPS超文本传输协议&#xff08;全称&#xff1a;Hypertext Transfer Protocol Secure &#xff09;&#xff0c;是以安全为目标的 HTTP 通道&#xff0c;在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性 。HTTPS 在HTTP 的基础下加入SSL&#x…

【JavaScript】JavaScript 运算符 ④ ( 逻辑运算符 | 逻辑与运算符 | 逻辑或运算符 || | 逻辑非运算符 ! )

文章目录 一、JavaScript 逻辑运算符1、逻辑运算符 概念2、逻辑与运算符 &&3、逻辑或运算符 ||4、逻辑非运算符 !5、完整代码示例 一、JavaScript 逻辑运算符 1、逻辑运算符 概念 JavaScript 中的 逻辑运算符 的作用是 对 布尔值 进行运算 , 运算完成 后 的 返回值 也是…

数据可视化-ECharts Html项目实战(1)

在之前的文章中&#xff0c;我们学习了如何安装Visual Studio Code并下载插件&#xff0c;想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢。 安装 Visual Studio…

深度学习-解读GoogleNet深度学习网络

深度学习-解读GoogleNet深度学习网络 深度学习中&#xff0c;经典网络引领一波又一波的技术革命&#xff0c;从LetNet到当前最火的GPT所用的Transformer&#xff0c;它们把AI技术不断推向高潮。2012年AlexNet大放异彩&#xff0c;它把深度学习技术引领第一个高峰&#xff0c;打…

单片机FLASH深度解析和编程实践(下)

本篇文章将同大家分享单片机FLASH编程的相关寄存器和寄存器操作及库函数操作。本篇文章依然以STM32单片机为例进行解析。有关FLASH的基本原理和实现方法&#xff0c;大家可以参考上一篇文章&#xff1a;单片机FLASH深度解析和编程实践&#xff08;上&#xff09;-CSDN博客 目录…

T1.数据库MySQL

二.SQL分类 2.1 DDL 2.1.1数据库操作 1). 查询所有数据库 show databases ; 2). 查询当前数据库 select database(); 3)创建数据库 create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则] ; 4&#xff09;删除数据库 drop database …

upload-labs通关方式

pass-1 通过弹窗可推断此关卡的语言大概率为js&#xff0c;因此得出两种解决办法 方法一 浏览器禁用js 关闭后就逃出了js的验证就可以正常php文件 上传成功后打开图片链接根据你写的一句话木马执行它&#xff0c;我这里采用phpinfo&#xff08;&#xff09; 方法二 在控制台…

C到C++的敲门砖-1

文章目录 关键字命名空间输入和输出缺省参数函数重载 关键字 相较于C语言32个关键字&#xff1a; autodoubleintstructbreakelselongswitchcaseenumregistertypedefcharexternreturnunionconstfloatshortunsignedcontinueforsignedvoiddefaultgotosizeofvolatiledoifwhilesta…

实现兼容性良好的前端页面开发

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

python自动化之(django)(2)

1、创建应用 python manage.py startapp apitest 这里还是从上节开始也就是命令行在所谓的autotest目录下来输入 然后可以清楚的看到 多了一个文件夹 2、创建视图 在views中加入test函数&#xff08;所建应用下&#xff09; from django.http import HttpResponse def tes…

Day40:安全开发-JavaEE应用SpringBoot框架JWT身份鉴权打包部署JARWAR

目录 SpringBoot-身份鉴权-JWT技术 SpringBoot-打包部署-JAR&WAR 思维导图 Java知识点 功能&#xff1a;数据库操作&#xff0c;文件操作&#xff0c;序列化数据&#xff0c;身份验证&#xff0c;框架开发&#xff0c;第三方组件使用等. 框架库&#xff1a;MyBatis&…