当前位置: 首页 > news >正文

FreeRTOS任务挂起以及延时部分源码分析


layout: post
title: “任务状态”
date: 2023-7-19 15:39:08 +0800
tags: FreeRTOS


任务状态

fireRTOS代码分析

任务挂起

//把一个任务挂起
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
{TCB_t *pxTCB;taskENTER_CRITICAL();//进入临界区{/* 参数是NULL的时候设置为当前任务, 否则返回这一个参数的TCB */pxTCB = prvGetTCBFromHandle( xTaskToSuspend );traceTASK_SUSPEND( pxTCB );/* 从就绪列表里面移除 */if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ){//重新设置优先级taskRESET_READY_PRIORITY( pxTCB->uxPriority );}else{mtCOVERAGE_TEST_MARKER();}/* 检测这一个任务是不是在等待一个事件 */if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ){//是的话把他从事件链表里面移除( void ) uxListRemove( &( pxTCB->xEventListItem ) );}//插入挂起的队列vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );#if( configUSE_TASK_NOTIFICATIONS == 1 ){if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION ){/* The task was blocked to wait for a 通知, but isnow suspended, so no notification was received. */pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;}}#endif}taskEXIT_CRITICAL();if( xSchedulerRunning != pdFALSE ){/* 重新设置一下下一个软件时钟的时间(一般用于Delay以及等待事件) */taskENTER_CRITICAL();{prvResetNextTaskUnblockTime();}taskEXIT_CRITICAL();}if( pxTCB == pxCurrentTCB ){if( xSchedulerRunning != pdFALSE ){/* 调度器在运行 */configASSERT( uxSchedulerSuspended == 0 );//切换任务portYIELD_WITHIN_API();}else{/* 调度器没有运行(不能进行任务切换) */if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ){/* 没有其他的任务了 */pxCurrentTCB = NULL;}else{//把记录当前任务的全局变量改为优先级最高的一个任务vTaskSwitchContext();}}}else{mtCOVERAGE_TEST_MARKER();}
}

恢复挂起的任务

//恢复挂起的任务
void vTaskResume( TaskHandle_t xTaskToResume )
{TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;/* 同上 */if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ){taskENTER_CRITICAL();{//检测是不是真的被挂起了if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ){traceTASK_RESUME( pxTCB );/* 从挂起的链表里面移除 */( void ) uxListRemove(  &( pxTCB->xStateListItem ) );//加入就绪列表prvAddTaskToReadyList( pxTCB );/* A higher priority task may have just been resumed. */if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ){/* 优先级比较当前任务高, 进行一次任务切换 */taskYIELD_IF_USING_PREEMPTION();}}}taskEXIT_CRITICAL();}
}
//恢复所有挂起的任务
BaseType_t xTaskResumeAll( void )
{
TCB_t *pxTCB = NULL;
BaseType_t xAlreadyYielded = pdFALSE;/* If uxSchedulerSuspended is zero then this function does not match aprevious call to vTaskSuspendAll(). */configASSERT( uxSchedulerSuspended );/* It is possible that an ISR caused a task to be removed from an eventlist while the scheduler was suspended.  If this was the case then theremoved task will have been added to the xPendingReadyList.  Once thescheduler has been resumed it is safe to move all the pending readytasks from this list into their appropriate ready list. 如果之前的任务有在ISR中并且任务调度实现的时候被从事件List里面移除, 需要处理 */taskENTER_CRITICAL();{//任务切换挂起的记录减一--uxSchedulerSuspended;if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ){if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ){/* Move any readied tasks from the pending list into theappropriate ready list. 这是一个等待恢复的队列, 一般是在时钟挂起的时候转为ready的任务 */while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ){//处理待处理的任务pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );( void ) uxListRemove( &( pxTCB->xEventListItem ) );( void ) uxListRemove( &( pxTCB->xStateListItem ) );prvAddTaskToReadyList( pxTCB );/* If the moved task has a priority higher than the currenttask then a yield must be performed. */if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ){//需要优先级切换xYieldPending = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}if( pxTCB != NULL ){/* A task was unblocked while the scheduler was suspended,which may have prevented the next unblock time from beingre-calculated, in which case re-calculate it now.  Mainlyimportant for low power tickless implementations, wherethis can prevent an unnecessary exit from low powerstate. 更新一下下一个需要处理的Delay时钟的值 */prvResetNextTaskUnblockTime();}/* If any ticks occurred while the scheduler was suspended thenthey should be processed now.  This ensures the tick count doesnot	slip, and that any delayed tasks are resumed at the correcttime. 处理挂期间任务的待处理事项*/{UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */if( uxPendedCounts > ( UBaseType_t ) 0U ){do{//调用时钟处理函数, 更新一下时钟值if( xTaskIncrementTick() != pdFALSE ){xYieldPending = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}--uxPendedCounts;//记录挂起的时钟数} while( uxPendedCounts > ( UBaseType_t ) 0U );uxPendedTicks = 0;}else{mtCOVERAGE_TEST_MARKER();}}if( xYieldPending != pdFALSE ){#if( configUSE_PREEMPTION != 0 ){xAlreadyYielded = pdTRUE;}#endif//任务切换taskYIELD_IF_USING_PREEMPTION();}}}taskEXIT_CRITICAL();return xAlreadyYielded;
}

延时函数

void vTaskDelay( const TickType_t xTicksToDelay )
{BaseType_t xAlreadyYielded = pdFALSE;/* A delay time of zero just forces a reschedule. */if( xTicksToDelay > ( TickType_t ) 0U ){vTaskSuspendAll();{/* A task that is removed from the event list while thescheduler is suspended will not get placed in the readylist or removed from the blocked list until the scheduleris resumed.This task cannot be in an event list as it is the currentlyexecuting task. 把这一个任务插入Delay队列里面 */prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );}xAlreadyYielded = xTaskResumeAll();}/* Force a reschedule if xTaskResumeAll has not already done so, we mayhave put ourselves to sleep. */if( xAlreadyYielded == pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}
}
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
{
TickType_t xTimeToWake;
const TickType_t xConstTickCount = xTickCount;/* 把当前的任务从运行的任务里面删除 */if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ){/* 这个优先级没有任务了, 清除标志位 */portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );}else{mtCOVERAGE_TEST_MARKER();}if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) ){/* 设置的时间是无限, 直接挂起. */vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );}else{/* 计算唤醒的时间 */xTimeToWake = xConstTickCount + xTicksToWait;/* 设置时钟 */listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );if( xTimeToWake < xConstTickCount ){/* 溢出列表. */vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );}else{/* 不是溢出 */vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );/* 设置下一次的唤醒时间 */if( xTimeToWake < xNextTaskUnblockTime ){xNextTaskUnblockTime = xTimeToWake;}else{mtCOVERAGE_TEST_MARKER();}}}}
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
{TickType_t xTimeToWake;BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;configASSERT( pxPreviousWakeTime );configASSERT( ( xTimeIncrement > 0U ) );configASSERT( uxSchedulerSuspended == 0 );vTaskSuspendAll();{/* Minor optimisation.  The tick count cannot change in thisblock. */const TickType_t xConstTickCount = xTickCount;/* Generate the tick time at which the task wants to wake. */xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;//节拍器溢出if( xConstTickCount < *pxPreviousWakeTime ){/* 唤醒时间和现在的时间都已经溢出过了 */if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ){xShouldDelay = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}else{/* 只有溢出时间溢出了, 或者都没有溢出 */if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ){xShouldDelay = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}/* Update the wake time ready for the next call. */*pxPreviousWakeTime = xTimeToWake;if( xShouldDelay != pdFALSE ){traceTASK_DELAY_UNTIL( xTimeToWake );/* 插入到延时链表里面 */prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );}else{mtCOVERAGE_TEST_MARKER();}}xAlreadyYielded = xTaskResumeAll();/* Force a reschedule if xTaskResumeAll has not already done so, we mayhave put ourselves to sleep. */if( xAlreadyYielded == pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}
}

相关文章:

FreeRTOS任务挂起以及延时部分源码分析

layout: post title: “任务状态” date: 2023-7-19 15:39:08 0800 tags: FreeRTOS 任务状态 fireRTOS代码分析 任务挂起 //把一个任务挂起 void vTaskSuspend( TaskHandle_t xTaskToSuspend ) {TCB_t *pxTCB;taskENTER_CRITICAL();//进入临界区{/* 参数是NULL的时候设置为当…...

oracle数据库慢查询SQL

目录 场景&#xff1a; 环境&#xff1a; 慢SQL查询一&#xff1a; 问题一&#xff1a;办件列表查询慢 分析&#xff1a; 解决方法&#xff1a; 问题二&#xff1a;系统性卡顿 分析&#xff1a; 解决方法&#xff1a; 慢SQL查询二 扩展&#xff1a; 场景&#xff1a; 线…...

C语言搭配EasyX实现贪吃蛇小游戏

封面展示 内部展示 完整代码 #define _CRT_SECURE_NO_WARNINGS #include<easyx.h> #include<stdio.h> #include<mmsystem.h> #pragma comment (lib,"winmm.lib") #define width 40//宽有40个格子 #define height 30//长有40个格子 #define size 2…...

# 软件安装-Linux搭建nginx(单机版)

软件安装-Linux搭建nginx(单机版) 安装版本:nginx-1.24.0 文章目录 软件安装-Linux搭建nginx(单机版)一、Nginx包下载二、创建用户1.新建组和用户2.设置用户密码3.登录自己创建的目录三、安装依赖组件四、安装Nginx五、启动Nginx六、配置Nginx一、Nginx包下载 1. nginx-1.24下…...

成熟的汽车制造供应商协同平台 要具备哪些功能特性?

汽车行业是一个产业链长且“重”的行业&#xff0c;整个业务流程包括了研发、设计、采购、库存、生产、销售、售后等一系列环节&#xff0c;在每一个环节都涉及到很多信息交换的需求。对内要保证研发、采购、营销等业务环节信息流通高效安全&#xff0c;对外要与上、下游合作伙…...

React16源码: React中处理ref的核心流程源码实现

ref的实现过程 1 &#xff09;概述 在更新流程当中如何去设置ref上面的对象的过程在我们创建fiber的时候去处理ref这个属性那我们什么时候创建fiber对象? 就是我们去更新某一个节点&#xff0c;然后要去调和它的子节点的时候这个时候我们会对每一个子节点去创建这个fiber对象…...

ref和reactive

看尤雨溪说&#xff1a;为什么Vue3 中应该使用 Ref 而不是 Reactive&#xff1f;...

掌握数据预测的艺术:线性回归模型详解

线性回归是统计学中用于建模两个或多个变量之间线性关系的一种方法,广泛应用于数据分析、机器学习等领域。从数学建模的角度出发,线性回归旨在找到一个线性方程,最好地描述自变量(或称为解释变量、特征变量)和因变量(或称为目标变量)之间的关系。本文将通过Python代码示…...

STM32F407移植OpenHarmony笔记8

继上一篇笔记&#xff0c;成功开启了littlefs文件系统&#xff0c;能读写FLASH上的文件了。 今天继续研究网络功能&#xff0c;让控制台的ping命令能工作。 轻量级系统使用的是liteos_m内核lwip协议栈实现网络功能&#xff0c;需要进行配置开启lwip支持。 lwip的移植分为两部分…...

C++:输入流/输出流

C流类库简介 C为了克服C语言中的scanf和printf存在的缺点。&#xff0c;使用cin/cout控制输入/输出。 cin&#xff1a;表示标准输入的istream类对象&#xff0c;cin从终端读入数据。cout&#xff1a;表示标准输出的ostream类对象&#xff0c;cout向终端写数据。cerr&#xff…...

十、Qt三维图表

一、Data Visualization模块概述 Data Visualization的三维显示功能主要有三种三维图形来实现&#xff0c;三各类的父类都是QAbstract3DGraph&#xff0c;从QWindow继承而来。这三类分别是&#xff1a;三维柱状图Q3DBar三维空间散点Q3DScatter三维曲面Q3DSurface 1、相关类的…...

CMake官方教程中文翻译 Step 6: Adding Support for a Testing Dashboard

鉴于自己破烂的英语&#xff0c;所以把cmake的官方文档用 谷歌翻译 翻译下来方便查看。 英语好的同学建议直接去看cmake官方文档&#xff08;英文&#xff09;学习&#xff1a;地址 点这里 或复制&#xff1a;https://cmake.org/cmake/help/latest/guide/tutorial/index.html …...

【leetcode】完全背包总结

本文内容参考了代码随想录&#xff0c;并进行了自己的总结。 完全背包 关键点 ● 每件物品有若干种状态&#xff1a;不选、选 1 件、选 2 件、…、选 n 件 代码 在代码上&#xff0c;只有重量的遍历方向和 01 背包不一样&#xff1a; for(int i 0; i < nums.length; i…...

【Linux】理解系统中一个被打开的文件

文件系统 前言一、C语言文件接口二、系统文件接口三、文件描述符四、struct file 对象五、stdin、stdout、stderr六、文件描述符的分配规则七、重定向1. 重定向的原理2. dup23. 重谈 stderr 八、缓冲区1. 缓冲区基础2. 深入理解缓冲区3. 用户缓冲区和内核缓冲区4. FILE 前言 首…...

k8s kubeadm部署安装详解

目录 kubeadm部署流程简述 环境准备 步骤简述 关闭 防火墙规则、selinux、swap交换 修改主机名 配置节点之间的主机名解析 调整内核参数 所有节点安装docker 安装依赖组件 配置Docker 所有节点安装kubeadm&#xff0c;kubelet和kubectl 定义kubernetes源并指定版本…...

RT-DETR算法优化改进: 下采样系列 | 一种新颖的基于 Haar 小波的下采样HWD,有效涨点系列

💡💡💡本文独家改进:HWD的核心思想是应用Haar小波变换来降低特征图的空间分辨率,同时保留尽可能多的信息,与传统的下采样方法相比,有效降低信息不确定性。 💡💡💡使用方法:代替原始网络的conv,下采样过程中尽可能包括更多信息,从而提升检测精度。 RT-DET…...

CocosCreator3.8源码分析

Cocos Creator架构 Cocos Creator 拥有两套引擎内核&#xff0c;C 内核 和 TypeScript 内核。C 内核用于原生平台&#xff0c;TypeScript 内核用于 Web 和小游戏平台。 在引擎内核之上&#xff0c;是用 TypeScript 编写的引擎框架层&#xff0c;用以统一两套内核的差异&#xf…...

(已解决)spingboot 后端发送QQ邮箱验证码

打开QQ邮箱pop3请求服务&#xff1a;&#xff08;按照QQ邮箱引导操作&#xff09; 导入依赖&#xff08;不是maven项目就自己添加jar包&#xff09;&#xff1a; <!-- 邮件发送--><dependency><groupId>org.springframework.boot</groupId><…...

【蓝桥杯冲冲冲】[NOIP2001 普及组] 装箱问题

蓝桥杯备赛 | 洛谷做题打卡day26 文章目录 蓝桥杯备赛 | 洛谷做题打卡day26题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路 题解代码我的一些话 [NOIP2001 普及组] 装箱问题 题目描述 有一个箱子容量为 V V V&#xff0c;同时有 n n n 个物品&#xff0c;每…...

2024牛客寒假算法基础集训营1

文章目录 A DFS搜索M牛客老粉才知道的秘密G why外卖E 本题又主要考察了贪心B 关鸡C 按闹分配 今天的牛客&#xff0c;说是都是基础题&#xff0c;头昏昏的&#xff0c;感觉真不会写&#xff0c;只能赛后补题了 A DFS搜索 写的时候刚开始以为还是比较难的&#xff0c;和dfs有关…...

【JEECG Boot】 JEECG Boot——Online表单 系统性知识体系全解

文章目录JEECG Boot——Online表单一、核心基础认知1.1 官方定义与核心定位1.2 核心价值与解决的痛点1.3 与代码生成器的核心区别1.4 技术栈与运行环境依赖1.5 适用场景与能力边界二、核心架构与底层驱动原理2.1 整体四层架构体系2.2 元数据驱动的核心原理2.3 核心元数据模型与…...

X-World:可扩展端到端驾驶中可控自我为中心多摄像头世界模型

26年3月来自小鹏汽车的论文“X-World: Controllable Ego-Centric Multi-Camera World Models for Scalable End-to-End Driving”。 在端到端自动驾驶时代&#xff0c;可扩展且可靠的评估变得日益重要。在这一时代&#xff0c;视觉-语言-动作&#xff08;VLA&#xff09;策略直…...

从雅可比矩阵到概率重塑:标准化流如何成为生成式模型的精确解?

1. 标准化流&#xff1a;生成式模型的精确解 想象你手里有一张白纸&#xff0c;上面画着一个标准圆形。现在你想把它变成一幅复杂的山水画&#xff0c;但又希望每一步修改都能精确追踪——这就是标准化流&#xff08;Normalizing Flows&#xff09;在概率分布世界做的事情。与其…...

Redis 服务器:全面解析与应用实践

Redis 服务器:全面解析与应用实践 引言 Redis(Remote Dictionary Server)是一款开源的、高性能的键值存储数据库。它采用内存作为存储介质,能够提供极快的读写速度,常用于缓存、会话管理、消息队列等领域。本文将全面解析Redis服务器的原理、配置、应用场景以及实践操作…...

深度解析WeChatMsg:个人数据主权时代的技术革命与架构设计

深度解析WeChatMsg&#xff1a;个人数据主权时代的技术革命与架构设计 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/W…...

MetalLB才是给Ingress这个老登做负重前行的那个男人棺

一、核心问题及解决方案&#xff08;按踩坑频率排序&#xff09; 问题 1&#xff1a;误删他人持有锁——最基础也最易犯的漏洞 成因&#xff1a;释放锁时未做身份校验&#xff0c;直接执行 DEL 命令删除键。典型场景&#xff1a;服务 A 持有锁后&#xff0c;业务逻辑耗时超过锁…...

CMake实战:如何自动生成带Git分支和编译时间的版本号(附完整代码)

CMake实战&#xff1a;自动化生成含Git分支与编译时间的版本标识系统 在持续集成和敏捷开发成为主流的今天&#xff0c;每次代码提交都可能触发自动化构建流程。作为开发者&#xff0c;你是否遇到过这样的困扰&#xff1a;测试人员报告了一个问题&#xff0c;但无法快速确认他们…...

哪款头戴式蓝牙耳机性价比高?十大热门平价头戴式耳机品牌推荐!

2026年头戴耳机市场新老品牌争奇斗艳&#xff0c;从入门到高端让人目不暇接。作为一名经历过选择困难的音频爱好者&#xff0c;我完全理解这种幸福的烦恼&#xff1a;参数术语堆砌、营销话术包装&#xff0c;让人难辨虚实。在实测过多款产品后&#xff0c;我发现关键要避开这些…...

从经验到智能:TVA时代企业质检员的角色转型

随着工业4.0的推进&#xff0c;汽车零部件生产逐渐向智能化、自动化转型&#xff0c;智能体视觉检测系统&#xff08;TVA&#xff09;的广泛应用&#xff0c;彻底改变了传统焊接点检测的模式&#xff0c;也对质检员的角色与能力提出了新的要求。传统模式下&#xff0c;质检员的…...

飞书文档批量导出架构实战:企业级知识库迁移的高效解决方案

飞书文档批量导出架构实战&#xff1a;企业级知识库迁移的高效解决方案 【免费下载链接】feishu-doc-export 飞书文档导出服务 项目地址: https://gitcode.com/gh_mirrors/fe/feishu-doc-export 在企业数字化转型过程中&#xff0c;知识库迁移成为组织面临的核心挑战之一…...