一、实验目标
创建三个动态任务,栈空间大小均为128字。startTask、Task1、Task2。startTask仅运行一次,负责task1、task2任务的创建,startTask任务的删除。Task1负责初始化列表、列表项123,并进行列表项的插入实验与删除实验。Task2负责5S闪烁一次LED0,用于指示系统的运行状态。
注:本实验基于正点原子FreeRTOS教程的学习总结。
二、实验准备
1.FreeRTOS的Keil动态任务创建与删除程序
2.STM3F407开发板
3.列表与列表项结构体
列表结构体List_t如下,主要包含两个校验值、列表中包含列表项的数量、用于遍历列表项的指针、末尾列表项。
/*
* Definition of the type of queue used by the scheduler.
*/
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE /* 校验值 */
volatile UBaseType_t uxNumberOfItems; /* 列表中列表项的数量 */
ListItem_t * configLIST_VOLATILE pxIndex; /* 用于遍历列表项的指针 */
MiniListItem_t xListEnd; /* 末尾列表项 */
listSECOND_LIST_INTEGRITY_CHECK_VALUE /* 校验值 */
} List_t;
列表项结构体ListItem_t如下,主要包含校验值、列表项值、上下列表项地址、所属列表、对应任务指针。
struct xLIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 校验值 */
configLIST_VOLATILE TickType_t xItemValue; /* 列表项值 */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /* 下一个列表项 */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /* 上一个列表项*/
void * pvOwner; /* 所属列表 */
struct xLIST * configLIST_VOLATILE pxContainer; /* 对应任务指针 */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 校验值 */
};
typedef struct xLIST_ITEM ListItem_t;
4.所需API函数介绍(list.c/list.)
vListInitialise函数用来初始化列表,输入为需要初始化的列表。
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
vListInitialiseItem函数用来初始化列表项,输入为需要初始化的列表项。
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
vListInsert函数用来顺序的将列表项插入列表,输入为列表、列表项。有序插入是将列表项俺早列表项值的大小,从小到大排序插入。
void vListInsert( List_t * const pxList,
ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
vListInsertEnd函数用来无序的将列表项插入列表,输入为列表、列表项。无序插入是将所需插入的列表项插入到当前列表项前一个。
void vListInsertEnd( List_t * const pxList,
ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
uxListRemove函数用于删除列表项,输入为待删除的列表项。
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
三、代码编写
3.1修改Task1的任务函数内容
Task1分为五步。第一步初始化列表与列表项,第二步打印列表项和列表的地址,第三步将列表项123顺序插入到列表中,第四步移除列表项2,第五步将列表项2无序插入到列表。
void task1(void *pvParameters)
{
/* 第一步:初始化列表和列表项 */
vListInitialise(&TestList); /* 初始化列表 */
vListInitialiseItem(&ListItem1); /* 初始化列表项1 */
vListInitialiseItem(&ListItem2); /* 初始化列表项2 */
vListInitialiseItem(&ListItem3); /* 初始化列表项3 */
/* 第二步:打印列表和其他列表项的地址 */
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");
/* 第三步:列表项1/2/3插入列表 */
printf("\r\n/*****************第三步:列表项1/2/3插入列表******************/\r\n");
vListInsert((List_t* )&TestList, /* 列表 */
(ListItem_t*)&ListItem1); /* 列表项1 */
vListInsert((List_t* )&TestList, /* 列表 */
(ListItem_t*)&ListItem2); /* 列表项2 */
vListInsert((List_t* )&TestList, /* 列表 */
(ListItem_t*)&ListItem3); /* 列表项3 */
printf("项目\t\t\t\t地址\r\n");
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");
/* 第四步:移除列表项2 */
printf("\r\n/*******************第四步:移除列表项2********************/\r\n");
uxListRemove((ListItem_t* )&ListItem2); /* 移除列表项 */
printf("项目\t\t\t\t地址\r\n");
printf("TestList->xListEnd->pxNext\t0x%p\r\n", (TestList.xListEnd.pxNext));
printf("ListItem1->pxNext\t\t0x%p\r\n", (ListItem1.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("ListItem3->pxPrevious\t\t0x%p\r\n", (ListItem3.pxPrevious));
printf("/**************************结束***************************/\r\n");
/* 第五步:列表末尾添加列表项2 */
printf("\r\n/****************第五步:列表末尾添加列表项2****************/\r\n");
vListInsertEnd((List_t* )&TestList, /* 列表 */
(ListItem_t* )&ListItem2); /* 列表项 */
printf("\r\n项目\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)
{
vTaskDelay(10);
}
}
3.2修改Task2的任务函数内容
Task2实现5S间隔LED0亮灭。
void task2(void *pvParameters)
{
while(1)
{
LED0_TOGGLE();
vTaskDelay(5000);
}
}
四、实验现象
实验现象如下所示。可以看到在第三步中,列表项123按照列表项值的从小到大顺序排列。