Real-time operating system Freertos open pit study notes: (3): task suspension and recovery, interrupt management

Tip: After the article is written, the table of contents can be automatically generated. How to generate it can refer to the help document on the right


Preface

insert image description here
This section includes these four contents. Mainly master 1 and 2, and 3 is an elective content. If you want to understand it in depth, you can study it.

1. API functions for task suspension and recovery

1. Specific function description

insert image description here

①vTaskSuspend() task suspension (pause) function

vTaskSuspend() is a function in FreeRTOS that is used to suspend the execution of tasks. When this function is called, the task enters a suspended state and is not eligible for execution until resumed.

The syntax of this function is as follows:

void vTaskSuspend(TaskHandle_t xTaskToSuspend);

Here, xTaskToSuspend is the handle of the task to be suspended. This handle is obtained when creating a task using the xTaskCreate() or xTaskCreateStatic() function.

When vTaskSuspend() is called, the task is immediately removed from the list of tasks ready to run. The task remains in a suspended state until it is resumed using the vTaskResume() function.

It should be noted that vTaskSuspend() should not be called from an interrupt service routine (ISR). Instead, use the vTaskSuspendFromISR() function to suspend tasks from the ISR.
insert image description here

②vTaskResume() task recovery function

vTaskResume() is a function in FreeRTOS used to resume the execution of suspended tasks. When this function is called, the task transitions from the suspended state to the ready state, making it eligible for execution.

The syntax of this function is as follows:

BaseType_t vTaskResume(TaskHandle_t xTaskToResume);

Here, xTaskToResume is the handle of the task to be resumed. This handle is obtained when creating a task using the xTaskCreate() or xTaskCreateStatic() function.

When vTaskResume() is called, the task is added back to the list of tasks ready to run. If the resumed task has a higher priority than the currently running task, a context switch may occur, allowing the resumed task to begin execution immediately.

It should be noted that vTaskResume() should not be called from an interrupt service routine (ISR). Instead, use the vTaskResumeFromISR() function to resume the task from the ISR.

vTaskResume() is useful in scenarios where a previously suspended task needs to be resumed, such as after a specific event or resource becomes available. Once the task is resumed, it resumes execution from where it was paused.
insert image description here

③xTaskResumeFromISR() resumes the suspended task during the interrupt

xTaskResumeFromISR() is a function in FreeRTOS that is used to resume the execution of a suspended task from an interrupt service routine (ISR). Unlike the vTaskResume() function, xTaskResumeFromISR() is a function specially designed to resume a task in an ISR.

The syntax of this function is as follows:

BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume);

Here, xTaskToResume is the handle of the task to be resumed. This handle is obtained when creating a task using the xTaskCreate() or xTaskCreateStatic() function.

When xTaskResumeFromISR() is called, the task transitions from the suspended state to the ready state, making it eligible for execution. Unlike vTaskResume(), xTaskResumeFromISR() defers the task's resume operation until a later context switch.

When calling xTaskResumeFromISR() in an ISR, you need to call an appropriate API to request a context switch before the ISR returns. This can be done using the xHigherPriorityTaskWoken parameter, which is set to pdTRUE when calling the API.

xTaskResumeFromISR() is useful in scenarios where a previously suspended task needs to be resumed from an ISR, such as resuming the execution of a task after an interrupt handler has completed.

It should be noted that since xTaskResumeFromISR() is called from an ISR, it has some special restrictions and requirements, including support for interrupt nesting and the use of a special context switch mechanism.
insert image description here

2. What is the difference between the recovery task function and the interrupt recovery task function?

There are some differences in functions and usage between the recovery task function (vTaskResume) and the interrupt recovery task function (xTaskResumeFromISR).

1. Calling method: The recovery task function can be called from the task context, while the interrupt recovery task function can only be called from the interrupt service routine (ISR).
2. Context switching: The resume task function (vTaskResume) can immediately execute context switching, so that the resumed task can start executing immediately. The interrupt recovery task function (xTaskResumeFromISR) delays the task recovery operation to a later context switch. You need to request the context switch by calling the appropriate API and set the xHigherPriorityTaskWoken parameter to pdTRUE.
3. Interrupt nesting: The interrupt recovery task function (xTaskResumeFromISR) supports interrupt nesting and can correctly resume tasks in multiple interrupt levels. The recovery task function (vTaskResume) does not have support for interrupt nesting and can only be called in the task context.
4. Restrictions and requirements: Since the interrupt recovery task function (xTaskResumeFromISR) is called from the ISR, it has some special restrictions and requirements. For example, interrupt controllers need to be properly configured and handled, as well as using special context switch mechanisms.

In general, the resume task function (vTaskResume) is suitable for resuming suspended tasks from the task context, while the interrupt resume task function (xTaskResumeFromISR) is suitable for resuming suspended tasks from the interrupt service routine.

It means: xTaskResumeFromISR() function needs to be called in the interrupt service routine (ISR). When entering an interrupt and need to resume the suspended task, you can call the xTaskResumeFromISR() function in the interrupt service function.

Before calling the xTaskResumeFromISR() function, you need to ensure that the interrupt controller has been correctly configured and handled, and set the xHigherPriorityTaskWoken parameter to pdTRUE. In this way, a context switch will be requested immediately before the interrupt service function returns, so that the resumed task can start execution in a later context switch.

Note that the xTaskResumeFromISR() function can only be used to resume tasks from interrupt contexts, and cannot be called from normal task contexts. If you need to resume a task from a normal task context, you should use the vTaskResume() function.

The specific interrupt mechanism of freertos will be explained later.

2. Specific routines for task suspension and recovery

1. Experimental purpose

insert image description here

2. Specific code

code show as below:

①Create task code

insert image description here

②LED, key0,1 task code

insert image description here

③key2 enters the interrupt to resume the pending task

insert image description here

3. Internal implementation of task suspension and recovery

insert image description here
insert image description here

4. Interrupt management of freertos

The main contents include:
insert image description here

1. What is an interrupt?

insert image description here
In bare-metal programming, interrupts are a very important concept. I won’t say much here. As shown in the figure, an interrupt request is triggered by certain conditions, and then the CPU stops the current program and enters the interrupt handler for execution. After completion, it returns to the interrupted program to continue execution.
What if an interrupt occurs and a more important interrupt request occurs at the same time, that is, interrupt nesting?
Adopt interrupt priority grouping mechanism.

2. Interrupt priority grouping mechanism

insert image description here
Looking at this interrupt priority register, the high four bits and the low four bits are different, and only the high four bits are used for priority representation. So for the two configuration methods of preemption priority and sub-priority, there are the following configuration methods:
insert image description here
For example, our most commonly used NVIC_PriorityGroup_2, then the preemption priority has two digits, 00, 01, 10, 11, sub- The priority is also two digits.

So for freeetos, how to manage interrupt priority?
insert image description here
It is suggested here that as long as the priority is preempted, NVIC_PriorityGroup_4 is used, so that the preemptive priority occupies all 4 bits.

3. Interrupt related registers

insert image description here
insert image description here
insert image description here
insert image description here
insert image description here

insert image description here
I don’t understand it, I don’t understand it at all, let’s go to the routine to understand it.

4. Interrupt management specific routines

insert image description here
Note: Two timers are created here. Since the priority range of system management is 5-15, if I turn off interrupts, the timer with priority 6 will be turned off, while the timer with priority 4 will not be affected.

(1) First create two basic timers TIM6 and TIM7
insert image description here
(2) Modify the priorities of the two timers to 4 and 6
insert image description here
(3) Implement the function of entering an interrupt every second and printing a string: only during initialization Configure the frequency division factor and counting period so that an interrupt is triggered every 1 second.
insert image description here
insert image description here
The stm32f429 series sets the system clock frequency to 180MHZ, while the clock frequency of TIM6 and TIM7 is 90MHz, so 900000000/10000/9000=1s.

(4) Execute the interrupt-disable function in task 1.
insert image description here
insert image description here
The function of the entire task function is to execute the task once every second, turn off the interrupt when task1_num increases to 5, and then turn on the interrupt after a delay of 5 seconds. When the two timers interrupt and print strings once every second, the interrupt is turned off at 5 seconds. At this time, only the timer with interrupt priority 4 that is not managed by the system can continue to run, and interrupts with priority 5-15 will stop directly. . Then after 5 seconds, the interrupt is turned on, and the two timer interrupts run normally again.

Note: In the if statement here, why can only delay_ms(5000); but not vTaskDelay(5000);?
delay_ms(5000) and vTaskDelay(5000) are two different delay functions.

delay_ms(5000): This is a common delay function used to add a specified millisecond delay in the code. In this function, the program will block until the specified time (5 seconds) elapses before continuing to execute subsequent code. This delay function is often used in bare-metal programming or non-real-time operating systems because it blocks the execution of the task and may cause the task to be unable to respond to other events.

vTaskDelay(5000): This is a delay function provided by FreeRTOS for implementing delay in tasks. In this function, the task will enter the blocking state and give up the CPU time slice to other tasks or interrupt handlers so that the system can continue to perform other tasks. After the specified time (5 seconds), the task will be reawakened and continue to execute subsequent code. This delay function is a commonly used method in real-time operating systems, which can realize time slice rotation and priority scheduling between tasks.

Summary: delay_ms(5000) is a blocking delay function that will block the execution of the task; vTaskDelay(5000) is a non-blocking delay function provided by FreeRTOS. The task will enter the blocking state during the delay period and give up the CPU. Time slices for other tasks . The choice of which delay function to use depends on the specific application scenario and system requirements.

Note again: the priority range of system management can be set.
Look at the BASEPRI register: interrupts whose priority is lower than a certain threshold are masked. When set to 0, no interrupts are turned off. When BASEPRI is set to 0x50, it means that the interrupt priority within 5-15 is masked, and the interrupt priority of 0-4 is executed normally.

5. Summary of interruption management

insert image description here

Guess you like

Origin blog.csdn.net/qq_53092944/article/details/132548691