网上的freeRTOS链表教程

网上的创建链表相关链接

之前找了半天的STM32的FreeRTOS关于链表的例程,没有什么好的例子,只有这几篇详细介绍了一下list.c的几个函数,其实FreeRTOS的task和time设计都有用到链表管理。

1.理解freertos链表LIST之插入 - unsv29的专栏 - 优快云博客

https://blog.youkuaiyun.com/unsv29/article/details/52525882

 

2.理解FreeRtos的链表 - unsv29的专栏 - 优快云博客

https://blog.youkuaiyun.com/unsv29/article/details/52485649

 

3.【连载】从单片机到操作系统⑤——FreeRTOS列表&列表项的源码解读 - 杰杰的博客 - 优快云博客

https://blog.youkuaiyun.com/jiejiemcu/article/details/80637559

 

4.FreeRTOS内核详解----LIST - hehao9051的专栏 - 优快云博客

https://blog.youkuaiyun.com/hehao9051/article/details/51477127

 

 

 

顺便了解一下堆栈:

1.STM32 大小端模式 与 堆栈及其增长方向分析 - baihengpei的博客 - 优快云博客

https://blog.youkuaiyun.com/xiaobai20131/article/details/50908584

 

2.浅谈STM32堆栈与uCOS堆栈,其实是两码事!~ - qq_23922117的博客 - 优快云博客

https://blog.youkuaiyun.com/qq_23922117/article/details/79400051

 

 

 

### FreeRTOS 链表的使用与实现 #### 数据结构解析 FreeRTOS中的链表通过`struct xLIST_ITEM`来表示单个节点[^2]: ```c struct xLIST_ITEM { TickType_t xItemValue; struct xLIST_ITEM * pxNext; struct xLIST_ITEM * pxPrevious; void * pvOwner; void * pvContainer; }; typedef struct xLIST_ITEM ListItem_t; ``` - `xItemValue`: 用于辅助节点按特定顺序排列。 - `pxNext`, `pxPrevious`: 分别指向前驱和后继节点,形成双向链接关系。 - `pvOwner`: 指向拥有当前节点的任务控制块(TCB),即任务描述符。 - `pvContainer`: 表明该节点所属的具体列表实例。 对于简化版本的小型列表项(`MiniListItem_t`),则省去了`pvOwner`和`pvContainer`字段[^3]。 #### 列表定义 整个列表由`List_t`结构体表示: ```c typedef struct xLIST { volatile UBaseType_t uxNumberOfItems; ListItem_t * configLIST_VOLATILE pxIndex; MiniListItem_t xListEnd; } List_t; ``` 其中, - `uxNumberOfItems`记录了列表内的有效条目数; - `pxIndex`作为迭代器作用于遍历过程之中; - 特殊哨兵节点`xListEnd`被置于队列末端以方便检测边界条件。 #### 初始化操作 创建并初始化一个新的空闲列表可通过如下方式完成: ```c void vListInitialise( List_t * const pxList ) { /* Initialize the list end */ memset((void *) &(pxList->xListEnd), 0, sizeof(pxList->xListEnd)); /* Set up a circular linked list with only one item (the dummy node). */ pxList->xListEnd.xItemValue = portMAX_DELAY; pxList->xListEnd.pxNext = &pxList->xListEnd; pxList->xListEnd.pxPrevious = &pxList->xListEnd; /* The number of items in an empty list is obviously zero. */ pxList->uxNumberOfItems = (UBaseType_t) 0; } ``` 这段代码片段展示了如何设置一个仅含虚拟头结点的循环双端链表,并将其计数值设为零[^1]。 #### 插入新元素 当需要往已有的有序序列里加入新的成员时,可以采用下面的方法: ```c void vListInsert(List_t* pxList, ListItem_t* pxNew){ // Find where to place this new element within the sorted order. while ((pxIterator != NULL) && (listGET_LIST_ITEM_VALUE(pxIterator) <= pxNew->xItemValue)){ pxIterator = pxIterator->pxNext; } prvInsertBetweenNodes(pxPrevNodeOfTargetPosition, pxIterator, pxNew); ++(pxList->uxNumberOfItems); } static inline void prvInsertBetweenNodes( ListItem_t *const pxFirst, ListItem_t *const pxSecond, ListItem_t *const pxNewItemToBeInserted) { pxNewItemToBeInserted->pxNext = pxSecond; pxNewItemToBeInserted->pxPrevious = pxFirst; pxFirst->pxNext = pxNewItemToBeInserted; if (pxSecond != NULL) { pxSecond->pxPrevious = pxNewItemToBeInserted; } } ``` 上述逻辑首先定位到合适位置再执行实际插入动作,确保整体保持升序状态。同时更新前后相邻两者的连接指向以及调整总数统计。 #### 移除现有项目 要删除指定的目标,则需先找到目标所在的位置然后再解除其关联: ```c void vRemoveFromList(const ListItem_t * const pxItemToRemove){ /* Remove from its current position and update links around it.*/ pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; if (NULL != pxItemToRemove->pxNext){ pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; } --(pxItemToRemove->pvContainer->uxNumberOfItems); } ``` 这里不仅修正了周围邻居之间的相互引用还同步减少了容器内部的对象数目。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值