FreeRTOS实时操作系统(六)列表与列表项

这篇具有很好参考价值的文章主要介绍了FreeRTOS实时操作系统(六)列表与列表项。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章

FreeRTOS实时操作系统(一)RTOS的基本概念

FreeRTOS实时操作系统(二)任务创建与任务删除(HAL库)

FreeRTOS实时操作系统(三)任务挂起与恢复

FreeRTOS实时操作系统(四)中断任务管理

FreeRTOS实时操作系统(五)进入临界区、任务调度器挂起与恢复

FreeRTOS实时操作系统(六)列表与列表项

FreeRTOS实时操作系统(七)时间片调度及RTOS的滴答定时器

FreeRTOS实时操作系统(八)任务状态查询及时间统计函数

FreeRTOS实时操作系统(九)时间延时函数及消息队列

FreeRTOS实时操作系统(十)信号量

FreeRTOS实时操作系统(十一)队列集

FreeRTOS实时操作系统(十二)事件标志组

FreeRTOS实时操作系统(十三)任务通知

FreeRTOS实时操作系统(十四)软件定时器

FreeRTOS实时操作系统(十五)Tickless低功耗模式

FreeRTOS实时操作系统(十六)内存管理



前言

接着学习正点原子的FreeRTOS教程,实际操作我是利用STM32CubeMX生成的库实现的,板子是STM32F1093C6T6


简要概念

列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务。
列表项就是存放在列表中的项目

FreeRTOS实时操作系统(六)列表与列表项
FreeRTOS 中的列表是一个双向环形链表。

列表的特点:列表项间的地址非连续的,是人为的连接到一起的。列表项的数目是由后期添加的个数决定的,随时可以改变。

列表的相关文件全部都在list.c和list.h中:

列表

FreeRTOS实时操作系统(六)列表与列表项

从上到下代表着:校验值、列表中的列表项的个数、遍历列表项的指针、末尾列表项、校验值

其中,末尾列表项是一个迷你列表项,排在末尾。

原本代码及注释:

typedef struct xLIST
{
	listFIRST_LIST_INTEGRITY_CHECK_VALUE				/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
	volatile UBaseType_t uxNumberOfItems;
	ListItem_t * configLIST_VOLATILE pxIndex;			/*< Used to walk through the list.  Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
	MiniListItem_t xListEnd;							/*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
	listSECOND_LIST_INTEGRITY_CHECK_VALUE				/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
} List_t;

列表项

FreeRTOS实时操作系统(六)列表与列表项
在xLIST_ITEM中,从上到下分别代表着:
校验列表项的数据完整性、用于降序排列的值、指向下一个链表项、指向上一个链表项、列表项的拥有者(通常是任务控制块)、指向列表项所在的列表、校验列表项的数据完整性。
(有点疑问,这里注释是说按照降序排列,而正点原子讲的是按照升序排列)

原本代码及注释:

struct xLIST_ITEM
{
	listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
	configLIST_VOLATILE TickType_t xItemValue;			/*< The value being listed.  In most cases this is used to sort the list in descending order. */
	struct xLIST_ITEM * configLIST_VOLATILE pxNext;		/*< Pointer to the next ListItem_t in the list. */
	struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;	/*< Pointer to the previous ListItem_t in the list. */
	void * pvOwner;										/*< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */
	void * configLIST_VOLATILE pvContainer;				/*< Pointer to the list in which this list item is placed (if any). */
	listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t;					/* For some reason lint wants this as two separate definitions. */

迷你列表项

原本代码及注释:

struct xMINI_LIST_ITEM
{
	listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
	configLIST_VOLATILE TickType_t xItemValue;
	struct xLIST_ITEM * configLIST_VOLATILE pxNext;
	struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

从上到下代表着:检测数据完整性、列表项的值、下一个列表、上一个列表

迷你列表项只用于标记列表的末尾和挂载其他插入列表中的列表项,因此不需要成员变量 pxOwner 和 pxContainer,以节省内存开销。

实例:
FreeRTOS实时操作系统(六)列表与列表项

相关API函数

初始化列表:vListInitialise()
初始化列表项:vListInitialiseItem()
列表末尾插入列表项:vListInsertEnd()
列表按照数值升序插入列表项:vListInsert()
列表移除列表项:uxListRemove()

初始化列表

由下图的初始化列表可知,xListEnd末尾列表项被定义为最大值,所以推测前面的注释意思应该是按照升序排列的。
FreeRTOS实时操作系统(六)列表与列表项
FreeRTOS实时操作系统(六)列表与列表项
FreeRTOS实时操作系统(六)列表与列表项

列表项初始化

FreeRTOS实时操作系统(六)列表与列表项
FreeRTOS实时操作系统(六)列表与列表项
列表项所属列表先不赋值。

列表项插入(升序)

void vListInsert  (  List_t * const pxList ,   ListItem_t * const pxNewListItem  )

将列表项按照其项值的升序方式插入列表

正点原子的视频中讲的很清除关于这一部分是如何插入的
FreeRTOS实时操作系统(六)列表与列表项
插入第一个列表项的过程:
FreeRTOS实时操作系统(六)列表与列表项

末尾列表项插入

这里并不是指最后一个列表项,是指插入到当前列表pxIndex指向的列表项的前一个位置
FreeRTOS实时操作系统(六)列表与列表项
这是一种无序插入

例如:如果pxIndex指向的是xListEnd时,插入的情况:
FreeRTOS实时操作系统(六)列表与列表项

列表项删除

FreeRTOS实时操作系统(六)列表与列表项

这里移除列表项的时候没有将内存释放,有文章说可能后续还要使用,所以没有释放,还不是很懂现在。

实战实验

实验代码:

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

void vTaskCode( void * pvParameters )
 {
	 
	vListInitialise(&TestList);         /* 初始化列表 */
    vListInitialiseItem(&ListItem1);    /* 初始化列表项1 */
    vListInitialiseItem(&ListItem2);    /* 初始化列表项2 */
    vListInitialiseItem(&ListItem3);    /* 初始化列表项3 */
    ListItem1.xItemValue = 40;
    ListItem2.xItemValue = 60;
    ListItem3.xItemValue = 50;

    /* 第二步:打印列表和其他列表项的地址 */
    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("\r\n/*****************第三步:列表项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("\r\n/*****************第四步:列表项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("\r\n/*****************第五步:列表项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("\r\n/*******************第六步:移除列表项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("\r\n/****************第七步:列表末尾添加列表项2****************/\r\n");
    TestList.pxIndex = &ListItem1;
    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);
    }
 }

首先,创建了三个列表项,每个列表项都有自己的地址,然后我们对各个函数进行测试,在第五步列表项3插入之后,列表的
pxIndex仍然指向的是末尾列表项,所以这个时候删除列表项后,pxIndex也还指向的是末尾列表项。在第七步中,我们指定了pxIndex指向列表项1,所以末尾列表项插入时,插入到列表项1前面。如果不指定的话,按照上一步操作后pxIndex指向的是末尾列表项,所以插入后会出现在末尾列表项前面。
实验结果:

FreeRTOS实时操作系统(六)列表与列表项
FreeRTOS实时操作系统(六)列表与列表项文章来源地址https://www.toymoban.com/news/detail-496886.html

到了这里,关于FreeRTOS实时操作系统(六)列表与列表项的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于STM32的实时操作系统FreeRTOS移植教程(手动移植)_stm32移植freertos(1)

    直接意识代码: 这是我们大脑最希望的添加代码方式,很显然他是 错的 , 两个任务之间产生了相互的影响 ,使得两个任务都执行错误,这种思想在 裸机开发 中肯定是 错的 ,但是在我们的 RTOS 中他就可以是 对的 。 任务型代码: 这是 独立的两个任务内容 ,我们只需要把

    2024年04月10日
    浏览(104)
  • STM32基于HAL库和STM32CubeMX的实时操作系统FreeRtOS开发

    1、FreeRTOS RTOS是一类操作系统,µC/OS,FreeRTOS,RTX,RT-Thread 等这些都是RTOS 类的操作系统 FreeRTOS 是众多RTOS 类操作系统中的一种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行,FreeRTOS 也不仅仅局限于在微控制器中使用。就单从文件数量上来看FreeRTOS 要比µC/OS 少得多

    2024年02月21日
    浏览(60)
  • STM32移植FreeRTOS操作系统

    一、FreeRTOS源码下载 (1)移植钱得准备前菜对吧,我们先来去官网瞄一瞄 网址:FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions 第一步:点击下载FreeRTOS 第二步:选择版本下载(我选择稳定版本) 注:我们下载的稳定版本不包含DEMO例

    2024年01月17日
    浏览(36)
  • STM32FreeRTOS操作系统移植

    移植好的FreeRTOS模板: 链接:https://pan.baidu.com/s/1_87VQAWXUl4jTqSCZ0MFjw?pwd=dw52  提取码:dw52 1.在工程中新建FreeRTOS文件夹 2.把源码source里面的文件全部粘贴进FreeRTOS文件夹中  3.在portable文件中只保留一下文件,其余删除  4.新建如下两个文件夹  5.在FreeRTOS_CODE目录下添加以下文件

    2024年02月08日
    浏览(43)
  • STM32操作系统FreeRTOS学习——基于hal库

    目录 一、基础概念 1、FreeRTOS 2、单片机编程的系统概念 a、裸机系统,包括轮询系统(不包括中断)和前后台系统(中断为前台,轮询为后台) b、多任务系统 3、FreeRTOS编程风格 a、数据类型 b、变量名的定义 c、函数名 d、宏定义 二、Cubemx创建工程 1、创建任务 2、创建队列

    2024年02月10日
    浏览(38)
  • 如何剪裁操作系统源码——移植FreeRTOS的内存管理模块到ARMV8裸片

    本文面向的需求场景是,为缺乏标准库实现的处理器IP移植内存管理模块,即为裸片部署C标准库中的 malloc() 和 free() 函数。 具体做法是——从操作系统的内存管理组件中剪裁出必要的源码,适配到目标处理器的开发环境(SDK/IDE/CMAKE工程子目录)中。 1.1 C标准库中的内存管理

    2024年02月13日
    浏览(34)
  • 微控制器实时操作系统实践1实时系统介绍

    这本实践指南将为你提供最重要的功能知识,以使实时操作系统(RTOS)在微控制器(MCU)上启动和运行。如果你有兴趣学习如何通过使用实际硬件的实例来实现RTOS的应用,并讨论常见的性能与开发时间的权衡,那么你就来对地方了!我们将使用自由RTOS来实现代码! 我们将使

    2024年02月08日
    浏览(42)
  • 物联网实时操作系统1RTOS简介(上)

    在大型计算机的世界里,操作系统(OS operating systems)已经存在了相当长的一段时间。最基本的操作系统可以追溯到20世纪50年代。到20世纪70年代中期,操作系统的概念、结构、功能和界面已经非常成熟。 微型系统大约在 1970年出现。在基于微处理器的设备中迅速应用操作系统

    2024年02月16日
    浏览(56)
  • 微控制器实时操作系统实践5选择IDE

    集成开发环境(IDE integrated development environment)有能力极大地影响开发。集成开发环境被设计成具有较小的学习曲线,并且通常提供一种简单的方法来从现有的驱动程序和中间件建立解决方案。 在本章中,我们将讨论如何选择IDE,看看不同类型的IDE,并选择一个IDE来创建你在

    2024年02月08日
    浏览(46)
  • 嵌入式实时操作系统的设计与开发

    在RTOS中,时钟具有非常重要的作用,通过时钟可实现延时任务、周期性触发任务执行、任务有限等待的计时。 大多数嵌入式系统有两种时钟源,分别为实时时钟RTC(Real-Time Clock)和定时器/计数器。 实时时钟一般是靠电池供电,即使系统断电,也可以维持日期和时间。由于实

    2024年02月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包