【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);
}