FreeRTOS之列表和列表项

FreeRTOS基础(九):FreeRTOS的列表和列表项 列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务。任务处在不同的状态下,就挂载在不同的列表中(比如就绪列表、阻塞列表、挂起列表)。而列表项就是存放在列表中的项目,一个列表项就关联着一个任务,可以说:列表代表处于某种状态的任务的集合,列表项就代表处于当前状态下的某一个任务。如下图所示:列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向循环链表。 阅读详情

列表和列表项是FreeRTOS的一个数据结构,是FreeRTOS的基石。

1.列表
列表是FreeRTOS中的一个数据结构,和链表类似,它的定义位于文件list.c和list.h中。
列表的结构体定义如下:

typedef struct xLIST
{
    listFIRST_LIST_INTEGRITY_CHECK_VALUE              // 用来检查列表完整性:configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1时,添加一个变量,初始化列表的时候赋一个特殊的值
    configLIST_VOLATILE UBaseType_t uxNumberOfItems;  // 记录列表中列表项的数目
    ListItem_t * configLIST_VOLATILE pxIndex;         // 记录当前列表项的索引号,用于遍历列表 
    MiniListItem_t xListEnd;                          // 列表的最后一个列表项
    listSECOND_LIST_INTEGRITY_CHECK_VALUE             // 同listFIRST_LIST_INTEGRITY_CHECK_VALUE一样
} List_t;

// 宏listFIRST_LIST_INTEGRITY_CHECK_VALUE和listSECOND_LIST_INTEGRITY_CHECK_VALUE是用来检查列表完整性的。
// 当宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1时,这两个地方会各添加一个变量xListIntegrityValue1和xListIntegrityValue2,初始化列表的时候,这两个变量中会写入一个特殊的值。
// 默认这个功能不开启。

2.列表项
FreeRTOS提供了两种列表项:列表项和迷你列表项,它们的定义都位于文件list.h中。
(1)列表项的结构体定义如下:

struct xLIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE            // 用来检查列表完整性
    configLIST_VOLATILE TickType_t xItemValue;           // 列表项的项值,列表按照该值的大小顺序排列
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;      // 指向下一个列表项
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;  // 指向前一个列表项
    void * pvOwner;                                      // 记录此链表归谁拥有,也就是指向任务控制块
    void * configLIST_VOLATILE pvContainer;              // 用来记录此列表项归哪个列表
    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE           // 用来检查列表完整性
};
typedef struct xLIST_ITEM ListItem_t;

(2)迷你列表项的结构体定义:

struct xMINI_LIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE            // 用于检查迷你列表项的完整性
    configLIST_VOLATILE TickType_t xItemValue;           // 列表项值,列表中的列表项按照该值顺序排列
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;      // 指向下一个列表项
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;  // 指向上一个列表项
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

3.列表初始化
列表初始化通过函数vListInitialise()来完成,此函数在文件list.c中定义,如下:

void vListInitialise( List_t * const pxList )
{
    // pxList此时只有一个列表项xListEnd,因此pxIndex只能指向这里
    pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );

    // 列表是按照列表项值顺序排列的,那么xListEnd作为列表的最后一个列表项,它的列表项值应该是最大的
    // portMAX_DELAY的定义位于文件portmacro.h中
    pxList->xListEnd.xItemValue = portMAX_DELAY;

    // pxList只有xListEnd这一个列表项,因此pxNext和pxPrevious只能指向自身
    pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
    pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );

    pxList->uxNumberOfItems = ( UBaseType_t ) 0U;

    // 初始化列表项中用于完整性检查字段,只有宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES为1时才有效
    listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
    listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

4.列表项初始化
列表项的初始化由函数vListInitialiseItem()来完成,定义如下:

void vListInitialiseItem( ListItem_t * const pxItem )
{
    // 初始化pvContainer为NULL,保证该列表项不属于任何列表
    pxItem->pvContainer = NULL;

    // 初始化用于完整性检查的变量,如果开启了这个功能的化
    listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
    listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

5.列表项插入

void vListInsert( List_t * const pxList,             // 列表项要插入的列表
                  ListItem_t * const pxNewListItem   // 要插入的列表项
                )
{
ListItem_t *pxIterator;
// 获取要插入的列表项的项值,因为列表是按照列表项值升序排列的,根据这个值可以确定列表项要插入的位置
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;  

    // 用来检查列表和列表项的完整性,其实就是检查列表和列表项中用于完整性检查的变量值是否被改变。
    // configASSERT()有效时才能实现。
    listTEST_LIST_INTEGRITY( pxList );
    listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );

    // 获取要插入的点,插入的情况分两种:
    // 第1种:pxList的最后一个列表项xListEnd的列表项值是portMAX_DELAY,若当前要插入的列表项的项值时portMAX_DELAY的话,那么它肯定是位于列表最末尾了。
    // 第2种:要插入的列表项的项值不能与portMAX_DELAY的情况,该情况需要与列表中的列表项一个一个去比较项值
    if( xValueOfInsertion == portMAX_DELAY )
    {
        pxIterator = pxList->xListEnd.pxPrevious;
    }
    else
    {
        for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) 
        {

        }
    }

    // 双向链表插入
    pxNewListItem->pxNext = pxIterator->pxNext;
    pxNewListItem->pxNext->pxPrevious = pxNewListItem;
    pxNewListItem->pxPrevious = pxIterator;
    pxIterator->pxNext = pxNewListItem;

    // 记录该列表项属于哪个列表
    pxNewListItem->pvContainer = ( void * ) pxList;

    // 列表项数目加1
    ( pxList->uxNumberOfItems )++;
}

注:当列表中的列表项增多时,会有一个神奇的发现:列表居然是一个环形列表。

6.列表项末尾插入
列表项末尾插入通过函数vListInsertEnd()函数实现,显示如下:

void vListInsertEnd( 
                List_t * const pxList,            // 列表项要插入的列表
                ListItem_t * const pxNewListItem  // 要插入的列表项
                   )
{
ListItem_t * const pxIndex = pxList->pxIndex;

    // 对列表和列表项进行完整性检查
    listTEST_LIST_INTEGRITY( pxList );
    listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );

    pxNewListItem->pxNext = pxIndex;
    pxNewListItem->pxPrevious = pxIndex->pxPrevious;

    mtCOVERAGE_TEST_DELAY();

    pxIndex->pxPrevious->pxNext = pxNewListItem;
    pxIndex->pxPrevious = pxNewListItem;

    // 记录列表项属于该列表
    pxNewListItem->pvContainer = ( void * ) pxList;
    ( pxList->uxNumberOfItems )++;
}

注:这里说的在末尾不是指xListEnd表示的末尾,而是要根据pxIndex来确定的。

7.列表项的删除
列表项的删除要通过函数uxListRemove()来实现的,定义如下:

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
// 获取该列表项所属的列表
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;

    // 删除列表项
    pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
    pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
    mtCOVERAGE_TEST_DELAY();

    // 确保pxIndex不为空
    if( pxList->pxIndex == pxItemToRemove )
    {
        pxList->pxIndex = pxItemToRemove->pxPrevious;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    // 清空pvContainer
    pxItemToRemove->pvContainer = NULL;
    ( pxList->uxNumberOfItems )--;

    // 返回列表中列表项的数目
    return pxList->uxNumberOfItems;
}

8.列表的遍历
将列表的遍历前,再说明一下:列表List_t中的成员变量pxIndex是用来遍历列表的。
FreeRTOS提供了一个函数来完成列表的遍历,这个函数是listGET_OWNER_OF_NEXT_ENTRY()。
每调用一次这个函数,则列表的pxIndex变量就会指向下一个项,并且返回这个列表项的pxOwner变量值,也就是TCB。
该函数本质上是一个宏,它的定义位于文件list.h文件中,如下:

#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )                                        \
{                                                                                           \
List_t * const pxConstList = ( pxList );                                                    \
    // pxIndex指向下一个列表项
    ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                            \
    // 若pxIndex指向了列表的xListEnd,则跳过xListEnd,pxIndex再一次指向处于列表头的列表项
    if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )  \
    {                                                                                       \
        ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                        \
    }                                                                                       \
    // 将pxIndex指向的新列表项的pvOwner赋值给pxTCB
    ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                          \
}

此函数用于从多个同优先级的就绪任务中查找下一个要运行的任务。

FreeRTOS的学习(四)——列表 最近因为疫情,已经在家一个星期多了,由于状态不佳,也是在最近重新拾起了FreeRTOS的学习,学习的过程着实路长且艰 ,不过待到多年后回首,一定会感谢自己现在的付出。 话不多说,这几天学了FreeRTOS的列表的组成和一些操作机制,对于数据结构(本科的时候学过,当时学的贼认真的一门课,虽然最后考试也才92,不过没到三年就忘的差不多了^-^)的内容需要重新学习,这个过程也是相对难熬的……... 阅读详情

相关推荐

FreeRTOS的列表和列表项

FreeRTOS中列表与列表项的实现及应用 摘要:FreeRTOS广泛使用列表(List)和列表项(ListItem)作为其基本数据结构。列表实质上是一个双向链表,包含头尾校验值、列表项计数和索引指针等成员。列表项则包含前后指针、所属列表指针等字段,支持数据存储和链表操作。系统还提供了迷你列表项用于标记列表末尾。FreeRTOS通过一系列宏函数和API(如vListInitialise、vListInsert等)实现对链表的初始化、有序/无序插入、删除等操作。这些操作考虑了数据校验、内存优化等机制,为任务调

qq_35609890的博客 1082

FreeRTOS高级篇1---FreeRTOS列表和列表项

FreeRTOS内核调度大量使用了列表(list)这一数据结构。我们如果想一探FreeRTOS背后的运行机制,首先遇到的拦路虎就是列表。对于FreeRTOS内核来说,列表就是它最基础的部分。我们在这一章集中讲解列表和列表项的结构以及操作函数,在下一章讲解任务创建时,会用到本章的知识点。 列表被FreeRTOS调度器使用,用于跟踪任务,处于就绪、挂起、延时的任务,都会被挂接到各自的列表中。...

朱工的专栏 4万+

【FreeRTOS-列表和列表项】

FreeRTOS列表和列表项

weixin_43251807的博客 1537

FreeRTOS学习-链表(List_t)

在FreeRTOS中,List是为了任务调度器深度定制的链表,因此,理解FreeRTOS内核中的链表有助于理解任务调度的原理和实现。当然该链表也可以为应用程序所用。本文将介绍FreeRTOS中List的基本用法和关键的数据结构。

Duran.L的专栏 945

FreeRTOS-列表和列表项

FreeRTOS知识

zhuimeng_1234的博客 866

从零到一:手把手教你用Python搭建医学影像识别CNN模型(附完整代码)

本文详细介绍了如何使用Python和TensorFlow/Keras从零开始构建一个医学影像识别的CNN模型,涵盖数据预处理、模型架构设计、训练调优及部署全流程。通过实战案例和完整代码,帮助开发者快速掌握深度学习在医学影像识别中的应用,特别适合医疗AI领域的初学者和研究者。

spark7igniter的博客 200

一文带你深度了解FreeRTOS列表和列表项

要想看懂FreeRTOS源码并学习其原理,有一个东西绝对跑不了,那就是FreeRTOS 的列表和列表项。列表和列表项是FreeRTOS的一个数据结构,FreeRTOS大量使用到了列表和列表项,它是FreeRTOS 的基石。要想深入学习并理解FreeRTOS,那么列表和列表项就必须首先掌握,否则后面根本就没法进行。本篇文章分为如下几部分: 1、什么是列表和列表项 2、列表和列表项的初始化7.3列表项的插入 3、列表项末尾插入 4、列表项的删除 5、列表项的遍历

m0_73931287的博客 2564

PyTorch实战:从零构建CNN图像分类模型

卷积神经网络(CNN)作为计算机视觉的核心架构,通过局部连接和权值共享机制高效处理图像数据。其核心组件包括卷积层、池化层和全连接层,其中PyTorch的动态计算图特性为CNN实现提供了灵活的开发环境。在工程实践中,使用CIFAR-10这类标准数据集可以快速验证模型性能,而数据增强和批归一化等技术能有效提升模型泛化能力。通过PyTorch实现CNN不仅能够掌握图像分类的基本原理,还能为后续迁移学习和复杂视觉任务打下基础,特别是在结合Adam优化器和学习率调度策略后,模型收敛速度和准确率都能得到显著提升。

weixin_42405592的博客 318

FreeRTOS 列表和列表项

在FreeRTOS的源码中大量地使用了列表和列表项,因此想要深入学习FreeRTOS,列表和列表项是必备的基础知识。这里所说的列表和列表项,是FreeRTOS源码中List和List Item的直译,事实上,FreeRTOS中的列表和列表项就是数据结构中的链表和节点。列表和列表项简介1、列表(List)列表是 FreeRTOS 中最基本的一种数据结构,其在物理存储单元上是非连续、非顺序的。

程序猿追的博客 1660

深入浅出卡尔曼滤波器算法

深入浅出讲解卡尔曼滤波器的工作原理及其公式推导,讨论卡尔曼滤波器的核心公式所代表的意义及个人的理解。

m0_37835056的博客 1365

Telegram 担保交易系统搭建指南:安全可靠的交易流程实现

本文介绍了基于Telegram Bot API搭建担保交易系统的完整方案。该系统通过第三方资金托管机制解决买卖双方信任问题,支持"付款后发货"和"收货后放款"的交易流程。文章详细阐述了系统架构设计,包括Telegram Bot交互层、后端业务逻辑层、数据库层和支付接口层。核心实现步骤涵盖:1)订单创建模块处理交易信息;2)支付处理模块集成Stripe Escrow实现资金托管;3)确认收货模块完成资金划转。系统采用PostgreSQL存储交易数据,并通过FastAPI

jingpide9527的博客 1948

FreeRTOS学习笔记——列表和列表项

​ 列表项是列表中用于存放数据的地方listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于检测列表项的数据完整性 *//* 列表项的值 *//* 下一个列表项 *//* 上一个列表项 *//* 列表项的拥有者 *//* 列表项所在列表 */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于检测列表项的数据完整性 *//* 重定义成 ListItem_t */结构体中的成员作用和。

Mr_Kaws的博客 1万+

Electron - Electron failed to install correctly, please delete node_modules/electron and try install

Electron安装失败:Electron failed to install correctly, please delete node_modules/electron and try installing again,electron安装报错:Electron failed to install correctly...解决方案,Electron 未能正确安装,请删除 node_modules/electron,然后再次尝试安装,如何解决这个问题,手把手教你解决,在yarn dev时报错,electr

🏆 前端领域优质创作者 4368

FreeRTOS—列表和列表项

列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来追踪 FreeRTOS 中的任务,列表项就是存放在列表中的项目;列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向环形链表,列表和列表项的关系和下图所示:列表的特点:列表项间的地址非连续,是人为的连接到一起的,列表项的数目是由后期添加的个数决定的,随时可以改变。数组的特点:数组成员地址是连续的,数组在最初确定了成员数量后期无法改变。

m0_75103637的博客 1447

观测器选择与工程实践建议

摘要:永磁同步电机(PMSM)无传感器控制中,观测器选型需综合考虑应用场景、性能需求与成本。消费级(家电、工具)推荐滑模观测器(SMO),成本低、鲁棒性强;工业级(伺服、泵阀)适用扩展卡尔曼滤波器(EKF),精度高但计算复杂;车规级(EPS、主驱动)需混合观测器(SMO+EKF),兼顾全速域性能与可靠性。低速时需高频注入法,IPMSM更适用。SMO易实现但存在抖振,EKF调试复杂。未来趋势是混合架构与AI增强,提升适应性与性能。选型需权衡速度范围、电机类型、处理器能力及成本。

汽车软件开发 145

YOLO11改进|注意力机制篇|引入ELA注意力机制

YOLO11添加ELA注意力机制

A1983Z的博客 3647

FreeRTOS列表和列表项

FreeRTOS列表和列表项是FreeRTOS的一个数据结构,类似于链表。FreeRTOS大量使用了列表和列表项,它是FreeRTOS中的基石,方便我们学习FreeRTOS的源码和原理。列表被用于跟踪FreeRTOS的任务,列表结构为List,再文件list.h中定义。

2202_75840803的博客 976

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

学习freertos第三篇——列表和列表项

关于列表和列表项的初始化,插入和删除

2301_81047209的博客 1699

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

九、FreeRTOS之FreeRTOS列表和列表项

列表是FreeRTOS中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务列表项就是存放在列表中的项目列表相当于链表,列表项相当于节点,FreeRTOS中的列表是一个双向环形链表列表的特点:列表项间的地址非连续的,是人为的连接到一起的。列表项的数目是由后期添加的个数决定的,随时可以改变数组的特点:数组成员地址是连续的,数组在最初确定了成员数量后期无法改变在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适用列表链表这种数据结构。

王同学 1468

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

FreeRTOS的列表与列表项

FreeRTOS学习日志(5)--FReeRTOS的列表与列表项

2301_78799455的博客 1320

【07】FreeRTOS的列表和列表项

listFIRST_LIST_INTEGRITY_CHECK_VALUE /* 校验值 *//* 列表中的列表项数量 */ListItem_t * configLIST_VOLATILE pxIndex /* 用于遍历列表项的指针 */MiniListItem_t xListEnd /* 末尾列表项 */listSECOND_LIST_INTEGRITY_CHECK_VALUE /* 校验值 */} List_t;

小浪宝宝的博客 891

FreeRTOS——列表和列表项

详细介绍了列表和列表项的相关概念

2301_76901677的博客 1161
上一篇: FreeRTOS之任务基础知识
下一篇: Ubuntu之首次设置root密码
linuxweiyh
博客等级 码龄11年 171粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值