FreeRTOS Getting Started Tutorial (Task Status)


Preface

This article will explain the task status in FreeRTOS. There are many statuses in FreeRTOS tasks. Understanding these statuses of tasks will help us understand how tasks run and stop.

1. Simple experiment

Before doing this, let's do an experiment to see how the task runs:
Code:

The following code first defines three flag bits, which mark which task is running.

static int Task1Flag = 0;
static int Task2Flag = 0;
static int Task3Flag = 0;

//任务执行函数
void Task1(void * param)
{
    
    
	static int i = 0;
	while (1)
	{
    
    
		Task1Flag = 1;
		Task2Flag = 0;
		Task3Flag = 0;
	}
}

//任务执行函数
void Task2(void * param)
{
    
    
	while (1)
	{
    
    
		Task1Flag = 0;
		Task2Flag = 1;
		Task3Flag = 0;		
	}
}

//任务执行函数
void Task3(void * param)
{
    
    
	while (1)
	{
    
    
		Task1Flag = 0;
		Task2Flag = 0;
		Task3Flag = 1;		
	}
}

Open the simulated serial port in keil:
Insert image description here

Open the logic analyzer in keil:
Insert image description here
Add the three defined variables to the logic analyzer:
Insert image description here
Set the status to bit:
Insert image description here
After setting, run the code at full speed:
We can observe that these three tasks are not executed at the same time. , but are executed separately, but the execution time is short and we cannot tell who is executing it.
Insert image description here
By observing the execution time of each task, we can know that the running time of each task is about 1ms. What is the reason for this?

There is a Tick interrupt in FreeRTOS. Whenever an interrupt occurs, it will be judged whether task switching is required. So how many ms does this Tick interrupt occur?

We can find the answer in the FreeRTOSConfig file:
Insert image description here
configTICK_RATE_HZ specifies the frequency of the kernel clock beat in Hertz (Hz).

In FreeRTOS, the kernel clock tick is a time standard that is used to measure the time of task run times, wait times, timers, and other functions. The frequency of the kernel clock beat can be set through configTICK_RATE_HZ. Its default value is 1000, which means 1000 clock beats per second, that is, the clock beat period is 1 millisecond.

Another question is why task 3 is executed first?
You can see such a function inside the task creation function. This function will add the created task to the ready linked list. The task created later will be at the front of the linked list, so the task created later will be taken out and executed first.
Insert image description here

2. Explanation of the concept of task status

Here we use a task conversion picture from Baiwen.com to explain:
Insert image description here
In FreeRTOS, each task has a status, which represents the current task situation. FreeRTOS uses some specific macro definitions to represent different task states. These macro definitions include:

eRunning: Indicates that the task is running.

eReady: Indicates that the task is in a ready state, waiting for the scheduler to schedule it for execution.

eBlocked: Indicates that the task is in a blocked state, that is, waiting for certain events to occur, such as waiting for a semaphore, message queue, timer timeout, etc.

eSuspended: Indicates that the task is in a suspended state, that is, the task has been suspended and does not participate in scheduling, but its status and resources are retained and can be resumed when needed.

eDeleted: Indicates that the task has been deleted and the corresponding control block and stack space have been released.

Transitions between task states are automatically managed by the FreeRTOS kernel. Tasks often change status under the following circumstances:

When a task is created, the task status changes from "Not Started" to "Ready".

The scheduler picks the task based on its priority and changes its status to "Running".

When a task waits for an event (such as a semaphore), the task status becomes "Blocked".

The task status may change to "Pending" while the task is waiting for other tasks to release resources.

When a task calls the delete function to delete itself, the task status changes to "Deleted".

3. vTaskDelay and vTaskDelayUntil

1.vTaskDelay

The vTaskDelay function is used to pause the current task for a period of time before continuing execution. Its parameter is an integer, indicating the number of system ticks to be delayed. For example, in the default configuration, the kernel beat cycle is 1 millisecond, so vTaskDelay(100) suspends the current task for 100 milliseconds.

需要注意的是,vTaskDelay会引起任务阻塞,同时该延迟时间不是绝对准确的。在等待期间FreeRTOS会尝试进行其他任务的调度,因此实际的延迟时间可能会比指定的时间长。

Code example:

void Task1(void * param)
{
    
    
	static int i = 0;
	while (1)
	{
    
    
		printf("Task1\r\n");
		vTaskDelay(1000);
	}
}

//任务执行函数
void Task2(void * param)
{
    
    
	while (1)
	{
    
    
		printf("Task2\r\n");
		vTaskDelay(2000);
	}
}

//任务执行函数
void Task3(void * param)
{
    
    
	while (1)
	{
    
    
		printf("Task3\r\n");
		vTaskDelay(3000);
	}
}

Observe the printing results of the serial port:
Insert image description here

2.vTaskDelayUntil

vTaskDelayUntil is a precise timing function that makes the task wait until a specific point in time before becoming ready again.

When calling vTaskDelayUntil, you need to provide a timestamp (represented by type TickType_t), and the task will sleep until the system clock reaches or exceeds the timestamp.

This allows tasks to be executed at precise time intervals, making it ideal for applications with high real-time requirements.

// 定义一个任务,该任务会每隔1秒输出一次消息
void Task1(void* pvParameters)
{
    
    
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = pdMS_TO_TICKS(1000); // 1秒的时间间隔

    // 获取当前时间作为初始时间
    xLastWakeTime = xTaskGetTickCount();

    while (1)
    {
    
    
        // 执行任务1的操作,例如输出消息
        printf("Task1 is running...\n");

        // 等待到达下一个时间间隔
        vTaskDelayUntil(&xLastWakeTime, xFrequency);
    }
}

int main(void)
{
    
    
    // 初始化FreeRTOS内核和硬件

    // 创建任务1
    xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 启动调度器
    vTaskStartScheduler();

    // 此处不会执行,因为调度器会接管控制权
    return 0;
}

3.The difference between vTaskDelay and vTaskDelayUntil

The vTaskDelay function and the vTaskDelayUntil function are both used to implement time delays for tasks in FreeRTOS, but they do so in different ways.

The vTaskDelay function works by passing a relative delay number of ticks. The task blocks for the specified number of ticks and then continues execution. This means that the delay time of vTaskDelay is relative to the execution time of the current task, and the actual delay time may be affected by task switching and system load. Therefore, the exact delay time cannot be guaranteed and there may be certain errors.

The vTaskDelayUntil function works by passing an absolute point in time expressed in ticks. The task waits until the current time reaches or exceeds the passed absolute time point, then continues execution. This means that vTaskDelayUntil provides more precise delay control and can achieve accurate timing tasks. You can calculate the next execution time point as needed and pass it to the vTaskDelayUntil function, and the task will block at that time point, ensuring accurate delay time.

vTaskDelay用于相对延迟,而vTaskDelayUntil用于绝对时间点延迟,使得在实现定时任务时更加方便和精确。

Summarize

This article will explain it here.

Guess you like

Origin blog.csdn.net/m0_49476241/article/details/130451344