您当前的位置: 首页 > 

韦东山

暂无认证

  • 0浏览

    0关注

    506博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

韦东山freeRTOS系列教程之【第三章】任务管理

韦东山 发布时间:2021-11-19 14:35:57 ,浏览量:0

文章目录
  • 系列教程总目录
  • 概述
  • 3.1 基本概念
  • 3.2 任务创建与删除
    • 3.2.1 什么是任务
    • 3.2.2 创建任务
    • 3.2.3 示例1: 创建任务
    • 3.2.4 示例2: 使用任务参数
    • 3.2.5 任务的删除
    • 3.2.6 示例3: 删除任务
  • 3.3 任务优先级和Tick
    • 3.3.1 任务优先级
    • 3.3.2 Tick
    • 3.3.3 示例4: 优先级实验
    • 3.3.4 示例5: 修改优先级
  • 3.4 任务状态
    • 3.4.1 阻塞状态(Blocked)
    • 3.4.2 暂停状态(Suspended)
    • 3.4.3 就绪状态(Ready)
    • 3.4.4 完整的状态转换图
  • 3.5 Delay函数
    • 3.5.1 两个Delay函数
    • 3.5.2 示例6: Delay
  • 3.6 空闲任务及其钩子函数
    • 3.6.1 介绍
    • 3.6.2 使用钩子函数的前提
  • 3.7 调度算法
    • 3.7.1 重要概念
    • 3.7.2 配置调度算法
    • 3.7.3 示例7: 调度
    • 3.7.4 对比效果: 抢占与否
    • 3.7.5 对比效果: 时间片轮转与否
    • 3.7.6 对比效果: 空闲任务让步

需要获取更好阅读体验的同学,请访问我专门设立的站点查看,地址:http://rtos.100ask.net/

系列教程总目录

本教程连载中,篇章会比较多,为方便同学们阅读,点击这里可以查看文章的 目录列表,目录列表页面地址:https://blog.csdn.net/thisway_diy/article/details/121399484

概述

在本章中,会涉及如下内容:

  • FreeRTOS如何给每个任务分配CPU时间
  • 如何选择某个任务来运行
  • 任务优先级如何起作用
  • 任务有哪些状态
  • 如何实现任务
  • 如何使用任务参数
  • 怎么修改任务优先级
  • 怎么删除任务
  • 怎么实现周期性的任务
  • 如何使用空闲任务
3.1 基本概念

对于整个单片机程序,我们称之为application,应用程序。

使用FreeRTOS时,我们可以在application中创建多个任务(task),有些文档把任务也称为线程(thread)。

在这里插入图片描述

以日常生活为例,比如这个母亲要同时做两件事:

  • 喂饭:这是一个任务
  • 回信息:这是另一个任务

这可以引入很多概念:

  • 任务状态(State):
    • 当前正在喂饭,它是running状态;另一个"回信息"的任务就是"not running"状态
    • "not running"状态还可以细分:
      • ready:就绪,随时可以运行
      • blocked:阻塞,卡住了,母亲在等待同事回信息
      • suspended:挂起,同事废话太多,不管他了
  • 优先级(Priority)
    • 我工作生活兼顾:喂饭、回信息优先级一样,轮流做
    • 我忙里偷闲:还有空闲任务,休息一下
    • 厨房着火了,什么都别说了,先灭火:优先级更高
  • 栈(Stack)
    • 喂小孩时,我要记得上一口喂了米饭,这口要喂青菜了
    • 回信息时,我要记得刚才聊的是啥
    • 做不同的任务,这些细节不一样
    • 对于人来说,当然是记在脑子里
    • 对于程序,是记在栈里
    • 每个任务有自己的栈
  • 事件驱动
    • 孩子吃饭太慢:先休息一会,等他咽下去了、等他提醒我了,再喂下一口
  • 协助式调度(Co-operative Scheduling)
    • 你在给同事回信息
      • 同事说:好了,你先去给小孩喂一口饭吧,你才能离开
      • 同事不放你走,即使孩子哭了你也不能走
    • 你好不容易可以给孩子喂饭了
      • 孩子说:好了,妈妈你去处理一下工作吧,你才能离开
      • 孩子不放你走,即使同事连发信息你也不能走

这涉及很多概念,后续章节详细分析。

3.2 任务创建与删除 3.2.1 什么是任务

在FreeRTOS中,任务就是一个函数,原型如下:

void ATaskFunction( void *pvParameters );

要注意的是:

  • 这个函数不能返回
  • 同一个函数,可以用来创建多个任务;换句话说,多个任务可以运行同一个函数
  • 函数内部,尽量使用局部变量:
    • 每个任务都有自己的栈
    • 每个任务运行这个函数时
      • 任务A的局部变量放在任务A的栈里、任务B的局部变量放在任务B的栈里
      • 不同任务的局部变量,有自己的副本
    • 函数使用全局变量、静态变量的话
      • 只有一个副本:多个任务使用的是同一个副本
      • 要防止冲突(后续会讲)

下面是一个示例:

void ATaskFunction( void *pvParameters )
{
	/* 对于不同的任务,局部变量放在任务的栈里,有各自的副本 */
	int32_t lVariableExample = 0;
	
    /* 任务函数通常实现为一个无限循环 */
	for( ;; )
	{
		/* 任务的代码 */
	}

    /* 如果程序从循环中退出,一定要使用vTaskDelete删除自己
     * NULL表示删除的是自己
     */
	vTaskDelete( NULL );
    
    /* 程序不会执行到这里, 如果执行到这里就出错了 */
}
3.2.2 创建任务

创建任务时使用的函数如下:

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
                        const char * const pcName, // 任务的名字
                        const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节
                        void * const pvParameters, // 调用任务函数时传入的参数
                        UBaseType_t uxPriority,    // 优先级
                        TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务

参数说明:

参数描述pvTaskCode函数指针,可以简单地认为任务就是一个C函数。它稍微特殊一点:永远不退出,或者退出时要调用"vTaskDelete(NULL)"pcName任务的名字,FreeRTOS内部不使用它,仅仅起调试作用。长度为:configMAX_TASK_NAME_LENusStackDepth每个任务都有自己的栈,这里指定栈大小。单位是word,比如传入100,表示栈大小为100 word,也就是400字节。最大值为uint16_t的最大值。怎么确定栈的大小,并不容易,很多时候是估计。精确的办法是看反汇编码。pvParameters调用pvTaskCode函数指针时用到:pvTaskCode(pvParameters)uxPriority优先级范围:0~(configMAX_PRIORITIES – 1)数值越小优先级越低,如果传入过大的值,xTaskCreate会把它调整为(configMAX_PRIORITIES – 1)pxCreatedTask用来保存xTaskCreate的输出结果:task handle。以后如果想操作这个任务,比如修改它的优先级,就需要这个handle。如果不想使用该handle,可以传入NULL。返回值成功:pdPASS;失败:errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY(失败原因只有内存不足)注意:文档里都说失败时返回值是pdFAIL,这不对。pdFAIL是0,errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY是-1。 3.2.3 示例1: 创建任务

代码为:FreeRTOS_01_create_task

使用2个函数分别创建2个任务。

任务1的代码:

void vTask1( void *pvParameters )
{
	const char *pcTaskName = "T1 run\r\n";
	volatile uint32_t ul; /* volatile用来避免被优化掉 */
	
	/* 任务函数的主体一般都是无限循环 */
	for( ;; )
	{
		/* 打印任务1的信息 */
		printf( pcTaskName );
		
		/* 延迟一会(比较简单粗暴) */
		for( ul = 0; ul             
关注
打赏
1658827356
查看更多评论
0.5502s