FreeRTOS学习---“任务”篇

如今,随着的单片机硬件性能不断提升,运行操作系统已经不在话下,所以最近学一下单片机上的这些小型操作系统,知其然即可,知道怎么使用,便是此行主要目的。

总目录

FreeRTOS学习—“任务”篇
FreeRTOS学习—“消息队列”篇
FreeRTOS学习—“信号量”篇
FreeRTOS学习—“事件组”篇
FreeRTOS学习—“定时器”篇

在这里插入图片描述

FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。
由于RTOS需占用一定的系统资源(尤其是RAM资源),只有μC/OS-II、embOS、salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。
相对μC/OS-II、embOS等商业操作系统,FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。
FreeRTOS 是一个可裁剪的小型 RTOS 系统,其特点包括:

  • FreeRTOS 的内核支持抢占式,合作式和时间片调度。 提供了一个用于低功耗的 Tickless 模式。
  • 系统的组件在创建时可以选择动态或者静态的 RAM,比如任务、消息队列、信号量、软件定时器等等。
  • FreeRTOS-MPU 支持 Corex-M 系列中的 MPU 单元,如 STM32F429。
  • FreeRTOS 系统简单、小巧、易用,通常情况下内核占用 4k-9k 字节的空间。
  • 高可移植性,代码主要 C 语言编写。
  • 高效的软件定时器。 强大的跟踪执行功能。
  • 堆栈溢出检测功能。
  • 任务数量不限。
  • 任务优先级不限。

了解一下即可,毕竟咱们不考试。
在这里插入图片描述

演示环境

这里还是用的之前开发用的ESP8266环境。这块芯片已经移植好了FreeRTOS,入口的user_main.c,其实直接就是一个Task,FreeRTOS允许在任务中创建其他任务,所以这里我们也直接进行demo的测试即可。
在这里插入图片描述

demo程序

这里直接上demo程序。

#include <stdio.h>
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

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. */ 
		printf("%s",pcTaskName); 
		vTaskDelay(2000 / portTICK_PERIOD_MS); 
	} 
} 

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. */ 
		printf("%s",pcTaskName); 
		vTaskDelay(2000 / portTICK_PERIOD_MS); 
		//taskYIELD();
	} 
}


/******************************************************************************
 * FunctionName : app_main
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void app_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( ;; ); 

}

这里创建了两个task,每个功能简单,就是输出一句话,然后延迟2秒钟。介绍几个重点
在这里插入图片描述

重点内容

任务创建

portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, 
							const signed portCHAR * const pcName, 
							unsigned portSHORT usStackDepth, 
							void *pvParameters, 
							unsigned portBASE_TYPE uxPriority, 
							xTaskHandle *pxCreatedTask );

参数详解

参数含义
pvTaskCode任务只是永不退出的 C 函数,实现常通常是一个死循环。参数
pcName具有描述性的任务名。这个参数不会被 FreeRTOS 使用。其只是单纯地用于辅助调试。识别一个具有可读性的名字总是比通过句柄来识别容易得多。应用程序可以通过定义常量 config_MAX_TASK_NAME_LEN 来定义任务名的最大长度——包括’\0’结束符。如果传入的字符串长度超过了这个最大值,字符串将会自动被截断。
usStackDepth当任务创建时,内核会分为每个任务分配属于任务自己的唯一状态,usStackDepth值用于告诉内核为它分配多大的栈空间。这个值指定的是栈空间可以保存多少个字(word),而不是多少个字节(byte)。比如说,如果是 32 位宽的栈空间,传入的 usStackDepth值为 100,则将会分配 400 字节的栈空间(100 * 4bytes)。栈深度乘以栈宽度的结果千万不能超过一个 size_t 类型变量所能表达的最大值。应用程序通过定义常量 configMINIMAL_STACK_SIZE 来决定空闲任务任用的栈空间大小。在 FreeRTOS 为微控制器架构提供的Demo 应用程序中,赋予此常量的值是对所有任务的最小建议值。如果你的任务会使用大量栈空间,那么你应当赋予一个更大的值。没有任何简单的方法可以决定一个任务到底需要多大的栈空间。计算出来虽然是可能的,但大多数用户会先简单地赋予一个自认为合理的值,然后利用 FreeRTOS 提供的特性来确证分配的空间既不欠缺也不浪费。
pvParameters任务函数接受一个指向 void 的指针(void*)。pvParameters 的值即是传递到任务中的值。
uxPriority指定任务执行的优先级。优先级的取值范围可以从最低优先级 0 到最高优先级(configMAX_PRIORITIES – 1)。configMAX_PRIORITIES 是一个由用户定义的常量。优先级号并没有上限(除了受限于采用的数据类型和系统的有效内存空间),但最好使用实际需要的最小数值以避免内存浪费。如果 uxPriority 的值超过了(configMAX_PRIORITIES – 1),将会导致实际赋给任务的优先级被自动封顶到最大合法值。
pxCreatedTaskpxCreatedTask 用于传出任务的句柄。这个句柄将在 API 调用中对该创建出来的任务进行引用,比如改变任务优先级,或者删除任务。如果应用程序中不会用到这个任务的句柄,则 pxCreatedTask 可以被设为 NULL。
返回值有两个可能的返回值:1. pdTRUE 表明任务创建成功。
2. errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 由于内存堆空间不足,FreeRTOS 无法分配足够的空间来保存任务结构数据和任务栈,因此无法创建任务。

启动任务

void vTaskStartScheduler( void )

注释掉的原因就是系统在其他地方调用这个,这里不需要执行。仅限于ESP8266这个程序如此。

函数主体

这里就不细说了,每个任务创建都会有一个主体函数,一个死循环的函数。

void vTask1( void *pvParameters ) 

状态切换函数

如果需要多任务进行切换,那么自然需要有一个函数,来使当前任务退出运行态。让其他任务能够进行运行

void vTaskDelay( portTickType xTicksToDelay ); 
参数含义
xTicksToDelay延迟多少个心跳周期。调用该延迟函数的任务将进入阻塞态,经延迟指定的心跳周期数后,再转移到就绪态。
void vTaskDelayUntil( portTickType * pxPreviousWakeTime, portTickType xTimeIncrement ); 
参数含义
pxPreviousWakeTime此参数命名时假定 vTaskDelayUntil()用于实现某个任务以固定频率周期性执行。这种情况下 pxPreviousWakeTime保存了任务上一次离开阻塞态(被唤醒)的时刻。这个时刻被用作一个参考点来计算该任务下一次离开阻塞态的时刻。pxPreviousWakeTime
xTimeIncrement此参数命名时同样是假定 vTaskDelayUntil()用于实现某个任务以固定频率周期性执行 —— 这个频率就是由xTimeIncrement 指定的。xTimeIncrement 的单位是心跳周期,可以使用常量portTICK_RATE_MS 将毫秒转换为心跳周期。

vTaskDelay()指定的延时时间是从调用vTaskDelay()之后(执行完该函数)开始算起的相对时间延迟
vTaskDelayUntil()指定一个绝对时间,每当时间到达,则解除任务阻塞,是绝对时间延迟,更准确。

改变任务优先级

void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );
参数含义
pxTask被修改优先级的任务句柄(即目标任务)——参考 xTaskCreate() API函数的参数 pxCreatedTask 以了解如何得到任务句柄方面的信息。任务可以通过传入 NULL 值来修改自己的优先级。
uxNewPriority目标任务将被设置到哪个优先级上。如果设置的值超过了最大可用优先级(configMAX_PRIORITIES – 1),则会被自动封顶为最大值。常量 configMAX_PRIORITIES 是在 FreeRTOSConfig.h 头文件中设置的一个编译时选项

查询任务优先级

unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );
参数含义
pxTask被查询任务的句柄(目标任务) ——参考 xTaskCreate() API 函数的参数pxCreatedTask 以了解如何得到任务句柄方面的信息。任务可以通过传入 NULL 值来查询自己的优先级。
返回值被查询任务的当前优先级。

注销任务

void vTaskDelete( xTaskHandle pxTaskToDelete );
参数含义
pxTaskToDelete被删除任务的句柄(目标任务) —— 参考 xTaskCreate() API 函数的参数 pxCreatedTask 以了解如何得到任务句柄方面的信息。任务可以通过传入 NULL 值来删除自己。

空闲任务回调函数

void vApplicationIdleHook(void)

空闲的时候,可以做一些操作,但是注意代码一定要简洁,量小。

主动出让CPU

void taskYIELD (void)

主动让出cpu,让同优先级的其他task获得cpu,因为没有其他优先级的task,所以调度器不会切换优先级

结束语

身体到了周一,脑子还停留在周末。下周就好多了,因为下周,没有周一
在这里插入图片描述
FreeRTOS学习—“任务”篇
FreeRTOS学习—“消息队列”篇
FreeRTOS学习—“信号量”篇
FreeRTOS学习—“事件组”篇
FreeRTOS学习—“定时器”篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖哥王老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值