(1)列表是 FreeRTOS 中最基本的一种数据结构,其在物理存储单元上是非连续、非顺序的。FreeRTOS 中的列表是一个双向链表。
(2)vListInsertEnd():用于将待插入列表的列表项插入到列表 pxIndex 指针指向列表项的前面(如果pxIndex指向listend,那么也就是将列表项插入到Listend的前面,然后例如我们假设Listend为第一个结点,那么实质就是将列表项插入到链表的最后一个,即我们可以将listend当成头节点,然后 vListInsertEnd()方法就是插入到列表的末尾)
(3)vListInsert():用于将待插入列表的列表项按照列表项值升序排序的顺序,有序地插入到列表
(4)特征1:freertos的链表是一个回环链表,然后listEnd可以看作一个头节点,存储值为MAX,用于排序
(5)特征2:如果listEnd看作一个头节点,ListEnd的pre永远指向链表的最后一个结点,而listEnd的next永远指向链表的第一个结点
(6) TestList.pxIndex = &ListItem1;如果将列表的pxIndex指向的结点改变,那么vListInsertEnd插入的结点位置不在是listend的前面,而是ListItem1结点的前面,并且pxIndex指向的结点改变,并不会改变之前链表的任何指向关系(包括Listend),但是改变vListInsertEnd插入结点的位置
(7)不可以重复插入同一个列表项,因为他们的地址是相同的,然后如果再次插入之后,链表之间的指向就会混乱,比如l1,l2,l3,他们的值分别是1,2,3,然后我要再次插入l2,此时链表为l1,l2,l2,l3,但是因为l2的地址是一样的,所以l2的next会指向l2,l2的pre也会指向l2,此时链表直接断开
(7)注意:博主此处将listend当作C语言链表中带头结点的链表来处理,方便理解(也可以把Listend当成列表的最后一个结点,因为链表本身就是双向循环列表,所谓的头结点都是为了方便理解)
#include "freeRTOS_demo.h"
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2( void * pvParameters );
List_t TestList; /* 定义测试列表 */
ListItem_t ListItem1; /* 定义测试列表项1 */
ListItem_t ListItem2; /* 定义测试列表项2 */
ListItem_t ListItem3; /* 定义测试列表项3 */
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t ) start_task,
(char * ) "start_task",
(configSTACK_DEPTH_TYPE ) START_TASK_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t * ) &start_task_handler );
vTaskStartScheduler();
}
void start_task( void * pvParameters )
{
taskENTER_CRITICAL(); /* 进入临界区 */
xTaskCreate((TaskFunction_t ) task2,
(char * ) "task2",
(configSTACK_DEPTH_TYPE ) TASK2_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(TaskHandle_t * ) &task2_handler );
vTaskDelete(NULL);
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task2( 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");
//双向循环链表顺序 listend listItem1 listItem3 listItem2
vListInsert( (List_t*)&TestList , (ListItem_t*)&ListItem1 );
vListInsert( (List_t*)&TestList , (ListItem_t*)&ListItem2 );
vListInsert( (List_t*)&TestList , (ListItem_t*)&ListItem3 );
//双向循环链表顺序 listend listItem1 listItem2
uxListRemove((ListItem_t*)&ListItem3);
//双向循环链表顺序 listend listItem1 listItem2 listItem3
vListInsertEnd( (List_t*)&TestList , (ListItem_t* )&ListItem3 );
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)
{
}
}