首页 > 其他分享 >FreeRTOS 列表和列表项

FreeRTOS 列表和列表项

时间:2024-08-01 21:56:32浏览次数:11  
标签:FreeRTOS xListEnd pxPrevious printf t0x% 列表 pxNext

强烈建议:一定要有数据结构中链表的基础 

列表和列表项

  • 列表: 列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务。
  • 列表项:列表项就是存放在列表中的项目
  列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向环形链表

特点:

列表项间的地址非连续的,是人为的连接到一起的。列表项的数目是由后期添加的个数决定的,随时可以改变。 在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适用列表(链表)这种数据结构

列表API函数

列表函数

有关于列表的东西均在文件 list.c 和 list.h 中,首先我们先看下在list.h中的,列表相关结构体:

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

  1. 在该结构体中, 包含了两个宏,这两个宏是确定的已知常量, FreeRTOS通过检查这两个常量的值,来判断列表的数据在程序运行过程中,是否遭到破坏 ,该功能一般用于调试, 默认是不开启的
  2. 成员uxNumberOfItems,用于记录列表中列表项的个数(不包含 xListEnd);
  3. 成员 pxIndex 用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项
  4. 成员 pxIndex 用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项

列表项函数

列表项是列表中用于存放数据的地方,在 list.h 文件中,有列表项的相关结构体定义:

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							            /* 列表项的拥有者 */
    	struct xLIST * configLIST_VOLATILE pxContainer; 	/* 列表项所在列表 */
   	    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE			/* 用于检测列表项的数据完整性 */
};
typedef struct xLIST_ITEM ListItem_t; 	

  1. 成员变量 xItemValue 为列表项的值,这个值多用于按升序对列表中的列表项进行排序
  2. 成员变量 pxNext 和 pxPrevious分别用于指向列表中列表项的下一个列表项和上一个列表项
  3. 成员变量 pxOwner 用于指向包含列表项的对象(通常是任务控制块)
  4. 成员变量 pxContainer 用于指向列表项所在列表。

迷你列表项函数

迷你列表项也是列表项,但迷你列表项仅用于标记列表的末尾和挂载其他插入列表中的列表项

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;
  1.  成员变量 xItemValue 为列表项的值,这个值多用于按升序对列表中的列表项进行排序
  2. 成员变量 pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列表项
  3. 迷你列表项只用于标记列表的末尾和挂载其他插入列表中的列表项,因此不需要成员变量pxOwner 和 pxContainer,以节省内存开销

 列表和列表项的关系

双向环形链表实现

函数

描述

vListInitialise()

初始化列表

vListInitialiseItem()

初始化列表项

vListInsertEnd()

列表末尾插入列表项

vListInsert()

列表插入列表项

uxListRemove()

列表移除列表项

 列表初始化函数vListInitialise( )

void vListInitialise( List_t * const pxList )
{
    /*  初始化时,列表中只有 xListEnd,因此 pxIndex 指向 xListEnd */ 
    pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); 

    /* xListEnd 的值初始化为最大值,用于列表项升序排序时,排在最后 */
    pxList->xListEnd.xItemValue = portMAX_DELAY;

    /* 初始化时,列表中只有 xListEnd,因此上一个和下一个列表项都为 xListEnd 本身 */
    pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );    
    pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); 

    /* 初始化时,列表中的列表项数量为 0(不包含 xListEnd) */
    pxList->uxNumberOfItems = ( UBaseType_t ) 0U;

    /* 初始化用于检测列表数据完整性的校验值 */
    listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
    listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

列表项初始化函数vListInitialiseItem( )

void vListInitialiseItem( ListItem_t * const pxItem )
{	
    pxItem->pxContainer = NULL;       
    /* 初始化时,列表项所在列表设为空 */

	listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );	         
    listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
    /* 初始化用于检测列表项数据完整性的校验值 */

} 

列表项插入函数vListInsert( )

此函数用于将待插入列表的列表项按照列表项值升序进行排序,有序地插入到列表中

void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) 
{
 	ListItem_t * pxIterator; 
	const TickType_t  xValueOfInsertion = pxNewListItem->xItemValue; 
	/* 获取列表项的数值依据数值升序排列 */

	listTEST_LIST_INTEGRITY (pxList); 					
	/* 检查参数是否正确 */

	listTEST_LIST_ITEM_INTEGRITY (pxNewListItem); 			
	/* 如果待插入列表项的值为最大值 */

	if( xValueOfInsertion == portMAX_DELAY )
 	{ 
		pxIterator = pxList->xListEnd.pxPrevious; 	//插入的位置为列表 xListEnd 前面 
      
	} 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->pxContainer = pxList; 					
	/* 更新待插入列表项所在列表 */ 

	( pxList->uxNumberOfItems )++;						
	/* 更新列表中列表项的数量 */ 
}

末尾列表项插入函数vListInsertEnd( )

此函数用于将待插入列表的列表项插入到列表 pxIndex 指针指向的列表项前面,是一种无序的插入方法

void vListInsertEnd (  List_t * const pxList ,   ListItem_t * const pxNewListItem  )
{
	 省略部分非关键代码 … …	

    /* 获取列表 pxIndex 指向的列表项 */	
    ListItem_t * const pxIndex = pxList->pxIndex;

    /* 更新待插入列表项的指针成员变量 */
	pxNewListItem->pxNext = pxIndex;	
    pxNewListItem->pxPrevious = pxIndex->pxPrevious;

 	/* 更新列表中原本列表项的指针成员变量 */
	pxIndex->pxPrevious->pxNext = pxNewListItem;	
    pxIndex->pxPrevious = pxNewListItem;

	/* 更新待插入列表项的所在列表成员变量 */	
    pxNewListItem->pxContainer = pxList;

	/* 更新列表中列表项的数量 */
    ( pxList->uxNumberOfItems )++;
} 

列表项移除函数uxListRemove( )

 此函数用于将列表项从列表项所在列表中移除

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) 
{
	List_t * const pxList = pxItemToRemove->pxContainer; 
    /* 从列表中移除列表项 */ 

	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; 
    /*如果 pxIndex 正指向待移除的列表项 */ 
	 
	if  ( pxList->pxIndex == pxItemToRemove ) 
	    {
	 	    pxList->pxIndex = pxItemToRemove->pxPrevious; //pxIndex 指向上一个列表项
	    }
    else 
	    { 
		    mtCOVERAGE_TEST_MARKER(); 
	    } 

    /*将待移除的列表项的所在列表指针清空*/ 
	pxItemToRemove->pxContainer = NULL; 

    /*更新列表中列表项的数量*/ 
	( pxList->uxNumberOfItems )--; 

    /*返回移除后的列表中列表项的数量*/ 
	return pxList->uxNumberOfItems; 
}

列表项的插入和删除实验

前面代码看懂,基本上掌握了。实验代码繁杂,不过只是涉及运用,反而更加简单 ,

这一步多看看加深理解运用

/*
 任务创建看之前部分,这里只涉及任务实现
*/

List_t                  TestList;           /* 定义测试列表 */
ListItem_t              ListItem1;          /* 定义测试列表项1 */
ListItem_t              ListItem2;          /* 定义测试列表项2 */
ListItem_t              ListItem3;          /* 定义测试列表项3 */

void task1(void *pvParameters)
{
    /* 第一步:初始化列表和列表项 */
    vListInitialise    (&TestList);             /* 初始化列表 */
    vListInitialiseItem(&ListItem1);            /* 初始化列表项1 */
    vListInitialiseItem(&ListItem2);            /* 初始化列表项2 */
    vListInitialiseItem(&ListItem3);            /* 初始化列表项3 */
    

    /* 第二步:打印列表和其他列表项的地址 */
    printf("/**************第二步:打印列表和列表项的地址**************/\r\n");
    printf("项目\t\t\t地址\r\n"); 
    printf("TestList             \t\t0x%p\t\r\n",         &TestList);
    printf("TestList->pxIndex    \t0x%p\t\r\n",           TestList.pxIndex);
    printf("TestList->xListEnd   \t0x%p\t\r\n",           (&TestList.xListEnd));
    printf("ListItem1            \t\t0x%p\t\r\n",         &ListItem1);
    printf("ListItem2            \t\t0x%p\t\r\n",         &ListItem2);
    printf("ListItem3            \t\t0x%p\t\r\n",         &ListItem3);
    printf("/**************************结束***************************/\r\n");
   

    /* 第三步:列表项1插入列表 */
    printf("/*****************第三步:列表项1插入列表******************/\r\n");

    vListInsert((List_t*    )&TestList,         /* 列表 */
                (ListItem_t*)&ListItem1);       /* 列表项 */

    printf("项目\t\t\t\t地址\r\n");
    printf("TestList->xListEnd->pxNext     \t0x%p\r\n",  (TestList.xListEnd.pxNext));
    printf("ListItem1->pxNext              \t\t0x%p\r\n",(ListItem1.pxNext));
    printf("TestList->xListEnd->pxPrevious \t0x%p\r\n",  (TestList.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious          \t\t0x%p\r\n",(ListItem1.pxPrevious));
    printf("/**************************结束***************************/\r\n");
  
    
    /* 第四步:列表项2插入列表 */
    printf("/*****************第四步:列表项2插入列表******************/\r\n");

    vListInsert((List_t*    )&TestList,         /* 列表 */
                (ListItem_t*)&ListItem2);       /* 列表项 */
    printf("项目\t\t\t\t地址\r\n");
    printf("TestList->xListEnd->pxNext     \t0x%p\r\n",     (TestList.xListEnd.pxNext));
    printf("ListItem1->pxNext              \t\t0x%p\r\n",   (ListItem1.pxNext));
    printf("ListItem2->pxNext              \t\t0x%p\r\n",   (ListItem2.pxNext));
    printf("TestList->xListEnd->pxPrevious \t0x%p\r\n",  (TestList.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious          \t\t0x%p\r\n",   (ListItem1.pxPrevious));
    printf("ListItem2->pxPrevious          \t\t0x%p\r\n",   (ListItem2.pxPrevious));
    printf("/**************************结束***************************/\r\n");
   

    /* 第五步:列表项3插入列表 */
    printf("/*****************第五步:列表项3插入列表******************/\r\n");

    vListInsert((List_t*    )&TestList,         /* 列表 */
                (ListItem_t*)&ListItem3);       /* 列表项 */

    printf("项目\t\t\t\t地址\r\n");
    printf("TestList->xListEnd->pxNext    \t0x%p\r\n",      (TestList.xListEnd.pxNext));
    printf("ListItem1->pxNext             \t\t0x%p\r\n",    (ListItem1.pxNext));
    printf("ListItem2->pxNext             \t\t0x%p\r\n",    (ListItem2.pxNext));
    printf("ListItem3->pxNext             \t\t0x%p\r\n",    (ListItem3.pxNext));
    printf("TestList->xListEnd->pxPrevious\t0x%p\r\n",   (TestList.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious         \t\t0x%p\r\n",    (ListItem1.pxPrevious));
    printf("ListItem2->pxPrevious         \t\t0x%p\r\n",    (ListItem2.pxPrevious));
    printf("ListItem3->pxPrevious         \t\t0x%p\r\n",    (ListItem3.pxPrevious));
    printf("/**************************结束***************************/\r\n");
    

    /* 第六步:移除列表项2 */
    printf("/*******************第六步:移除列表项2********************/\r\n");

    uxListRemove((ListItem_t*   )&ListItem2);   /* 移除列表项 */

    printf("项目\t\t\t\t地址\r\n");
    printf("TestList->xListEnd->pxNext     \t0x%p\r\n",     (TestList.xListEnd.pxNext));
    printf("ListItem1->pxNext              \t\t0x%p\r\n",   (ListItem1.pxNext));
    printf("ListItem3->pxNext              \t\t0x%p\r\n",   (ListItem3.pxNext));
    printf("TestList->xListEnd->pxPrevious \t0x%p\r\n", (TestList.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious          \t\t0x%p\r\n",   (ListItem1.pxPrevious));
    printf("ListItem3->pxPrevious          \t\t0x%p\r\n",   (ListItem3.pxPrevious));
    printf("/**************************结束***************************/\r\n");
    
    
    /* 第七步:列表末尾添加列表项2 */
    printf("/****************第七步:列表末尾添加列表项2****************/\r\n");

    vListInsertEnd((List_t*     )&TestList,     /* 列表 */
                   (ListItem_t* )&ListItem2);   /* 列表项 */

    printf("项目\t\t\t\t地址\r\n");
    printf("TestList->pxIndex              \t\t0x%p\r\n",   TestList.pxIndex);
    printf("TestList->xListEnd->pxNext     \t0x%p\r\n",     (TestList.xListEnd.pxNext));
    printf("ListItem1->pxNext              \t\t0x%p\r\n",   (ListItem1.pxNext));
    printf("ListItem2->pxNext              \t\t0x%p\r\n",   (ListItem2.pxNext));
    printf("ListItem3->pxNext              \t\t0x%p\r\n",   (ListItem3.pxNext));
    printf("TestList->xListEnd->pxPrevious \t0x%p\r\n",  (TestList.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious          \t\t0x%p\r\n",   (ListItem1.pxPrevious));
    printf("ListItem2->pxPrevious          \t\t0x%p\r\n",   (ListItem2.pxPrevious));
    printf("ListItem3->pxPrevious          \t\t0x%p\r\n",   (ListItem3.pxPrevious));
    printf("/**************************结束***************************/\r\n");
    
    while(1)
    {
        vTaskDelay(1000);
    }
}

标签:FreeRTOS,xListEnd,pxPrevious,printf,t0x%,列表,pxNext
From: https://blog.csdn.net/weixin_51738481/article/details/140851366

相关文章

  • 微信小程序教程010:列表渲染
    文章目录列表渲染1、wx:for2、手动指定索引和当前项的变量名3、wx:key的使用列表渲染1、wx:for通过wx:for可以根据指定的数组,循环渲染重复的组件结构,语法结构如下:<viewwx:for="{{array}}"> 索引是:{{index}},当前项是:{{item}}</view>定义数......
  • 使用列表理解迭代列表
    我正在从头开始练习Python。我的代码中有两个问题。代码是将列表中的所有数字相乘。代码:str1=input("Enteryourlittlestring:")list1=str1.split()print(list1)int_list=[int(list1[int(x)])forxinrange(0,len(list1))ifstr.isdigit(list1[int(x)])]x=1......
  • 使用 with/as 上下文管理器打开文件列表
    注意:我知道withopen('f1')asf1,open('f2')asf2:...语法。这是一个不同的问题。给定一个字符串列表file_names是否有一种方法使用with/as使用单行打开其中的每个文件名。诸如:with[open(fn)forfninfile_names]......
  • 如何更新 jinja2 中的字典键值列表
    我已将字典的键domain设置为空字符串“”。我正在检查dictkeyssluser的var字段是否已定义,如果是,则我需要从提供的用户值中填写电子邮件域数据。{%setsslusers=[{'ssluser':SSL_VPN_User01,'sslusercred':SSL_USER_CRED......
  • FreeRTOS学习笔记(二)
    FreeRTOS移植一、获取FreeRTOS源码1.1官网下载进入官网直接下载官网:https://www.freertos.org/zh-cn-cmn-s/1.2正点原子网盘下载正点原子资料v10.4.6例程git:https://gitee.com/yuan-zhenbin/freertos-code-repository.gitFreeRTOS资料网盘:http://www.openedv.c......
  • el-table数据中特殊字符tooltip换行展示并且列表中超出显示省略号
     <el-table-column prop="baMsg" label="描述信息">             <template slot-scope="scope">                <el-tooltip class="item" effect="dark" placement="top-start">           ......
  • STM32F103+FreeRTOS的使用ESP8266与手机APP实现TCP连接通信控制
    前言本人初学FreeRTOS,来自不知名普通院校,大二物联网专业,简单看完百问网韦东山老师FreeRTOS就想随便找个小项目试试看,手头里没什么元器件,只有一块ESP8266wifi模块以及温湿度模块显示屏模块,所以用到的模块不多,这俩个模块可能不太适用于FreeRTOS,但主要目的想着以最少的资源练练......
  • 编写一个函数,它接受一个 str/ 单词并按顺序输出这些字符的组合列表
    基本上是标题。输入示例是:'word'空格被标记为'~',所需的输出将是:word工作~沃~dw~rdwo~~w~~d~~rd〜或〜哇~~~o~dw~~~~~r~~o~~Thereasonforthisistosearchforwordsthatmaynotbefullycompleteasthetextbeingsearchthroughfrom......
  • FreeRtos笔记1
    记录学习过程:了解简单的Arm架构,CPU中各种寄存器的作用:堆的含义(就是空闲的内存),堆的作用是用来管理这些内存(堆函数,链表):内存的栈-->每个任务都有独属于自己的栈,在自己的任务栈中会保存函数,局部变量,还有自己的现场:任务是如何进行的:任务的调度过程:......
  • 如何按特定键值有效过滤字典列表?
    我正在开发一个Python项目,我需要根据特定键的值过滤字典列表。例如,给定一个如下所示的字典列表:data=[{"name":"Alice","age":30},{"name":"Bob","age":25},{"name":"Charlie","age":35}......