【FreeRTOS源码阅读】<1> list.c

struct xLIST_ITEM
{
	TickType_t xItemValue;			/*< 链表节点的值。 在大多数情况下,它用于按降序对列表进行排序 */
	struct xLIST_ITEM * pxNext;		/*< 指向链表中下一个 ListItem_t  */
	struct xLIST_ITEM * pxPrevious;	/*< 指向链表中上一个 ListItem_t  */
	void * pvOwner;					/*< 指向包含列表项的对象(通常是TCB)的指针。 因此,在包含列表项的对象与列表项本身之间存在双向链接。 */
	void * pvContainer;				/*< 指向放置此列表项的列表的指针(如果有)。 */
};

struct xMINI_LIST_ITEM
{
	configLIST_VOLATILE TickType_t xItemValue;
	struct xLIST_ITEM * configLIST_VOLATILE pxNext;
	struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};

typedef struct xLIST
{
	UBaseType_t uxNumberOfItems;    /*< 当前列表包含的项目数量 >*/
	ListItem_t * pxIndex;		    /*< 用于遍历列表。 指向通过调用listGET_OWNER_OF_NEXT_ENTRY()返回的最后一项。 */
	MiniListItem_t xListEnd;		/*< 列表项目包含最大可能的项目值,这意味着它始终位于列表的末尾,因此用作标记。 */
} List_t;

以上三个结构体是 FreeRTOS用的链表的三个格式。


void vListInitialise( List_t * const pxList )
{
	/* The list structure contains a list item which is used to mark the
	end of the list.  To initialise the list the list end is inserted
	as the only list entry. */
	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );			/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */

	/* The list end value is the highest possible value in the list to
	ensure it remains at the end of the list. */
	pxList->xListEnd.xItemValue = portMAX_DELAY;

	/* The list end next and previous pointers point to itself so we know
	when the list is empty. */
	pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );	/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */

	pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
}

上面的代码是链表的初始化程序,经过该函数初始化后链表内容如下:


void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t * const pxIndex = pxList->pxIndex;

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

	pxNewListItem->pvContainer = ( void * ) pxList;

	( pxList->uxNumberOfItems )++;
}

上面的代码是将pxNewListItem插入到pxList链表中函数。

描述:

将列表项插入列表。 该项目将被插入到这样的位置,即它将成为多次调用listGET_OWNER_OF_NEXT_ENTRY返回的列表中的最后一个项目。列表成员pvIndex用于遍历列表。 调用listGET_OWNER_OF_NEXT_ENTRY将pvIndex递增到列表中的下一项。 使用vListInsertEnd将项目放置在列表中可以有效地将项目放置在pvIndex指向的列表位置。 这意味着在pvIndex参数再次指向要插入的项目之前,列表GET_OWNER_OF_NEXT_ENTRY将返回列表中的所有其他项目。

调用该函数插入三个新项目后链表结构如下:


void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t *pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;

	/* 根据新插入的项目的值有序的插入到链表中。

	如果链表中已经包含具有相同项目值的项目,则应在其后放置新的项目。 这样可确保存储在就绪列表(所有列表均具有相同的xItemValue值)中的TCB获得同等的CPU资源(言外之意就是如果有相同优先级的任务则按先后顺序进行执行)。 但是,如果项目的值等于ListEnd的项目值这个时候应该检查一下是不是哪里设置错误 */
	if( xValueOfInsertion == portMAX_DELAY )
	{
		pxIterator = pxList->xListEnd.pxPrevious;
	}
	else
	{

		for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
		{
			/* 此处不进行任何操作,等到迭代器找到合适的位置就退出 */
		}
	}

	pxNewListItem->pxNext = pxIterator->pxNext;
	pxNewListItem->pxNext->pxPrevious = pxNewListItem;
	pxNewListItem->pxPrevious = pxIterator;
	pxIterator->pxNext = pxNewListItem;

	/* 更新该链表项目存储的容器 */
	pxNewListItem->pvContainer = ( void * ) pxList;

	( pxList->uxNumberOfItems )++;
}

上面的代码是将pxNewListItem按xItemValue的值按照顺序的排序方式插入到链表中。

列表中出入三个新元素后结构如下:


UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
/* 链表项目知道自己在哪个链表中 (pvContainer表示该项目在哪个链表中)*/
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;

	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

	/* 确保pxIndex 指向一个有效值 */
	if( pxList->pxIndex == pxItemToRemove )
	{
		pxList->pxIndex = pxItemToRemove->pxPrevious;
	}

	pxItemToRemove->pvContainer = NULL;
	( pxList->uxNumberOfItems )--;

	return pxList->uxNumberOfItems;
}

上面代码是删除一个链表项目。

如上一步所示,删除pxNewListItem2后,链表结构如下:

至此,所有的list.c的代码已经结束

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以通过以下步骤下载FreeRTOS源码: 1. 访问FreeRTOS官网,点击页面上的"Download"按钮。 2. 在下载页面中,选择您需要的版本并点击下载按钮。 3. 下载完成后,双击打开下载文件,并点击"Extract"按钮进行解压。 4. 打开刚刚设置的下载路径,您会看到已经下载完成的FreeRTOS源码文件夹。其中,"Source"文件夹是您需要的源码文件,它包含了FreeRTOS的核心代码。 5. 如果您需要进行Keil工程移植,可以将源码文件复制到您的工程文件夹中。 6. 在移植过程中,您可能需要保留"portable"文件夹中的"keil"、"MemMang"和"RVDS"这三个文件夹,其他文件夹可以删除。 7. 打开Keil工程,创建分组并添加源码文件。 8. 添加相应的头文件路径,并进行编译。如果遇到无法打开"FreeRTOSConfig.h"文件的错误提示,您可以自行创建该文件,或者从FreeRTOS官方移植工程的Demo文件夹中找到相应的配置文件并添加到工程中。 9. 完成以上步骤后,您可以继续进行您的工程开发了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [STM32-FreeRTOS源码下载及移植步骤(基于Keil)](https://blog.csdn.net/qq_37596943/article/details/88934115)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值