【FreeRTOS学习笔记 】学习写链表
遇到结构体定义不完全:
如图,注意不要在结构体里用到还未声明的结构体;
调试中进入硬FLAUT:
只运行到写一个结构体而已..
如图,在使用结构体指针时,需要为它分配内存:
此时访问不会
继续看有没有别的方法,并且还不知道分配内存函数做了什么;
使用单片机设置外设地址的方法,手动设置结构体的地址,RAM起始地址可以在Debug的设备看到:
效果:成功插入链表
成功删除节点:
按序插入节点:
如图成功实现链表和插入表尾、按序插入、删除节点的操作;
//手动定义结构体地址
#define List_ROOT_BASE (uint32_t)0x20000030
#define List_END_BASE (List_ROOT_BASE + 0x14)
#define ListItem_1_BASE (List_END_BASE + 0xC)
#define ListItem_2_BASE (ListItem_1_BASE + 0x14)
#define ListItem_3_BASE (ListItem_2_BASE + 0x14)
FreeRTOSConfig_user.h代码:
#ifndef FreeRTOSConfig_user_H//FreeRtos_CONFIG_H
#define FreeRTOSConfig_user_H
#define configUSE_16_BIT_TICKS 0
#endif /* FreeRTOSConfig_user_H */
portmacro.h代码:
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include "stdint.h"
#include "stddef.h"
#include "FreeRTOSConfig_user.h"
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portSHORT short
#define portLONG long
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; //Stack类型
typedef portBASE_TYPE BaseType_t; //Base类型
typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; //Tick类型
#define portMAX_DELAY (TickType_t)0xff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY (TickType_t)0xffff
#endif
#endif /* PORTMACRO_H */
list_user.h代码:
#ifndef LIST_USER_H
#define LIST_USER_H
#include "portmacro.h"
struct xLIST_ITEM //4+4+4+4+4 = 20 =0x14
{
TickType_t xItemValue; //辅助值,用于链表排序
struct xLIST_ITEM * pxNext; //指向下一节点
struct xLIST_ITEM * pxPrevious; //指向上一节点
void * pvOwner; //指向内核对象
void * pvContainer; //指向节点所在的链表
};
typedef struct xLIST_ITEM ListItem_t;
typedef struct xMINI_LIST_ITEM //4+4+4 = 12 = 0xC
{
TickType_t xItemValue;
ListItem_t * pxNext;
ListItem_t * pxPrevious;
}MiniListItem_t;
typedef struct xLIST //4+4+4+4+4 = 20 = 0x14
{
UBaseType_t uxNumberOfItems; //链表含有的节点数
ListItem_t * pxIndex; //指向...
MiniListItem_t xListEnd; //链表尾节点
}List_t;
/* 节点初始化 */
extern void vListInitialiseItem ( ListItem_t * const pxItem );
/* 链表初始化 */
extern void vListInitialise( List_t * const pxList );
/* 将节点插入到链表的尾部 */
extern void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem );
/* 将节点按照升序排列插入到链表 */
extern void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem );
/* 将节点从链表删除 */
extern UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove );
#endif
list_user.c代码:
#include "list_user.h"
/* 节点初始化 */
void vListInitialiseItem ( ListItem_t * const pxItem )
{
/* 初始未插入链表 */
pxItem->pvContainer = NULL;
}
/* 链表初始化 */
/* 结构体直接用.取成员,结构体指针要(*p).取成员,或者用-> */
void vListInitialise( List_t * const pxList )
{
pxList->uxNumberOfItems = (UBaseType_t)0U; //初始0节点
pxList->pxIndex = (ListItem_t *)&(pxList->xListEnd);//初始指尾节点
pxList->xListEnd.xItemValue = portMAX_DELAY;//尾节点排最后
pxList->xListEnd.pxNext = (ListItem_t *)&(pxList->xListEnd);//初始指自己,下同
pxList->xListEnd.pxPrevious = (ListItem_t *)&(pxList->xListEnd);
}
/* 将节点插入到链表的尾部 */
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t * pxIndex = pxList->pxIndex; //pxIndex表示插入点
pxNewListItem->pxNext = pxIndex; //操作New节点
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
pxNewListItem->pvContainer = (void *)pxList;
pxIndex->pxPrevious->pxNext = pxNewListItem; //操作连接点
pxIndex->pxPrevious = pxNewListItem;
pxList->pxIndex = pxNewListItem;
(pxList->uxNumberOfItems) ++; //操作根节点
}
/* 将节点按照升序排列插入到链表 */
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
TickType_t New_xItemValue = pxNewListItem->xItemValue;
ListItem_t * pxIterator;
if (New_xItemValue == portMAX_DELAY)
{
pxIterator = (ListItem_t *)&(pxList->xListEnd);
}else
{
for (pxIterator = (ListItem_t *)(pxList->xListEnd.pxNext); \
pxIterator->xItemValue < New_xItemValue;\
pxIterator = pxIterator->pxNext)
{
//只用于寻找节点
}
}
pxNewListItem->pxNext = pxIterator; //插入pxIterator前
pxNewListItem->pxPrevious = pxIterator->pxPrevious;
pxNewListItem->pvContainer = (void *)pxList;
pxIterator->pxPrevious->pxNext = pxNewListItem;
pxIterator->pxPrevious = pxNewListItem;
(pxList->uxNumberOfItems) ++;
}
/* 将节点从链表删除 */
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
List_t * TempList_t = pxItemToRemove->pvContainer;
if ((TempList_t->pxIndex) == pxItemToRemove)
{
TempList_t->pxIndex = pxItemToRemove->pxPrevious;
}
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
pxItemToRemove->pxNext = NULL;
pxItemToRemove->pxPrevious = NULL;
(TempList_t->uxNumberOfItems) --;
pxItemToRemove->pvContainer = NULL;
return (TempList_t->uxNumberOfItems);
}
main函数的代码:
#include "list_user.h"
//结构体地址
#define List_ROOT_BASE (uint32_t)0x20000030
#define List_END_BASE (List_ROOT_BASE + 0x14)
#define ListItem_1_BASE (List_END_BASE + 0xC)
#define ListItem_2_BASE (ListItem_1_BASE + 0x14)
#define ListItem_3_BASE (ListItem_2_BASE + 0x14)
//尝试在表尾插入节点、按序插入节点、以及删除节点
int main(void)
{
//GPIOA ((GPIO_TypeDef *) GPIOA_BASE) 参考库函数写法
//RAM 0x20000000 Size 0x1000 用30起始
List_t* List_ROOT = (List_t*)(List_ROOT_BASE);
MiniListItem_t* List_END = (MiniListItem_t*)List_END_BASE;
ListItem_t* ListItem_1 = (ListItem_t*)ListItem_1_BASE;
ListItem_t* ListItem_2 = (ListItem_t*)ListItem_2_BASE;
ListItem_t* ListItem_3 = (ListItem_t*)ListItem_3_BASE;
//List_ROOT -> xListEnd = * List_END;
vListInitialise(List_ROOT);
ListItem_1 -> xItemValue = (TickType_t)1;
vListInitialiseItem(ListItem_1);
ListItem_2 -> xItemValue = (TickType_t)2;
vListInitialiseItem(ListItem_2);
ListItem_3 -> xItemValue = (TickType_t)3;
vListInitialiseItem(ListItem_3);
vListInsertEnd (List_ROOT, ListItem_1);
vListInsertEnd (List_ROOT, ListItem_2);
vListInsertEnd (List_ROOT, ListItem_3);
uxListRemove(ListItem_2);
uxListRemove(ListItem_1);
uxListRemove(ListItem_3);
vListInsert (List_ROOT, ListItem_1);
vListInsert (List_ROOT, ListItem_2);
vListInsert (List_ROOT, ListItem_3);
uxListRemove(ListItem_2);
uxListRemove(ListItem_1);
uxListRemove(ListItem_3);
while(1);
}