<FreeRTOS入门第三节>列表介绍和使用 相关API介绍

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

今天学习了FreeRTOS的列表(List),本文只是博主自身理解可能有不足望指正,具体请看正点原子的freeRTOS操作系统文档。第七章列表


一、列表是什么?

列表是FreeRTOS的一个数据结构体,使用之前要打开projdefs.h这个文件第60行的configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES宏
在这里插入图片描述

这个是迷你的列表

/***********************************下面我用英文数值表示每一个结构体成员**************************/
typedef struct xLIST
{
 /* one */   listFIRST_LIST_INTEGRITY_CHECK_VALUE     
 /* tow */   volatile UBaseType_t uxNumberOfItems;
 /* three */   ListItem_t * configLIST_VOLATILE pxIndex; 
 /* four */    MiniListItem_t xListEnd;                 
 /*five */   listSECOND_LIST_INTEGRITY_CHECK_VALUE    
} List_t;
/*
one and five:是用来效准列表的完整性
tow:指列表项的数量
three:指列表索引和用来遍历列表的
four:指列表结束的地址
*/

列表项(一定要区分列表和列表项)
我的理解是:列表是父类,列表项是子类,要先有父类,才能有子类。父类包含子类。

struct xLIST_ITEM
{
 /* one */   listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           
 /* tow */   configLIST_VOLATILE TickType_t xItemValue;         
 /* three */  struct xLIST_ITEM * configLIST_VOLATILE pxNext;     
 /* four */   struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; 
 /* five */   void * pvOwner;                                     
 /* six */   struct xLIST * configLIST_VOLATILE pxContainer;   
 /* seven */   listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE         
};
typedef struct xLIST_ITEM ListItem_t; 
/*
one and seven:是用来效准列表的完整性
tow:指列表项的数据
three:指下一个列表项
four:上一个列表项      //pxNext和pxPrevious查上个父类或者子类的地址
six:指显示父类(该列表)
*/

二、理解列表工作

1.代码模板

代码如下(示例):

List_t List_main; //调用列表的结构体
ListItem_t ListItem1;//调用列表项的结构体

void Task1Function_list(void* param){ //这是在任务一中运行的哈
	vListInitialise(&List_main); //初始化列表
	vListInitialiseItem(&ListItem1);//初始化列表项
	ListItem1.xItemValue=30; //调用列表项结构体成员赋值
	vListInsert(&List_main,&ListItem1);//给列表项添加列表(添加父类)
	for(;;){
		printf("**************** LIST_NAME************************\r\n");
		printf("List->addr:%#x\r\n",(int)&List_main);//输出列表的地址
		printf("List->xListend:%#x\r\n",(int)&List_main.xListEnd);//列表的结束地址
		printf("List->pxIndex:%#x\r\n",(int)&List_main.pxIndex);//列表的索引地址
		printf("Listitem1->addr:%#x\r\n",(int)&ListItem1);//列表项的地址
		printf("**********************************************\r\n");
		printf("**************** LIST_pxPrevious************************\r\n");
		printf("List_main->xTistEnd->pxPrevious:%#x\r\n",(int)&List_main.xListEnd.pxPrevious);//列表的结束地址的上一个列表项
		printf("ListItem->pxPrevious:%#x\r\n",(int)&ListItem1.pxPrevious);//列表项的上一个列表或者列表项
		printf("**************** LIST_pxNext************************\r\n");
		printf("List_main->xTistEnd->pxNext:%#x\r\n",(int)&List_main.xListEnd.pxNext);//列表的结束地址的下一个列表项
		printf("List1Item->pxNext:%#x\r\n",(int)&ListItem1.pxNext);//列表项的下一个列表或者列表项
		printf("**************** LIST_Number************************\r\n");
		printf("List_main->Nuber:%d\r\n",List_main.uxNumberOfItems);//列表的列表项数量
		printf("List1Item->xItemValue:%d\r\n",ListItem1.xItemValue);//列表项的值
		vTaskDelay(30);	//进入阻塞态30ms	
	}

}

效果展示
在这里插入图片描述

2.进一步理解

下图转载于正点原子freeRtos文档第七章->107、108page.
在这里插入图片描述
在这里插入图片描述

/*这个xListNext里面又包含下面三个结构体成员
xListENd->pxNext;  
xListEnd->pxPrevious;
xListEnd->xlteavalue;
*/

这里很好的演示了List列表和ListItem列表项的运行。记住不管有多少个列表项,他们最终都是形成闭环的。List->xListEnd->pxNext=ListItem1;这个意思就是List的xListEnd成员的pxNext成员是ListItem1列表项的地址。pxContainer表示子类的父类(及父类);

3.源码

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "stdio.h"
#ifdef __GNUC__ //printf重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1, (uint8_t*)&ch,1,HAL_MAX_DELAY);
    return ch;
}

TaskHandle_t HandlerTask1;
TaskHandle_t Task_Name4;

BaseType_t xReturn;

List_t List_main;
ListItem_t ListItem1;


void SystemClock_Config(void);
StackType_t xTask3Static[128];
StaticTask_t xTaskTCB;

StackType_t xIdle3Static[128];
StaticTask_t xIdleTCB;
static int task1flag=0;
static int task2flag=0;
static int task3flag=0;
static int task4flag=0;
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize ){
			*ppxIdleTaskTCBBuffer=&xIdleTCB;				
			*ppxIdleTaskStackBuffer=xIdle3Static;
			*pulIdleTaskStackSize=128;
}

void Task1Function( void * param){

	vListInitialise(&List_main);
	vListInitialiseItem(&ListItem1);
	ListItem1.xItemValue=30;
	uint8_t List_buff[20];
	vListInsert(&List_main,&ListItem1);
	for(;;){
		printf("**************** LIST_NAME************************\r\n");
		printf("List->addr:%#x\r\n",(int)&List_main);
		printf("List->xListend:%#x\r\n",(int)&List_main.xListEnd);
		printf("List->pxIndex:%#x\r\n",(int)&List_main.pxIndex);
		printf("Listitem1->addr:%#x\r\n",(int)&ListItem1);
		printf("**********************************************\r\n");
		printf("**************** LIST_pxPrevious************************\r\n");
		printf("List_main->xTistEnd->pxPrevious:%#x\r\n",(int)&List_main.xListEnd.pxPrevious);
		printf("ListItem->pxPrevious:%#x\r\n",(int)&ListItem1.pxPrevious);
		printf("**************** LIST_pxNext************************\r\n");
		printf("List_main->xTistEnd->pxNext:%#x\r\n",(int)&List_main.xListEnd.pxNext);
		printf("List1Item->pxNext:%#x\r\n",(int)&ListItem1.pxNext);
		printf("**************** LIST_Number************************\r\n");
		printf("List_main->Nuber:%d\r\n",List_main.uxNumberOfItems);
		printf("List1Item->xItemValue:%d\r\n",ListItem1.xItemValue);

		vTaskDelay(30);		
	}
}
void Task2Function(void* param){

  for(;;)
  {
		task1flag=0;
		task2flag=1;
		task3flag=0;
		task4flag=0;
	uint8_t buff2[10]="Task2\r\n";
	HAL_UART_Transmit(&huart1,(uint8_t*)buff2,strlen(buff2)*sizeof(char),HAL_MAX_DELAY);
	vTaskDelay(30);
  }
}
void Task3Funtion(void* param){
	TickType_t st_time=xTaskGetTickCount(); 
  int str[]={1,2,4,5,6};
	int j;
	while(1){
		task1flag=0;
		task2flag=0;
		task3flag=1;
		task4flag=0;
		//vTaskDelet();
		uint8_t buff[20]="Task3\r\n";
		for(int i=0;i<j;i++){
			
	  HAL_UART_Transmit(&huart1,(uint8_t*)buff,strlen(buff)*sizeof(char),HAL_MAX_DELAY);		
		}
		j++;
		if(j==5)j=0;
		xTaskDelayUntil(&st_time,30);
		//taskEXIT_CRITICAL();//退出临界点
		//taskENTER_CRITICAL();//进入临界点
	}
	
}

void Task4Funtion(void* param){
	taskENTER_CRITICAL();
	
	task1flag=0;
	task2flag=0;
	task3flag=0;
	task4flag=1;
	xReturn=xTaskCreate(Task1Function,"Task1",128,NULL,2,&HandlerTask1);
	
	xTaskCreate(Task2Function,"Task2",128,NULL,3,NULL);
	
 	xTaskCreateStatic(Task3Funtion,"Task3",128,NULL,3,xTask3Static,&xTaskTCB);
	if(xReturn == pdPASS){
			uint8_t buffS[20]="Task1 Create OK..\r\n";
			HAL_UART_Transmit(&huart1,(uint8_t*)buffS,strlen(buffS)*sizeof(char),HAL_MAX_DELAY);
			
		}
	vTaskDelete(Task_Name4);
	taskEXIT_CRITICAL();
}



int main(void)
{
  
	
	HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
	MX_USART1_UART_Init();
	
	xTaskCreate(Task4Funtion,"Task4",600,NULL,1,&Task_Name4);
	
  vTaskStartScheduler();
	
  while (1)
  {
   
  }
 
}


void SystemClock_Config(void)
{
	
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};


  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

 
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

void Error_Handler(void)
{
 
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)
{

}
#endif /* USE_FULL_ASSERT */

三、相关API结束

/*
	定义结构体具体看list.h文件
*/
List_t List_main;
ListItem_t ListItem1;
/*
	初始化列表
*/
istInitialise(&List_main);
/*
	初始化列表项
*/
vListInitialiseItem(&ListItem1);
/*
	列表项赋值
*/
ListItem1.xItemValue=30;
/*
	向列表添加列表项
*/
vListInsert(&List_main,&ListItem1);

注意上面函数不能放到while(1)和for(;;)里面,不然程序要卡死

		printf("**************** LIST_NAME************************\r\n");
		//注释看最上面的程序模板
		printf("List->addr:%#x\r\n",(int)&List_main);
		printf("List->xListend:%#x\r\n",(int)&List_main.xListEnd);
		printf("List->pxIndex:%#x\r\n",(int)&List_main.pxIndex);
		printf("Listitem1->addr:%#x\r\n",(int)&ListItem1);
		printf("**********************************************\r\n");
		printf("**************** LIST_pxPrevious************************\r\n");
		printf("List_main->xTistEnd->pxPrevious:%#x\r\n",(int)&List_main.xListEnd.pxPrevious);
		printf("ListItem->pxPrevious:%#x\r\n",(int)&ListItem1.pxPrevious);
		printf("**************** LIST_pxNext************************\r\n");
		printf("List_main->xTistEnd->pxNext:%#x\r\n",(int)&List_main.xListEnd.pxNext);
		printf("List1Item->pxNext:%#x\r\n",(int)&ListItem1.pxNext);
		printf("**************** LIST_Number************************\r\n");
		printf("List_main->Nuber:%d\r\n",List_main.uxNumberOfItems);
		printf("List1Item->xItemValue:%d\r\n",ListItem1.xItemValue);

总结

现在是北京时间中午12:52分,下午还有很多时间可以学习任务调度器
博观而约取,厚积而薄发

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单片有机机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值