能具体讲解吗,你给的这两个方案都不能实际解决问题
时间: 2024-02-26 16:58:46 浏览: 21
好的,我来具体讲解一下。
对于第一个问题,可以将时间戳从32bit改为64bit。由于64bit的整型范围很大,可以满足大部分嵌入式应用的需求。如果采用滚动计数的方式,可以在每次溢出时将时间戳重新归零,并且在一个变量中记录溢出的次数。例如:
```c
#define MAX_UINT32 0xFFFFFFFFUL
#define MAX_UINT64 0xFFFFFFFFFFFFFFFFULL
uint64_t ullTickCount = 0;
uint32_t ulOverflowCount = 0;
void vTaskIncrementTick(void)
{
ullTickCount++;
if (ullTickCount >= MAX_UINT32) {
ullTickCount = 0;
ulOverflowCount++;
}
}
uint64_t ullGetTickCount(void)
{
uint64_t ullTickCountCopy;
uint32_t ulTickCount;
do {
ulTickCount = ulSysTickCounter;
ullTickCountCopy = ullTickCount;
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)
ullTickCountCopy += ulOverflowCount << 32UL;
} while (ulTickCount != ulSysTickCounter);
return ullTickCountCopy;
}
```
对于第二个问题,可以使用FreeRTOS提供的时间片窗口机制。这个机制可以让用户定义一个时间窗口,在时间窗口内只统计任务的运行时间。具体操作方式如下:
1. 在FreeRTOSConfig.h文件中定义configGENERATE_RUN_TIME_STATS为1,并定义configUSE_STATS_FORMATTING_FUNCTIONS为1。
2. 在vTaskGetRunTimeStats函数中使用vTaskSetTimeOutState函数开启时间片窗口,在窗口内只统计任务的运行时间。例如:
```c
void vTaskGetRunTimeStats(char *pcWriteBuffer)
{
const char *pcHeader = "Task Abs Time % Time\r\n*************************************************\r\n";
const uint32_t ulHeaderLength = strlen(pcHeader);
TaskStatus_t *pxTaskStatusArray;
volatile uint32_t ulTotalRunTime, ulStatsAsPercentage;
uint32_t ulStatsCount, x;
uint64_t ullTickCount;
float fStatsAsFloat;
TimeOut_t xTimeOut;
/* Make sure the write buffer does not contain a string. */
*pcWriteBuffer = 0x00;
/* Allocate a TaskStatus_t structure for each task. An array could be
allocated statically at compile time. */
pxTaskStatusArray = pvPortMalloc(sizeof(TaskStatus_t) * uxTaskGetNumberOfTasks());
if (pxTaskStatusArray != NULL) {
/* Generate raw status information about each task. */
ulStatsCount = uxTaskGetSystemState(pxTaskStatusArray, uxTaskGetNumberOfTasks(), &ulTotalRunTime);
/* Avoid divide by zero errors. */
if (ulTotalRunTime > 0UL) {
/* Generate readable ASCII output from the raw status information. */
memcpy(pcWriteBuffer, pcHeader, ulHeaderLength);
pcWriteBuffer += ulHeaderLength;
/* For each populated position in the pxTaskStatusArray array,
format the raw data as human readable ASCII data. */
for (x = 0; x < ulStatsCount; x++) {
/* What percentage of the total run time has the task used?
This will always be rounded down to the nearest integer.
ulTotalRunTimeDiv100 has already been divided by 100. */
ulStatsAsPercentage = pxTaskStatusArray[x].ulRunTimeCounter / ulTotalRunTimeDiv100;
/* The pxTaskStatusArray[x].ulRunTimeCounter value is a proportion of the total
run time, so xTaskGetTickCount() is multiplied by the same proportion to
obtain the time spent in the task since the total run time counter was
last reset. */
ullTickCount = ullGetTickCount();
vTaskSetTimeOutState(&xTimeOut);
vTaskDelayUntil(&xTimeOut, xTimeOut.xOverflowCount + ulStatsAsPercentage);
fStatsAsFloat = ((float)pxTaskStatusArray[x].ulRunTimeCounter) / ulTotalRunTime;
fStatsAsFloat *= (float)100.0;
sprintf(pcWriteBuffer, "%-20s %10u %3u%%\r\n", pxTaskStatusArray[x].pcTaskName, pxTaskStatusArray[x].ulRunTimeCounter, (unsigned int)fStatsAsFloat);
pcWriteBuffer += strlen(pcWriteBuffer);
}
}
/* The array is no longer needed, free the memory it consumes. */
vPortFree(pxTaskStatusArray);
}
}
```
在上述代码中,vTaskSetTimeOutState函数用于开启时间片窗口,xTimeOut.xOverflowCount表示当前时间片窗口的起始时间戳,ulStatsAsPercentage表示以当前任务的运行时间占总运行时间的百分比作为时间片窗口的大小。这样,在时间片窗口内只会统计任务的运行时间,从而避免了长时间运行空闲任务所带来的百分比信息不清晰的问题。