FreeRTOS:TCB_t结构体解读(转载)

2023-11-29 22:04

本文主要是介绍FreeRTOS:TCB_t结构体解读(转载),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

TCB_t:任务控制块

TCB_t的全称为Task Control Block,也就是任务控制块,这个结构体包含了一个任务所有的信息,它的定义以及相关变量的解释如下:

typedef struct tskTaskControlBlock             {// 这里栈顶指针必须位于TCB第一项是为了便于上下文切换操作,详见xPortPendSVHandler中任务切换的操作。volatile StackType_t    *pxTopOfStack;    // MPU相关暂时不讨论#if ( portUSING_MPU_WRAPPERS == 1 )
/*< MPU设置被定义为端口层的一部分。它必须是TCB结构的第二个成员。 */xMPU_SETTINGS    xMPUSettings;        #endif// 表示任务状态,不同的状态会挂接在不同的状态链表下// 由于configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES = 0 ,此链表共5个成员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_t结构体的定义中可以看到根据栈的生长方式的不同,其将具有不同的成员变量pxEndOfStack,在这里说明一下栈的生长方式是如何定义的,以及为何生长方式会存在pxEndOfStack这一变量的差异。

栈的生长方式可以分为两种,一种是向下生长,一种是向上生长,FreeRTOS中用portSTACK_GROWTH来区分这两种生长方式,portSTACK_GROWTH大于0为向上生长,小于零为向下生长。两种生长方式的区别可以简单概括如下

  • 向上生长:入栈时栈顶指针增加,出栈时栈顶指针减小。
  • 向下生长:入栈时栈顶指针减小,出栈时栈顶指针增加。

    为什么会有这两种出入栈方式呢?为何不将所有芯片统一成一种生长方式?这一点应该是芯片设计的实际需要,具体原因无法解答。

    有了上图栈的生长方式为什么会影响成员变量的个数很好理解了,pxStack是指向栈内存分配的起始地址(低地址),pxEndOfStack是指向栈的尾部的,当栈是向下生长时,pxStack和pxEndOfStack值是一致的,再定义pxEndOfStack浪费了内存而栈是向上生长时pxStack与pxEndOfStack的值不一致,如果想知道栈的结束地址,必须要定义一个变量pxEndOfStack来存储,以用于后续的栈溢出检测等操作

    状态链表

        FreeRTOS中的任务一共有四种状态分别是运行状态(Running State),就绪状态(Ready State),阻塞状态(Blocked State),挂起状态(Suspended State),其含义可以简单理解为

  • 运行状态:正在执行的任务。

  • 就绪状态:等待获得执行权的任务。

  • 阻塞状态:直到某些条件达成才会重新进入就绪态等待获得执行权,否则不会执行的任务。

  • 挂起状态:除非被主动恢复,否则永远不会执行。

这四种链表分别对应着pxCurrentTCB,pxReadyTasksLists,pxDelayedTaskList,xSuspendedTaskList这四个变量。除运行状态外,任务处于其它状态时,都是通过将任务TCB中的xStateListItem挂到相应的链表下来表示的。

这篇关于FreeRTOS:TCB_t结构体解读(转载)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/434475

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

MCU7.keil中build产生的hex文件解读

1.hex文件大致解读 闲来无事,查看了MCU6.用keil新建项目的hex文件 用FlexHex打开 给我的第一印象是:经过软件的解释之后,发现这些数据排列地十分整齐 :02000F0080FE71:03000000020003F8:0C000300787FE4F6D8FD75810702000F3D:00000001FF 把解释后的数据当作十六进制来观察 1.每一行数据

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

GPT系列之:GPT-1,GPT-2,GPT-3详细解读

一、GPT1 论文:Improving Language Understanding by Generative Pre-Training 链接:https://cdn.openai.com/research-covers/languageunsupervised/language_understanding_paper.pdf 启发点:生成loss和微调loss同时作用,让下游任务来适应预训

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

FreeRTOS学习笔记(六)队列

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQueueReceive2.4 xQueueSendFromISR2.5 xQueueRecei