【FreeRTOS】任务管理与调度

文章目录

  • 调度:
  • 总结


调度:

  1. 相同优先级的任务轮流运行
  2. 最高优先级的任务先运行

可以得出结论如下:

  • a 高优先级的任务在运行,未执行完,更低优先级的任务无法运行
  • b 一旦高优先级任务就绪,它会马上运行(假设厨房着火了,会马上去灭火)
  • c 如果最高优先级的任务有多个,他们轮流运行

他们都是使用链表进行管理

打开CubeMX,最高优先级56
在这里插入图片描述
在这里插入图片描述

56个List,

RadeyList[55] —>优先级为55的,处于就绪态的任务
RadeyList[54] —>优先级为54的,处于就绪态的任务
……
RadeyList[N] —>优先级为N的,处于就绪态的任务
……
RadeyList[0]

我们一开始创建了好几个任务,优先级默认都是osPriorityNormal=24

  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); // 默认任务/* 创建任务:光 */ // 创建一个静态分配内存的任务xLightTaskHandle = xTaskCreateStatic(Led_Test,           //LED测试函数,PC13以500ms间隔亮灭一次"LightTask",        //光任务128,                //栈大小,这里提供了栈的大小(长度)NULL,               //无传入的参数osPriorityNormal,   //优先级默认g_pucStackOfLightTask,  // 静态分配的栈,一个buffer,这里只提供了首地址,长度就是栈的大小,最开始栈的类型不对,栈的类型uint32_t&g_TCBofLightTask       // 取址TCB);/* 创建任务:色 */ xColorTaskHandle = xTaskCreateStatic(ColorLED_Test,           //LED测试函数,PC13以500ms间隔亮灭一次"ColorTask",        //光任务128,                //栈大小,这里提供了栈的大小(长度)NULL,               //无传入的参数osPriorityNormal,   //优先级默认g_pucStackOfColorTask,  // 静态分配的栈,一个buffer,这里只提供了首地址,长度就是栈的大小&g_TCBofColorTask       // 取址TCB);

执行完上面的程序之后,会创建三个任务, 放在 RadeyList[24] 这个链表里面~其他链表都是空的

这里是怎么调度的呢?

启动调度器后
执行

osStatus_t osKernelStart (void) {osStatus_t stat;if (IS_IRQ()) {stat = osErrorISR;}else {if (KernelState == osKernelReady) {KernelState = osKernelRunning;vTaskStartScheduler();stat = osOK;} else {stat = osError;}}return (stat);
}

执行完之后,这里就创建了一个空闲的任务

在这里插入图片描述

void vTaskStartScheduler( void )
{
BaseType_t xReturn;/* Add the idle task at the lowest priority. */#if( configSUPPORT_STATIC_ALLOCATION == 1 ){StaticTask_t *pxIdleTaskTCBBuffer = NULL;StackType_t *pxIdleTaskStackBuffer = NULL;uint32_t ulIdleTaskStackSize;/* The Idle task is created using user provided RAM - obtain theaddress of the RAM then create the idle task. */vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );xIdleTaskHandle = xTaskCreateStatic(	prvIdleTask,configIDLE_TASK_NAME,ulIdleTaskStackSize,( void * ) NULL, /*lint !e961.  The cast is not redundant for all compilers. */( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),pxIdleTaskStackBuffer,pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */if( xIdleTaskHandle != NULL ){xReturn = pdPASS;}else{xReturn = pdFAIL;}}#else{/* The Idle task is being created using dynamically allocated RAM. */xReturn = xTaskCreate(	prvIdleTask,configIDLE_TASK_NAME,configMINIMAL_STACK_SIZE,( void * ) NULL,( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),&xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */}#endif /* configSUPPORT_STATIC_ALLOCATION */#if ( configUSE_TIMERS == 1 ){if( xReturn == pdPASS ){xReturn = xTimerCreateTimerTask();}else{mtCOVERAGE_TEST_MARKER();}}#endif /* configUSE_TIMERS */if( xReturn == pdPASS ){/* freertos_tasks_c_additions_init() should only be called if the userdefinable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that isthe only macro called by the function. */#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT{freertos_tasks_c_additions_init();}#endif/* Interrupts are turned off here, to ensure a tick does not occurbefore or during the call to xPortStartScheduler().  The stacks ofthe created tasks contain a status word with interrupts switched onso interrupts will automatically get re-enabled when the first taskstarts to run. */portDISABLE_INTERRUPTS();#if ( configUSE_NEWLIB_REENTRANT == 1 ){/* Switch Newlib's _impure_ptr variable to point to the _reentstructure specific to the task that will run first. */_impure_ptr = &( pxCurrentTCB->xNewLib_reent );}#endif /* configUSE_NEWLIB_REENTRANT */xNextTaskUnblockTime = portMAX_DELAY;xSchedulerRunning = pdTRUE;xTickCount = ( TickType_t ) 0U;/* If configGENERATE_RUN_TIME_STATS is defined then the followingmacro must be defined to configure the timer/counter used to generatethe run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATSis set to 0 and the following line fails to build then ensure you do nothave portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in yourFreeRTOSConfig.h file. */portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();/* Setting up the timer tick is hardware specific and thus in theportable interface. */if( xPortStartScheduler() != pdFALSE ){/* Should not reach here as if the scheduler is running thefunction will not return. */}else{/* Should only reach here if a task calls xTaskEndScheduler(). */}}else{/* This line will only be reached if the kernel could not be started,because there was not enough FreeRTOS heap to create the idle taskor the timer task. */configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );}/* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,meaning xIdleTaskHandle is not used anywhere else. */( void ) xIdleTaskHandle;
}

函数名:prvIdleTask 空闲任务

现在的链表

在这里插入图片描述

在这里插入图片描述
这句话是把这个新的任务添加进ReadyList,添加进就绪列表,根据优先级找到链表

还有一个全局变量当前TCB

在这里插入图片描述
最开始只有StartDefaultTask这一个任务,那么全局指针pxCurrentTCB就指向这个任务

在这里插入图片描述

当我们创建led的任务时,指针指向Led_Test
在这里插入图片描述

当创建ColorLED_Test时候,指针就指向了ColorLED_Test
在这里插入图片描述

启动调度器的时候,创建了一个空闲任务,但是优先级是0,优先级比较低,pxCurrentTCB保留,还是指向ColorLED_Test

当我们真正启动调度器的时候,就从ColorLED_Test任务开始,先运行最后创建的任务

  • =这就是06_create_task_use_params里,后面创建的task3最先开始运行的原因!!!=

在系统里,会初始化一个Tick,Tick中断里面有计数累加,作为时钟基准,并且会调度

cubemx定义了一个时钟,频率是1000,每1ms产生一次中断
在这里插入图片描述

Tick中断:

  1. 计数累加,作为时钟基准
  2. 并且会发起调度

调度:从上到下遍历ReadyList,找到24的时候,非空,然后指向下一个任务

  • 遍历ReadyList,找到第一个非空的链表,把pxCurrentTCB指向下一个任务,然后启动

在这里插入图片描述

运行1ms之后,计数值又累计,发起下一次调度,再次遍历这些链表,从上面找到下面,找到第24个不空,把pxCurrentTCB指向下一个任务,然后启动

在这里插入图片描述

下一次调度

在这里插入图片描述

上面就是轮流运行这些相同优先级的就绪态任务的,运行依赖于tick中断,依赖于调度机制

在默认任务里,读取遥控器的键值,如果是播放按键,会创建一个播放音乐的任务,优先级是25,如图所示:

在这里插入图片描述

这个任务马上处于就绪态,并且是最高优先级,所以会马上运行这个任务

在这里插入图片描述

当执行到vTaskDelay的时候,现在是Blocked状态,已经不是Ready状态了,现在就会从25优先级的链表中删除,移动到某一个delay的链表里,有DelayedTaskList1和DelayedTaskList2(这里是防止定时器溢出,才有两个delay链表)

在这里插入图片描述

假设存放到DelayedTaskList1里了,下一次Tick中断的时候,现在又要发起一次调度,重新遍历……
取出下一个任务来运行(上次运行的是任务1,下一个任务就是任务2)
在这里插入图片描述

下一次中断,在调度如下图所示:

在这里插入图片描述

在Tick中断里发起一个比较复杂的调度,同时也判断一下delay链表你的时间有没有到,如果时间到了,就把它放入就绪链表

  1. 计数值 ++
  2. 判断DelayedTaskList里的任务是否可恢复,
  3. 发起调度

假设5号任务是2个Tick,5号任务的Tick已经到了,就需要把这个5号任务从delay链表里移动到第25个优先级的链表中去

然后发起一个调度,再遍历所有链表,发现25非空,就执行5号任务~

在5号任务里又使用了delay,又把这个任务放到DelayedTaskList里

在这里插入图片描述

然后遍历整个链表,发现第24项非空,又执行下一个任务(任务1)

在这里插入图片描述

假设在任务1里又调用了这个函数(按下了播放键,暂停的功能)
在这里插入图片描述

这个任务被暂停了,是不可能通过Tick中断唤醒的,只能Resume(从链表中移除,重新叨叨ReadyList里)

上面全是链表的操作


总结

  • 在Tick中断里计数值++
  • 判断DelaydeTaskList里的任务是否可以被恢复,如果时间到了,就移动到就绪态链表中
  • 发起调度,在找到非空链表中,找到下一个任务运行~

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

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

相关文章

Postman Postman接口测试工具使用简介

Postman这个接口测试工具的使用做个简单的介绍,仅供参考。 插件安装 1)下载并安装chrome浏览器 2)如下 软件使用说明

从零入手人工智能(5)—— 决策树

1.前言 在上一篇文章《从零入手人工智能(4)—— 逻辑回归》中讲述了逻辑回归这个分类算法,今天我们的主角是决策树。决策树和逻辑回归这两种算法都属于分类算法,以下是决策树和逻辑回归的相同点: 分类任务&#xff1…

椭圆的矩阵表示法

椭圆的矩阵表示法 flyfish 1. 标准几何表示法 标准几何表示法是通过椭圆的几何定义来表示的: x 2 a 2 y 2 b 2 1 \frac{x^2}{a^2} \frac{y^2}{b^2} 1 a2x2​b2y2​1其中, a a a 是椭圆的长半轴长度, b b b 是椭圆的短半轴长度。 2.…

三十八篇:架构大师之路:探索软件设计的无限可能

架构大师之路:探索软件设计的无限可能 1. 引言:架构的艺术与科学 在软件工程的广阔天地中,系统架构不仅是设计的骨架,更是灵魂所在。它如同建筑师手中的蓝图,决定了系统的结构、性能、可维护性以及未来的扩展性。本节…

AWS-PatchAsgInstance自动化定时ASG组打补丁

问题 需要给AWS的EC2水平自动扩展组AutoScaling Group(ASG)中的EC2自动定期打补丁。 创建自动化运行IAM角色 找到创建角色入口页面,如下图: 开始创建Systems Manager自动化运行的IAM角色,如下图: 设置…

2023-2024 学年第二学期小学数学六年级期末质量检测模拟(制作:王胤皓)(90分钟)

word效果预览: 一、我会填 1. 1.\hspace{0.5em} 1. 一个多位数,亿位上是次小的素数,千位上是最小的质数的立方,十万位是 10 10 10 和 15 15 15 的最大公约数,万位是最小的合数,十位上的数既不是质数也…

体验了一下AI生产3D模型有感

我的实验路子是想试试能不能帮我建一下实物模型 SO 我选择了一个成都环球中心的网图 但是生成的结果掺不忍睹,但是看demo来看,似乎如果你能给出一张干净的提示图片,他还是能做出一些东西的 这里我延申的思考是这个物体他如果没看过背面&…

大型企业网络DHCP服务器配置安装实践@FreeBSD

企业需求 需要为企业里的机器配置一台DHCP服务器。因为光猫提供DHCP服务的能力很差,多机器dhcp多机器NAT拓扑方式机器一多就卡顿。使用一台路由器来进行子网络的dhcp和NAT服务,分担光猫负载,但是还有一部分机器需要放到光猫网络,…

torchinfo这个包中的summary真的很好用

1.安装直接使用 pip 进行安装即可: pip install torchinfo 2.导入该模块 from torchinfo import summary 3.使用模块 summary(model)#这里的model是你自己的model,可以添加参数进去 4.效果图: 第一个图片是直接打印model吗,…

SpringBoot+ENC实现密钥加密及使用原理

😊 作者: 一恍过去 💖 主页: https://blog.csdn.net/zhuocailing3390 🎊 社区: Java技术栈交流 🎉 主题: SpringBootENC实现密钥加密及使用原理 ⏱️ 创作时间: 202…

K8s部署高可用Jenkins

小伙伴们大家好呀!断更了近一个月,XiXi去学习了一下K8s和Jenkins的相关技术。学习内容有些庞杂,近一个月的时间里我只学会了一些皮毛,更多的内容还需要后面不断学习,不断积累。最主要的是云主机真得很贵,为…

注意 llamaIndex 中 Chroma 的坑!

llamaIndex 做索引是默认存在内存中,由于索引需要通过网络调用 API,而且索引是比较耗时的操作,为了避免每次都进行索引,使用向量数据库进行 Embedding 存储以提高效率。首先将 Document 解析成 Node,索引时调用 Embedd…

一、系统学习微服务遇到的问题集合

1、启动了nacos服务&#xff0c;没有在注册列表 应该是版本问题 Alibaba-nacos版本 nacos-文档 Spring Cloud Alibaba-中文 Spring-Cloud-Alibaba-英文 Spring-Cloud-Gateway 写的很好的一篇文章 在Spring initial上面配置 start.aliyun.com 重新下载 < 2、 No Feign…

力扣SQL50 求关注者的数量 分组计数

Problem: 1729. 求关注者的数量 Code select user_id, count(1) followers_count from Followers group by user_id order by user_id;

运算放大器(运放)低通滤波反相放大器电路和积分器电路

低通滤波反相放大器电路 运放积分器电路请访问下行链接 运算放大器(运放)积分器电路 设计目标 输入ViMin输入ViMax输出VoMin输出VoMaxBW&#xff1a;fp电源Vee电源Vcc–0.1V0.1V–2V2V2kHz–2.5V2.5V 设计说明 这款可调式低通反相放大器电路可将信号电平放大 26dB 或 20V/…

全面理解-Flutter(万字长文,深度解析)

1、Web 性能差&#xff0c;跟原生 App 存在肉眼可见的差距&#xff1b; 2、React Native 跟 Web 相比&#xff0c;支持的能力非常有限&#xff0c;特定长场景问题&#xff0c;需要三端团队一个一个处理&#xff1b; 3、Web 浏览器的安卓碎片化严重&#xff08;感谢 X5&#x…

【C++算法】——高精度(加,减,乘,除)

前言 高精度算法就是为了去解决一些比较大的数&#xff0c;这些数大到long long都存不下。&#xff0c;这里的主要思想就是用字符串来存。 下面的内容有很多用到c的容器&#xff0c;不明白的可以先去学习stl。 一 高精度加法 首先第一步就是去模拟我们自己写的加法&#xff…

Nikto一键扫描Web服务器(KALI工具系列三十)

目录 1、KALI LINUX 简介 2、Nikto工具简介 3、信息收集 3.1 目标IP&#xff08;服务器) 3.2kali的IP 4、操作实例 4.1 基本扫描 4.2 扫描特定端口 4.3 保存扫描结果 4.4 指定保存格式 4.5 连接尝试 4.6 仅扫描文件上传 5、总结 1、KALI LINUX 简介 Kali Linux 是一…

2024最新版:C++用Vcpkg搭配VS2022安装matplotlib-cpp库

matplotlib-cpp是一个用于在C中使用matplotlib绘图库的头文件库。它提供了一个简单的接口&#xff0c;使得在C中创建和显示图形变得更加容易。这个库的灵感来自于Python的matplotlib库&#xff0c;它使得在C中进行数据可视化变得更加便捷。 matplotlib-cpp允许在C中使用类似Py…