FreeRTOS——TCB任务控制块、任务句柄、任务栈详解
任务控制块结构体
任务控制块是 FreeRTOS 中用于描述和管理任务的数据结构,包含了任务的状态、优先级、堆栈等信息。
TCB_t的全称为Task Control Block,也就是任务控制块,这个结构体包含了一个任务所有的信息,它的定义以及相关变量的解释如下:
typedef struct tskTaskControlBlock {// 这里栈顶指针必须位于TCB第一项是为了便于上下文切换操作,详见xPortPendSVHandler中任务切换的操作。volatile StackType_t *pxTopOfStack; // MPU相关暂时不讨论#if ( portUSING_MPU_WRAPPERS == 1 )xMPU_SETTINGS xMPUSettings; #endif// 表示任务状态,不同的状态会挂接在不同的状态链表下ListItem_t xStateListItem; // 事件链表项,会挂接到不同事件链表下ListItem_t xEventListItem; // 任务优先级,数值越大优先级越高UBaseType_t uxPriority; // 指向堆栈起始位置,这只是单纯的一个分配空间的地址,可以用来检测堆栈是否溢出StackType_t *pxStack; // 任务名char pcTaskName[ configMAX_TASK_NAME_LEN ];// 指向栈尾,可以用来检测堆栈是否溢出#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )StackType_t *pxEndOfStack; #endif// 记录临界段的嵌套层数#if ( portCRITICAL_NESTING_IN_TCB == 1 )UBaseType_t uxCriticalNesting; #endif// 跟踪调试用的变量#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxTCBNumber; UBaseType_t uxTaskNumber; #endif// 任务优先级被临时提高时,保存任务原本的优先级#if ( configUSE_MUTEXES == 1 )UBaseType_t uxBasePriority; UBaseType_t uxMutexesHeld;#endif// 任务的一个标签值,可以由用户自定义它的意义,例如可以传入一个函数指针可以用来做Hook 函数调用#if ( configUSE_APPLICATION_TASK_TAG == 1 )TaskHookFunction_t pxTaskTag;#endif// 任务的线程本地存储指针,可以理解为这个任务私有的存储空间#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];#endif// 运行时间变量#if( configGENERATE_RUN_TIME_STATS == 1 )uint32_t ulRunTimeCounter; #endif// 支持NEWLIB的一个变量#if ( configUSE_NEWLIB_REENTRANT == 1 )struct _reent xNewLib_reent;#endif// 任务通知功能需要用到的变量#if( configUSE_TASK_NOTIFICATIONS == 1 )// 任务通知的值 volatile uint32_t ulNotifiedValue;// 任务通知的状态volatile uint8_t ucNotifyState;#endif// 用来标记这个任务的栈是不是静态分配的#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) uint8_t ucStaticallyAllocated; #endif// 延时是否被打断#if( INCLUDE_xTaskAbortDelay == 1 )uint8_t ucDelayAborted;#endif// 错误标识#if( configUSE_POSIX_ERRNO == 1 )int iTaskErrno;#endif} tskTCB;typedef tskTCB TCB_t;
栈顶指针必须为TCB结构体的第一项,原因是栈顶指针与我们的任务上下文保存、任务切换和任务恢复等操作息息相关。
每个任务都有自己的任务控制块,类似身份证。
TCB结构体中portSTACK_GROWTH>0表示栈是向上生长,<0表示栈是向下生长,我们STM32的栈是高地址往低地址存储,是向下生长的;而堆是低地址往高地址生长,是向上生长的。
任务句柄
任务句柄(Task Handle)是在 FreeRTOS 中用于标识和引用任务的数据类型。每个创建的任务都会分配一个唯一的任务句柄,通过该句柄可以对任务进行操作和管理。
任务句柄是一个指向任务控制块(Task Control Block,TCB)的指针。
使用任务句柄,可以通过 FreeRTOS 提供的 API 函数对任务进行操作,例如挂起(suspend)、恢复(resume)、删除(delete)任务,或者查询任务的状态等。另外,任务句柄还可以用于任务通信和同步的机制,例如向任务发送信号量或消息。
在创建任务时,通过调用 FreeRTOS 提供的任务创建函数(例如 xTaskCreate()
)可以获取到相应任务的句柄。你可以将该句柄保存在一个变量中,以便后续对该任务进行操作或引用。
任务句柄提供了一种有效的方式来管理和操作 FreeRTOS 中的任务。通过使用任务句柄,可以方便地对任务进行控制和监视。
任务栈
图解
任务创建 static void prvInitialiseNewTask(…)
这个函数用于创建新的任务,其中的 “prv” 表示该函数是一个私有函数,只用于内部处理和初始化新任务的操作。对于外部使用者来说,应该使用公开的 API 函数来创建和管理任务,而不是直接调用 “prvInitialiseNewTask”。
这个函数被 TaskHandle_t xTaskCreateStatic() 函数调用
函数源代码如下:
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, /* 任务入口 */const char * const pcName, /* 任务名称,字符串形式 */const uint32_t ulStackDepth, /* 任务栈大小,单位为字 */void * const pvParameters, /* 任务形参 */TaskHandle_t * const pxCreatedTask, /* 任务句柄 */TCB_t *pxNewTCB ) /* 任务控制块指针 */{StackType_t *pxTopOfStack; //栈顶UBaseType_t x; /* 获取栈顶地址 */pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );//pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );/* 向下做8字节对齐 */pxTopOfStack = ( StackType_t * ) ( ( ( uint32_t ) pxTopOfStack ) & ( ~( ( uint32_t ) 0x0007 ) ) ); /* 将任务的名字存储在TCB中 */for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ){pxNewTCB->pcTaskName[ x ] = pcName[ x ];if( pcName[ x ] == 0x00 ){break;}}/* 任务名字的长度不能超过configMAX_TASK_NAME_LEN */pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';/* 初始化TCB中的xStateListItem节点 */vListInitialiseItem( &( pxNewTCB->xStateListItem ) );/* 设置xStateListItem节点的拥有者 */listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );/* 初始化任务栈 */pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); /* 让任务句柄指向任务控制块 */if( ( void * ) pxCreatedTask != NULL ){ *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;}
}
初始化任务栈 StackType_t *pxPortInitialiseStack(…)
详细存储见下图:
初始化任务栈的作用是保存当前上下文的任务信息,以供我们后续任务切换所使用。
总结:
任务控制块是存储任务信息的载体,每个任务都有对应自己的任务控制块,我们在创建完任务之后,生成了任务对应的任务控制块,我们所定义的对应任务句柄在任务创建完成之后,就会指向我们的任务控制块,相当于我们可以通过任务句柄,间接去控制和管理我们的任务,而任务栈则是一些寄存器的载体,任务栈通过栈顶地址的加减,去存储一些寄存器信息,进而去设置任务的模式以及一些任务切换时所需要的信息,例如将任务栈中的PC寄存器存储了该任务的函数指针,在进行任务切换时,就可以调出PC寄存器存储的信息,进而找到相应的任务函数去执行,任务栈也为该任务预留了一些寄存器的空间,方便后面的使用。
相关文章:

FreeRTOS——TCB任务控制块、任务句柄、任务栈详解
任务控制块结构体 任务控制块是 FreeRTOS 中用于描述和管理任务的数据结构,包含了任务的状态、优先级、堆栈等信息。 TCB_t的全称为Task Control Block,也就是任务控制块,这个结构体包含了一个任务所有的信息,它的定义以及相关变…...

【STM32单片机_(HAL库)】4-5-2【定时器TIM】【感应开关盖垃圾桶项目】HC-SR04超声波模块实验
1.硬件 STM32单片机最小系统HC-SR04超声波模块 2.软件 hcsr04驱动文件添加main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "uart1.h" #include "hcsr04.h"int main(void) {HAL_Init(); …...

安全网络架构
网络安全解决方案是指通过一系列技术和措施来保护网络系统和数据的安全。它涉及多个方面,包括网络设备的防护、数据的加密和备份、安全策略的制定和执行等。以下是一些常见的网络安全解决方案: 防火墙:防火墙是一种硬件或软件设备,…...

【万字长文】Word2Vec计算详解(二)Skip-gram模型
【万字长文】Word2Vec计算详解(二)Skip-gram模型 写在前面 本篇介绍Word2Vec中的第二个模型Skip-gram模型 【万字长文】Word2Vec计算详解(一)CBOW模型 markdown行 9000 【万字长文】Word2Vec计算详解(二)S…...

随机掉落的项目足迹:解决TypeError: Cannot read properties of undefined (reading ‘push‘)报错
问题引入 下面是request.js中请求拦截器相关的代码 但是运行时却出现了报错 问题解决 useRouter() 是 Vue Router 提供的组合式 API,它只能在 Vue 组件的 setup() 函数中有效。如果在其他地方(例如 Axios 的拦截器中)调用它,可…...

ChatTTS 本地安装和测试
Ubuntu 22服务器,3.9/3.10都可以,但是 3.11不可以 sudo apt install python3.10 apt install python3.10 python3.10-dev #ubuntu 22 安装python3.10对应的pip3.10 # 下载 get-pip.py curl -sS https://bootstrap.pypa.io/get-pip.py -o get-pip.py # 使…...
[Leetcode] 560 Subarray Sum Equals K
题意:给定一个数组求连续的子数组的和为k的有几个 Input: nums [1,1,1], k 2 Output: 2 https://leetcode.com/problems/subarray-sum-equals-k/description/ 首先思考1.因为是subarray sum前缀和很容易想到,那问题就转化成preSum[i] preSum[j] - k…...
TCL Android面试题大全及参考答案
能谈谈Jetpack组件吗? Jetpack 是一套用于 Android 开发的工具和组件库,它可以帮助开发者更高效地构建高质量的 Android 应用。 一、主要组件分类 架构组件: ViewModel:负责存储和管理与界面相关的数据,当屏幕旋转或配置发生变化时,ViewModel 可以帮助保存数据,避免数据…...
JVM错误:OutOfMemoryError: GC overhead limit exceeded
OutOfMemoryError: GC overhead limit exceeded 在Window服务器上跑一个项目,无意中出现服务访问不了,查看日志文档,第一次遇到了这个异常信息。 1. 错误含义 OutOfMemoryError: GC overhead limit exceeded 是 JVM 中的一种错误ÿ…...

Unity网络开发 - C#开源网络通信库PESocket的使用
概述 在现代多人在线游戏中,稳定且高效的网络通信是确保游戏体验的关键。本文将探讨如何利用C#开源网络通信库PESocket来构建一个简单的Unity客户端与.NET控制台服务器之间的实时消息传递系统。通过本例,读者不仅能够了解PESocket的基本用法,…...

【完-网络安全】Shell与脚本
文章目录 1.CLI与GUI2.终端和Shell2.1 Shell 壳层2.2 终端2.3 终端和Shell区别3.标准流 4.PowerShell4.1 管理员与非管理员4.2 指令4.3 重定向4.4 管道 5.环境变量5.1 影响范围5.2环境变量的作用5.3 常见的环境变量 6.脚本 1.CLI与GUI CLI命令行界面(CLl,Command Line Interfa…...
磁盘标签和分区标签
在Windows中,我们为分区命名,那个名字就是「分区标签」。所以说“分区标签”是给分区的一个名字。 「磁盘标签」其实是我们经常说的「分区表」,比如MBR、GPT等等。而「分区标签」,虽然叫做“分区”标签,但它则是文件系…...

关于摩托车一键启动无钥匙进入、智能科技创新
摩托车一键启动无钥匙进入功能 一、工作原理 摩托车的一键启动无钥匙进入功能采用了世界最先进的RFID无线射频技术和最先进的车辆身份编码识别系统,率先应用小型化、小功率射频天线的开发方案,并成功融合了遥控系统和无钥匙系统,沿用了传统…...

怎么找矩阵系统,怎么源码搭建,源头技术开发需要哪些支持
一、引言 在进行矩阵系统源码搭建时,选择合适的工具至关重要。正确的工具选择不仅可以提高开发效率,还能确保系统的稳定性、可扩展性和性能。本文将探讨在矩阵系统源码搭建过程中如何选择合适的工具。 二、前端开发工具选择 前端框架 React:由…...
云原生化 - 工具镜像(简约版)
在微服务和云原生环境中,容器化的目标之一是尽可能保持镜像小型化以提高启动速度和减少安全风险。然而,在实际操作中,有时候需要临时引入一些工具来进行调试、监控或问题排查。Kubernetes提供了临时容器(ephemeral containers&…...

uni-app如何搭建项目(一步一步教程)
来来来,看这里 uni-app新建项目教程uni-app项目结构 首先我们要有一个HBuilder这个软件,然后我们来搭建uni-app项目 uni-app新建项目教程 首先我们打开这个HBuilder软件,好我们就出现这个界面,我们点击新建项目 然后我们选择…...
javascript中原型链(__proto__)与原型(prototype)
JavaScript中原型链(proto)与原型(prototype) 在JavaScript中,理解原型链(__proto__)和原型(prototype)对于深入掌握面向对象编程至关重要。本文将通过示例代码,详细解析__proto__和prototype之间的关系&a…...

基于多种机器学习的酒店客户流失预测模型的研究与实现
文章目录 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主项目介绍实现过程 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主 项目介绍 项目背景: 在当今竞争激烈的酒店行业中,预测和防止客户流…...

Unity实现自定义图集(三)
以下内容是根据Unity 2020.1.0f1版本进行编写的 1、实现编辑器模式下进游戏前Pack全部自定义图集 同Unity的图集一样,Unity的编辑器模式会在进游戏前把全部的SpriteAtlas都打一次图集,如图: 我们也实现这样的效果。 首先需要获取全部的图集路径。因为目前使用的是以.…...
【测开面试真题】
针对地图导航设计测试用例 文章目录 1. selenium 定位元素的方式有几种?2. 自动化测试能够取代人工测试吗?3. 什么是回归测试? 1. selenium 定位元素的方式有几种? 🐧①通过CSS选择器定位;🐧②…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...