FreeRTOS列表与列表项

FreeRTOS中的列表与列表项本质是数据结构中的链表链表和节点。

1. 列表与列表项

1.1 列表

列表属于RTOS中基本的数据结构,物理单元上非连续、非顺序。FreeRTOS中的列表是一个双向链表,在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;
  • 定义中的两个校验宏用于存已知常量,FreeRTOS通过校验这两个值来判断列表的程序在运行过程是否遭到破坏。一般用于调试过程,默认不开启
  • uxNumberOfItems记录列表中列表项的数量,不包括xListEnd
  • pxIndex用于指向列表中的某一个列表项(个人认为类似于链表中的头节点)
  • xListEnd迷你列表项,升序排列挂在最末尾

结构图大致如下:
列表

2. 列表项

列表项的定义如下:

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;/* 重定义成ListItem_t */
  • 与列表一样,包含两个用作校验数据完整性的宏
  • xItemValue为列表项的值,该值多用于按升序对列表进行排序
  • pxNext和pxPrevious用于指向上一个与下一个
  • pxContainer用于指向列表项所在的列表
  • pvOwner用于指向包含列表项的对象(如任务控制块)

结构如下所示:
列表项
迷你列表项定义如下:

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;/* 重定义成MiniListItem_t */
  • 迷你列表项中也同样包含用于检测列表项数据完整性的宏定义。
  • 相对于列表项,因为只用于标记列表的末尾和挂载其他插入列表中的列表项,
    因此不需要成员变量pxOwner 和pxContainer,以节省内存开销。

示意图如下:

在这里插入图片描述

2. 相关API

  • vListInitialise() 初始化列表,参数是待初始化的列表。初始化的时候,xListEnd手拉手
  • vListInitialiseItem() 初始化列表项,参数是待初始化的列表项
  • vListInsertEnd() 在pIndex前插入列表项,参数是列表,待插入的列表项
  • vListInsert() 插入列表项,参数是列表,待插入的列表项
  • uxListRemove() 列表移除列表项,参数是待移除的列表项

初始化后的列表与列表项结构如下:

在这里插入图片描述

3. 列表项插入与删除实验

我们在任务1中测试列表项的插入与删除,前面几篇文章也说了好几遍如何创建任务了,这里就不在赘述了。

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"); 
	printf("按下KEY0键继续!\r\n\r\n\r\n"); 
	while (key_scan(0) != KEY0_PRES) 
	{ 
		vTaskDelay(10); 
	}
	/* 第三步:列表项1插入列表 */ 
	printf("/*****************第三步:列表项1插入列表******************/\r\n"); 
	vListInsert( 
		(List_t* )&TestList, /* 列表 */ 
		(ListItem_t* )&ListItem1); /* 列表项 */ 
	/* 打印信息,代码省略 */ 
	while (key_scan(0) != KEY0_PRES) 
	{ 
		vTaskDelay(10); 
	} 
	/* 第四步:列表项2插入列表 */ 
	printf("/*****************第四步:列表项2插入列表******************/\r\n"); 
	vListInsert( 
		(List_t* )&TestList, /* 列表 */ 
		(ListItem_t* )&ListItem2); /* 列表项 */ 
	/* 打印信息,代码省略 */ 
	while (key_scan(0) != KEY0_PRES) 
	{ 
		vTaskDelay(10); 
	} 
	/* 第五步:列表项3插入列表 */ 
	printf("/*****************第五步:列表项3插入列表******************/\r\n"); 
	vListInsert( 
		(List_t* )&TestList, /* 列表 */ 
		(ListItem_t* )&ListItem3); /* 列表项 */ /* 
	打印信息,代码省略 */ 
	while (key_scan(0) != KEY0_PRES) { 
		vTaskDelay(10); 
	} 
	/* 第六步:移除列表项2 */ 
	printf("/*******************第六步:移除列表项2********************/\r\n"); 
	uxListRemove((ListItem_t*)&ListItem2); /* 移除列表项 */ 
	/* 打印信息,代码省略 */ 
	while (key_scan(0) != KEY0_PRES) { 
		vTaskDelay(10); 
	} 
	/* 第七步:列表末尾添加列表项2 */ 
	printf("/****************第七步:列表末尾添加列表项2****************/\r\n"); 
	vListInsertEnd( 
		(List_t* )&TestList, /* 列表 */
		(ListItem_t* )&ListItem2); /* 列表项 */ 
	/* 打印信息,代码省略 */ 
	while(1) { 
		vTaskDelay(10); 
	} 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FreeRTOS中,任务、队列、信号量等都是以列表的形式存储的,因此,列表的遍历是非常常见的操作。FreeRTOS提供了一些API来遍历不同类型的列表。 以任务列表为例,FreeRTOS提供了以下API来遍历任务列表: 1. `vTaskList()`:此API将任务列表的详细信息打印到标准输出。 2. `vTaskGetRunTimeStats()`:此API将任务列表中每个任务的运行时间、CPU使用率等信息打印到标准输出。 如果你需要在代码中遍历任务列表,可以使用以下API: 1. `vTaskSuspendAll()`:此API将所有任务暂停,以便安全地遍历任务列表。 2. `xTaskGetNextTask()`:此API返回一个指向下一个任务控制块的指针。 3. `xTaskResumeAll()`:此API将所有任务恢复,以便它们可以继续执行。 以下是一个示例代码,展示了如何使用上述API来遍历任务列表: ``` void vTaskListAll(void) { TaskStatus_t *pxTaskStatusArray; volatile UBaseType_t uxArraySize, x; // 获取任务数量 uxArraySize = uxTaskGetNumberOfTasks(); // 分配存储任务状态信息的内存 pxTaskStatusArray = pvPortMalloc(sizeof(TaskStatus_t) * uxArraySize); // 获取任务状态信息 uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, NULL); // 打印任务状态信息 printf("TaskName\t\tPriority\tStatus\t\tStackHighWaterMark\n"); for(x = 0; x < uxArraySize; x++) { printf("%s\t\t%d\t\t%s\t\t%d\n", pxTaskStatusArray[x].pcTaskName, pxTaskStatusArray[x].uxCurrentPriority, pxTaskStatusArray[x].eCurrentState == eRunning ? "Running" : pxTaskStatusArray[x].eCurrentState == eReady ? "Ready" : pxTaskStatusArray[x].eCurrentState == eBlocked ? "Blocked" : "Unknown", pxTaskStatusArray[x].usStackHighWaterMark); } // 释放存储任务状态信息的内存 vPortFree(pxTaskStatusArray); } ``` 这个函数将列出所有任务的名称、优先级、状态和堆栈高水位标记。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐大队队长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值