IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> stm32F103移植FreeRTOS V10.2.1打印任务堆栈信息和任务运行时间统计 -> 正文阅读

[嵌入式]stm32F103移植FreeRTOS V10.2.1打印任务堆栈信息和任务运行时间统计

? ? ? ? 本篇内容进行分享的是FreeRTOS中打印任务堆栈信息和任务运行时间的统计,在FreeRTOS中我们可以通过函数vTaskList()?统计每个任务的堆栈信息,通过函数vTaskGetRunTimeStats()来统计每个任务使用 CPU 的时间,以及所使用的时间占总时间的比例。在调试代码的时候我们可以根据这个时间使用值来分析哪个任务的 CPU 占用率高,然后合理的分配或优化任务。

?一、预备知识

? ? ? ?FreeRTOS调试时要想打印任务堆栈信息和任务运行时间统计,需要熟悉FreeRTOS提供的2个函数vTaskGetRunTimeStats()函数和vTaskList()函数以及配置一个高精度而且比滴答中断(1ms)快很多的硬件定时器用于任务运行时间统计。

1、vTaskGetRunTimeStats()函数

? ? ? ?vTaskGetRunTimeStats()函数是FreeRTOS中自带的一个用来统计各个Task占用CPU时间的函数,使用这个功能我们可以清晰地看到每个任务所占用时间、百分比以及CPU整体的占用率,任务的运行时间信息提供了每个任务获取到的CPU使用权总的时间。vTaskGetRunTimeStats()函数会将统计到的信息填充到另一个列表里,这样我们就可以随时知道所有任务抢占CPU的结果,便于我们合理规划安排这些任务。

? ? ? ?函数原型为:

void vTaskGetRunTimeStats( char *pcWriteBuffer )

? ? ? ?虽然说vTaskGetRunTimeStats()函数是FreeRTOS中已经给出的,但是我们无法直接使用。使用这个函数之前我们需要使能以下这4个宏, 需要将以下4个宏设置为1。??

  • configGENERATE_RUN_TIME_STATS
  • configUSE_STATS_FORMATTING_FUNCTIONS
  • configSUPPORT_DYNAMIC_ALLOCATION
  • configUSE_TRACE_FACILITY

? ? ? ? ?下面是FreeRTOS提供的源码:

#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )

	void vTaskGetRunTimeStats( char *pcWriteBuffer )
	{
	TaskStatus_t *pxTaskStatusArray;
	UBaseType_t uxArraySize, x;
	uint32_t ulTotalTime, ulStatsAsPercentage;

		#if( configUSE_TRACE_FACILITY != 1 )
		{
			#error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
		}
		#endif

? ? ? ? ? 下图是截屏。

?? ? ? ? ?其中FreeRTOS已经默认将宏configSUPPORT_DYNAMIC_ALLOCATION设置为1,参见FreeRTOS提供的源码:?

? ? ? ? 我们必须在FreeRTOSConfig.h文件中添加代码,将另外3个宏设置为1:

? ? ? ? (1)、configUSE_TRACE_FACILITY设置为1。

? ? ? ? (2)、configUSE_STATS_FORMATTING_FUNCTIONS设置为1。

? ? ? ? (3)、configGENERATE_RUN_TIME_STATS设置为1。

? ? ?启用上面这3个宏之后我们还必须要定义下面2个宏:

? ? ? ?portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()

  • portGET_RUN_TIME_COUNTER_VALUE()

?? ? ? ?第一个宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS():配置一个高精度定时器/计数器提供时基,这个时基的分辨率一定要比FreeRTOS的系统时钟(滴答时钟)高,一般高出10~20倍。第二个宏portGET_RUN_TIME_COUNTER_VALUE():读取时基的时间值。

2、vTaskList()函数

? ? ? ? vTaskList()函数是FreeRTOS中自带的一个用来获取任务信息的函数,该函数会创建一个列表,列表中包含任务名称,任务状态信息,任务优先级,剩余堆栈以及任务编号的信息。

? ? ? ? 函数原型为:

void vTaskList( char * pcWriteBuffer )

? ? ? ?虽然说vTaskList()函数是FreeRTOS中已经给出的,但是我们无法直接使用。使用这个函数之前我们需要使能以下这2个宏, 需要将以下2个宏设置为1。

  1. configUSE_TRACE_FACILITY
  2. configUSE_STATS_FORMATTING_FUNCTIONS

? ? ? ?下面是FreeRTOS提供的源码:

#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )

	void vTaskList( char * pcWriteBuffer )
	{
	TaskStatus_t *pxTaskStatusArray;
	UBaseType_t uxArraySize, x;
	char cStatus;

?? ? ? ?下面是截屏。

? ? ? ? 我们必须在FreeRTOSConfig.h文件中添加代码,将2个宏设置为1:? ? ? ??

? ? ? ? (1)、configUSE_TRACE_FACILITY设置为1。?

? ? ? ? (2)、configUSE_STATS_FORMATTING_FUNCTIONS设置为1。

3、配置一个硬件定时器用于任务运行时间统计

? ? ? ?? 我们已经知道了FreeRTOS是有一个系统时钟(滴答时钟)的,但是这个系统时钟的时基是以1ms(个人配置)为周期的,对于一些耗时小于1ms的任务是不能很好地统计的,所以我们还需要额外提供一个更加精确的时基,才能精确的统计任务运行时间,我们一般将这个更加精准的时基配置成系统时钟(滴答时钟)的20-30倍

? ? ? ?? 在单片机中利用硬件定时器TIM2中断可以很容易提供一个固定周期的更加精准的时基,因此我们需要配置硬件定时器TIM2产生50us的时钟脉冲,这样可以满足我们的需要,可以进行任务运行时间统计。

?二、FreeRTOSConfig.h文件配置

1、FreeRTOSConfig.h文件修改宏configUSE_TRACE_FACILITY

?? ? ? ?? FreeRTOSConfig.h文件默认设置为0,我们只需要将其修改为1即可。

//#define configUSE_TRACE_FACILITY	0			//2022.10.27删除
#define configUSE_TRACE_FACILITY	1			//2022.10.27新添加	//为1,启用可视化跟踪调试

??? ? ? ?? FreeRTOSConfig.h文件配置宏configUSE_TRACE_FACILITY为1后的截图参见下图:

?2、FreeRTOSConfig.h文件添加宏configGENERATE_RUN_TIME_STATS

??? ? ? ?? FreeRTOSConfig.h文件没有提供宏configGENERATE_RUN_TIME_STATS,我们需要手动添加,将configGENERATE_RUN_TIME_STATS设置为1。代码如下:

#define configGENERATE_RUN_TIME_STATS                1	

?3、FreeRTOSConfig.h文件添加宏configUSE_STATS_FORMATTING_FUNCTIONS

??? ? ? ?? FreeRTOSConfig.h文件没有提供宏configUSE_STATS_FORMATTING_FUNCTIONS,我们需要手动添加,将configUSE_STATS_FORMATTING_FUNCTIONS设置为1。代码如下:

#define configUSE_STATS_FORMATTING_FUNCTIONS         1

4、FreeRTOSConfig.h文件添加1个32位的计数器FreeRTOSRunTimeTicks外部声明

??? ? ? ?? FreeRTOSConfig.h文件没有提供32位的计数器FreeRTOSRunTimeTicks,我们需要手动添加,将下面6行拷贝到FreeRTOSConfig.h文件。这样就声明了一个32位计数器的外部声明。

? ? ? ? ? ?说明:32位的计数器FreeRTOSRunTimeTicks用于任务运行时间统计。

? ? ? ? ? ?警告:在FreeRTOSConfig.h文件你进行了外部声明,需要在.C文件中单独定义这个32位计数器FreeRTOSRunTimeTicks。


/* Ensure stdint is only used by the compiler, and not the assembler. *///2022.10.27新添加
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)		//2022.10.27新添加
	#include <stdint.h>													//2022.10.27新添加
	extern volatile uint32_t FreeRTOSRunTimeTicks;						//2022.10.27新添加
#endif																	//2022.10.27新添加

5、FreeRTOSConfig.h添加宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS

??? ? ? ?? FreeRTOSConfig.h文件没有提供宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS,我们需要手动添加,将下面2行拷贝到FreeRTOSConfig.h文件。

? ? ? ? ? ?说明:宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()用于任务运行时间统计。

? ? ? ? ? ?警告:你仅仅声明了宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),以及该宏对应的函数ConfigureTimeForRunTimeStats(void),你需要在.C文件中单独定义这个宏以及实现这个宏ConfigureTimeForRunTimeStats(void)。

void ConfigureTimeForRunTimeStats(void);
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     ConfigureTimeForRunTimeStats()

6、FreeRTOSConfig.h文件添加宏portGET_RUN_TIME_COUNTER_VALUE

??? ? ? ?? FreeRTOSConfig.h文件没有提供宏portGET_RUN_TIME_COUNTER_VALUE(),我们需要手动添加,将下面2行拷贝到FreeRTOSConfig.h文件。

??? ? ? ?? 宏portGET_RUN_TIME_COUNTER_VALUE()用于任务运行时间统计。

??? ? ? ?? 说明:宏portGET_RUN_TIME_COUNTER_VALUE()其实就对应我们前面定义的32位计数器FreeRTOSRunTimeTicks???????。

#define portGET_RUN_TIME_COUNTER_VALUE()             FreeRTOSRunTimeTicks

7、完整的FreeRTOSConfig.h文件文件?

??? ? ? ?? 下面是添加完所有的宏,完整的FreeRTOSConfig.h文件文件。

/*
 * FreeRTOS Kernel V10.2.1
 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * http://www.FreeRTOS.org
 * http://aws.amazon.com/freertos
 *
 * 1 tab == 4 spaces!
 */

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. 
 *
 * See http://www.freertos.org/a00110.html
 *----------------------------------------------------------*/

#define configUSE_PREEMPTION		1
#define configUSE_IDLE_HOOK			0
#define configUSE_TICK_HOOK			0
#define configCPU_CLOCK_HZ			( ( unsigned long ) 72000000 )	
#define configTICK_RATE_HZ			( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES		( 5 )
#define configMINIMAL_STACK_SIZE	( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 17 * 1024 ) )
#define configMAX_TASK_NAME_LEN		( 16 )

//#define configUSE_TRACE_FACILITY	0			//2022.10.27删除
#define configUSE_TRACE_FACILITY	1			//2022.10.27新添加	//为1,启用可视化跟踪调试

#define configUSE_16_BIT_TICKS		0
#define configIDLE_SHOULD_YIELD		1

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 		0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet		1
#define INCLUDE_uxTaskPriorityGet		1
#define INCLUDE_vTaskDelete				1
#define INCLUDE_vTaskCleanUpResources	0
#define INCLUDE_vTaskSuspend			1
#define INCLUDE_vTaskDelayUntil			1
#define INCLUDE_vTaskDelay				1

/* This is the raw value as per the Cortex-M3 NVIC.  Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 		255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	191 /* equivalent to 0xb0, or priority 11. */


/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15.  This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting.  Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY	15



#define xPortPendSVHandler  	PendSV_Handler
#define xPortSysTickHandler 	SysTick_Handler
#define vPortSVCHandler    		SVC_Handler



#define configCHECK_FOR_STACK_OVERFLOW  2		//2022.10.26新添加宏定义检测堆栈溢出



/* Ensure stdint is only used by the compiler, and not the assembler. *///2022.10.27新添加
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)		//2022.10.27新添加
	#include <stdint.h>													//2022.10.27新添加
	extern volatile uint32_t FreeRTOSRunTimeTicks;						//2022.10.27新添加
#endif																	//2022.10.27新添加

void ConfigureTimeForRunTimeStats(void);								//2022.10.27新添加


/* Run time and task stats gathering related definitions. */			//2022.10.27新添加
#define configGENERATE_RUN_TIME_STATS                1					//2022.10.27新添加	//为1时,启用运行时间统计功能(至少达到嘀嗒中断的10-20倍,才能进行统计功能)
#define configUSE_STATS_FORMATTING_FUNCTIONS         1					//2022.10.27新添加	//为1时,启用运行时间统计功能(至少达到嘀嗒中断的10-20倍,才能进行统计功能)
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     ConfigureTimeForRunTimeStats()	//2022.10.27新添加//TIM2定时器提供时间统计的时基,频率为20K,即周期为50us,是滴答中断(1ms)的20倍
#define portGET_RUN_TIME_COUNTER_VALUE()             FreeRTOSRunTimeTicks			//2022.10.27新添加//获取时间统计时间值



#endif /* FREERTOS_CONFIG_H */

三、精准时基配置

? ? ? ? 配置一个硬件定时器TIM2用于任务运行时间统计,我们需要配置硬件定时器TIM2产生50us的时钟脉冲。

? ? ? ? 警告:如果硬件定时器周期定义的太长的话(例如:配置硬件定时器周期为1ms),任务运行时间统计就会不准(因为有些任务运行时间太短,远远低于1ms),因此硬件定时器周期为滴答中断(1ms)的10倍-20倍比较合适(这里我们配置周期为50us)。

1、定义一个32位的计数器FreeRTOSRunTimeTicks

volatile uint32_t FreeRTOSRunTimeTicks = 0UL;

2、定义硬件定时器TIM2周期为50us

#define  timerINTERRUPT_FREQUENCY	20000

3、编写宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()对应的函数

? ? ? ? 在FreeRTOSConfig.h文件定义了宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS以及对应的函数ConfigureTimeForRunTimeStats(void),参见下图:

? ? ? ? 因此我们在.C中必须实现ConfigureTimeForRunTimeStats()函数,函数代码参见下面。

//初始化TIM2为FreeRTOS的时间提供基础时基
void ConfigureTimeForRunTimeStats(void)
{
	FreeRTOSRunTimeTicks = 0UL;	
	TIM2_Configuration();
}

? ? ? ? 函数 ConfigureTimeForRunTimeStats()其实就是初始化定时器,因为时间统计功能需要用户提供一个高精度的时钟,这里使用定时器2。这个时钟的精度要比FreeRTOS的系统时钟高,大约 10~20 倍即可。举例来讲:FreeRTOS 系统时钟我们配置的是 1000HZ,周期 1ms,这里我们将定时器 2的中断频率配置为 20KHZ,周期 50us,刚好是系统时钟频率的 20 倍。

4、编写定时器TIM2初始化程序

//TIM2定时器配置为50us,达到嘀嗒中断(1ms)的20倍,才能满足运行时间统计的需要
void TIM2_Configuration(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	uint16_t usPeriod;
	uint16_t usPrescaler;
	uint32_t uiTIMxCLK;
	
	
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
    TIM_DeInit(TIM2);
 	TIM_InternalClockConfig(TIM2);

	uiTIMxCLK = SystemCoreClock;	// SystemCoreClock = 72000000
	usPrescaler = 100 - 1;					/* 分频比 = 100 */
	usPeriod =  (uiTIMxCLK / 100) / timerINTERRUPT_FREQUENCY  - 1;		/* 自动重装的值 */
	
	TIM_TimeBaseStructure.TIM_Period = usPeriod;
	TIM_TimeBaseStructure.TIM_Prescaler = usPrescaler;		
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
	TIM_ARRPreloadConfig(TIM2, ENABLE);
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	TIM_Cmd(TIM2, ENABLE);
}

5、编写定时器TIM2中断服务程序

? ? ? ?FreeRTOSRunTimeTicks 是个全局变量,用来为时间统计功能提供时间,在定时器 2 的中断服务函数中进行更新。 定时器TIM2中断服务程序只干一件事情,就是不停的累加前面定义的32位计数器FreeRTOSRunTimeTicks。

void TIM2_IRQHandler(void)
{	
	if (TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);			
		FreeRTOSRunTimeTicks++;	
	}
}

6、给定时器TIM2分配硬件优先级分组和抢占优先级


void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure; 
	

	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//嵌套优先级分组为 4
	
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//不接受FreeRTOS控制
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
}

四、主程序

#include "FreeRTOS.h"
#include "task.h"


static TaskHandle_t xHandleTaskStart = NULL;
static TaskHandle_t xHandleTask1 = NULL;
static TaskHandle_t xHandleTask2 = NULL;
static TaskHandle_t xHandleTaskRunTimeStats = NULL; 


static void vTaskStart(void *pvParameters);
static void vTask1(void *pvParameters);
static void vTask2(void *pvParameters);
static void vTaskRunTimeStats(void *pvParameters);
static void AppTaskCreate (void); 



char PRINT_RunTimeInfo[1024];



void vTask1(void *pvParameters)
{	
	uint16_t i = 0;
	
    while(1)
    {		
		i = 0;
		while (i < 32000)
		{
			i = i + 1;
			__NOP();
			__NOP();
			__NOP();
			__NOP();
			__NOP();			
		}

		GPIO_LED1_ON();
		vTaskDelay(250);
		GPIO_LED1_OFF();
		vTaskDelay(250);	
    }
}



void vTask2(void *pvParameters)
{	
	uint16_t i = 0;
	
    while(1)
    {		
		i = 0;
		while (i < 32000)
		{
			i = i + 1;
			__NOP();
			__NOP();
			__NOP();
			__NOP();
			__NOP();			
		}

		GPIO_LED2_ON();
		vTaskDelay(250);
		GPIO_LED2_OFF();
		vTaskDelay(250);	
    }
}



static void vTaskRunTimeStats(void *pvParameters)
{	
    while(1)
    {				
		printf("=================================================\r\n");
		printf("任务名                       任务状态 优先级   剩余栈 任务序号\r\n");
		vTaskList((char *)&PRINT_RunTimeInfo);
		printf("%s\r\n", PRINT_RunTimeInfo);				
		printf("任务名                     运行计数              使用率\r\n");
		vTaskGetRunTimeStats((char *)&PRINT_RunTimeInfo);
		printf("%s\r\n", PRINT_RunTimeInfo);
		vTaskDelay(1000);
    }//while(1)
}


static void AppTaskCreate (void)
{

	xTaskCreate( vTaskStart,     			// 任务函数  
                 "vTaskStart",   			// 任务名    
                 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 4, 						// 任务优先级
                 &xHandleTaskStart);  		// 任务句柄 	

}



static void vTaskStart(void *pvParameters)
{
	
	taskENTER_CRITICAL(); 					//进入临界区

	
	xTaskCreate( vTask1,     				// 任务函数  
                 "vTask1",   				// 任务名    
                 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 3, 						// 任务优先级
                 &xHandleTask1);   			// 任务句柄  


	xTaskCreate( vTask2,     				// 任务函数  
                 "vTask2",   				// 任务名    
                 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 2, 						// 任务优先级
                 &xHandleTask2);   			// 任务句柄  


	xTaskCreate( vTaskRunTimeStats,     	// 任务函数  
                 "vTaskRunTimeStats",  		// 任务名    
                 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 1, 						// 任务优先级
                 &xHandleTaskRunTimeStats); // 任务句柄  	
	
	vTaskDelete(xHandleTaskStart); 			//删除开始任务
	taskEXIT_CRITICAL(); 					//退出临界区
}



int main(void)
{
	__set_PRIMASK(1); 	
	bsp_InitPrint();        //重定向printf函数到USART3串口
	GPIO_Configuration();	
	NVIC_Configuration();
	
	//创建任务
	AppTaskCreate();
	//启动调度器
	vTaskStartScheduler();
    while (1);	
}

五、实测结果

六、后记

? ? ? ?刚刚测试时,我把任务Task1和任务Task2编写成如下形式:

void vTask1(void *pvParameters)
{		
    while(1)
    {		
		GPIO_LED1_ON();
		vTaskDelay(250);
		GPIO_LED1_OFF();
		vTaskDelay(250);	
    }
}



void vTask2(void *pvParameters)
{		
    while(1)
    {		
		GPIO_LED2_ON();
		vTaskDelay(250);
		GPIO_LED2_OFF();
		vTaskDelay(250);	
    }
}

? ? ? ?结果测试时发现统计的任务Task1和任务Task2的运行时间总是为0,最后想了想,原因是这2个任务没有执行代码,vTaskGetRunTimeStats()函数统计不到,因此就在这2个任务中添加了如下的垃圾代码,vTaskGetRunTimeStats()函数立即就可以统计到任务Task1和任务Task2的运行时间啦!

		i = 0;
		while (i < 32000)
		{
			i = i + 1;
			__NOP();
			__NOP();
			__NOP();
			__NOP();
			__NOP();			
		}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:14:20  更:2022-10-31 12:18:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 14:06:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码