In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly explains "what are the basic knowledge of multitasking management in FreeRTOS real-time operating system". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn the basics of multitasking management in FreeRTOS real-time operating system.
The core of RTOS system is task management, and FreeRTOS is no exception, and most engineers or students who learn RTOS system are mainly to use the multi-task processing function of RTOS. The first thing that RTOS system must master is the operation of task creation, deletion, suspension and recovery, which shows the importance of task management.
What is a multitasking system?
Recall that we used to use 51, AVR, STM32 single-chip microcomputer bare metal (not using the system) is generally in the main function with while (1) to do a big cycle to complete all the processing, that is, the application is an infinite loop, the loop calls the corresponding functions to complete the required processing. Sometimes we also need to complete some processing in the interruption. Compared with the multitasking system, this is the single-task system, also known as the foreground and background system, with the interrupt service function as the foreground program and the large loop while (1) as the background program.
The real-time performance of the foreground and background systems is poor, and all the tasks (applications) of the foreground and background systems are waiting in line to be executed in turn, no matter how urgent this program is now, you can only wait if it's not your turn! It means that all tasks (applications) have the same priority. But the foreground and backstage system is simple and the resource consumption is less! In a slightly larger embedded application, the front and background system is obviously inadequate, and a multitasking system is needed at this time.
The multitasking system will divide and conquer a big problem (application), divide the big problem into many small problems, gradually solve the small problems, and the big problems will be solved accordingly. These small problems can be dealt with as a small task alone. These small tasks are processed concurrently, note that it is not that many tasks are executed together at the same time, but because the execution time of each task is so short that it looks like many tasks are executed at the same time. Multiple tasks pose a new problem: which task runs first and which task runs later? The thing that does this is called the Task Scheduler in the RTOS system. Different systems have different implementation methods of task scheduler. For example, if FreeRTOS is a preemptive real-time multitasking system, then its task scheduler is also preemptive.
High-priority tasks can interrupt the operation of low-priority tasks and gain the right to use CPU, thus ensuring the operation of those urgent tasks. In this way, we can set a high priority for those tasks that require high real-time performance, such as obstacle detection in autopilot. The basic principle of preemptive multitasking system is to return the right to use CPU to low-priority tasks after the completion of high-priority tasks.
FreeRTOS tasks and collaborations
Applications in FreeRTOS can use either tasks, Co-Routine, or a combination of both. However, tasks and collaborators use different API functions, so data cannot be sent from tasks to collaborators through queues (or semaphores), and vice versa. The collaboration program is prepared for those MCU with few resources, and its overhead is very small, but the FreeRTOS official does not intend to update the collaboration program, so this tutorial only covers tasks.
1. Characteristics of tasks (Task)
A real-time application can be used as a stand-alone task when using RTOS. Each task has its own running environment and does not depend on other tasks in the system or the RTOS scheduler. Only one task can be run at any one point in time, and which task to run is determined by the RTOS scheduler, so the RTOS scheduler repeatedly opens and closes each task. Tasks do not need to know the specific behavior of the RTOS scheduler, and the job of the RTOS scheduler is to ensure that the context (register values, stack contents, etc.) when a task starts execution is the same as the last time the task exited. In order to do this, each task must have a stack and save the context on the stack when the task is switched, so that when the task executes again, the context can be removed from the stack and the task resumes running.
Task characteristics: simple. There are no restrictions on use. Support preemptive support priority each task has a stack, resulting in increased RAM usage. If you use preemption, you must carefully consider the problem of reentry.
two。 Characteristics of Co-routine
Collaborative programming is for those MCU with few resources, but with the rapid development of MCU, the performance is becoming more and more powerful.
It is seldom used in Xiecheng! But FreeRTOS has no plans to remove the collaboration, but FreeRTOS is absolutely
It will not be updated and maintained any more, so we just need to know about it. Conceptually, the process and the task are similar, but
There are the following fundamental differences:
Stack usage: all coprograms use the same stack (if it is a task, each task has its own stack), which consumes less RAM than using tasks.
Scheduler and priority: collaborators use collaborative schedulers, but you can use them in preemptive schedulers.
Macro implementation: co-programs are implemented through macro definitions.
Usage restrictions: a lot of restrictions have been made to reduce the consumption of RAM.
Task status
A task in FreeRTOS is always in one of the following states:
Running state
When a task is running, it is said that the task is in the running state, and the task in the running state is the task currently using the processor. If you are using a single-core processor, there will always be only one task running at any time.
Ready state
The tasks in the ready state are those that are ready (these tasks are not blocked or suspended) and can be run, but the tasks in the ready state have not yet been run because there is a task with the same priority or higher priority running!
Blocking state
If a task is currently waiting for an external event, it is said to be in the blocking state, for example, if a task calls the function vTaskDelay (), it will enter the blocking state until the delay period is completed. Tasks also enter the blocking state while waiting for queues, semaphores, event groups, notifications, or mutexes. When a task enters the blocking state, there will be a timeout, and when the timeout is exceeded, the task will exit the blocking state, even if the waiting event has not yet arrived!
Suspended state
Like the blocking state, a task cannot be called into the running state by the scheduler after it enters the pending state, but there is no timeout for the task to enter the pending state. Tasks enter and exit the pending state by calling the functions vTaskSuspend () and xTaskResume ().
Task priority
Each task can be assigned a priority from 0 ~ (configMAX_PRIORITIES-1). ConfigMAX_PRIORITIES is defined in the file FreeRTOSConfig.h, which we talked about earlier when we explained the FreeRTOS system configuration. If the hardware platform used supports instructions such as calculating leading zeros (which can be used to select the next task to be run, and the Cortex-M processor supports the instruction), and configUSE_PORT_OPTIMISED_TASK_SELECTION is also set to 1, then the macro configMax _ PRIORITIES cannot exceed 32! That is, the priority cannot exceed level 32. In other cases, the macro configMax _ PRIORITIES can be any value, but considering the consumption of RAM, the macro configMAX_PRIORITIES is best set to a minimum value that satisfies the application.
The lower the priority number, the lower the priority of the task, the lowest priority of 0, and the highest priority of configMAX_PRIORITIES-1. Idle tasks have the lowest priority of 0.
The FreeRTOS scheduler ensures that high-priority tasks in the ready or running state gain access to the processor, in other words, only the tasks with the highest priority in the ready state run. When the macro configUSE_TIME_SLICING is defined as 1, multiple tasks can share a single priority, unlimited in number. By default, the macro configUSE _ TIME_SLICING is defined as 1 in the file FreeRTOS.h. At this point, tasks with the same priority in the ready state will use the time slice round robin scheduler to get the run time.
Task realization
In the process of using FreeRTOS, we use the function xTaskCreate () or xTaskCreateStatic () to create the task, and the first parameter pxTaskCode of these two functions is the task function for this task. What is a task function? The task function is the function that completes the work of this task. What am I doing on this mission? What are you gonna do? All the functions to be accomplished are implemented in this task function. For example, I want to do a task, this task needs to light a water lamp, then the program of this water lamp is realized in the task function. The official task function template given by FreeRTOS is as follows:
Void vATaskFunction (void * pvParameters) {for (;;) {/ /-- Task application-- vTaskDelay (); / * you don't have to use a delay function here, other API functions that allow FreeRTOS to switch tasks, such as request semaphores, queues, etc., or even call the task scheduler directly. It's just that the most commonly used is the delay function of FreeRTOS. * /} / * cannot return or exit from the task function. If you return or exit from the task function, configASSERT () will be called, provided you define configASSERT (). If you must exit from the task function, be sure to call the function vTaskDelete (NULL) to delete the task. * / vTaskDelete (NULL); (5)} task control block
Each task in FreeRTOS has some attributes to store. FreeRTOS aggregates these attributes and represents them in a structure called task control block: TCB_t, which is automatically assigned to each task when you create a task using the function xTaskCreate (). In the old version of FreeRTOS, the task control block is called tskTCB, but the new version is renamed to TCB_t, but it is still tskTCB in nature. The task control block mentioned later in this tutorial is represented by TCB_t, and this structure is defined in the file tasks.c. The member variables in the task control block of FreeRTOS are much less than those of UCOSIII, and most of them are related to tailoring. when some functions are not used, the related variables do not participate in the compilation, and the size of the task control block will be further reduced.
Typedef struct tskTaskControlBlock {volatile StackType_t * pxTopOfStack; / / Top of Task Stack # if (portUSING_MPU_WRAPPERS = = 1) xMPU_SETTINGS xMPUSettings; / / MPU related Settings # endif ListItem_t xStateListItem; / / status list item ListItem_t xEventListItem; / / event list item UBaseType_t uxPriority; / / Task priority StackType_t * pxStack / / Task stack start address char pcTaskName [configMAX_TASK_NAME_LEN]; / / Task name # if (portSTACK_GROWTH > 0) StackType_t * pxEndOfStack; / / bottom of task stack # endif # if (portCRITICAL_NESTING_IN_TCB = = 1) UBaseType_t uxCriticalNesting / / critical section nesting depth # endif # if (configUSE_TRACE_FACILITY = = 1) / / trace or UBaseType_t uxTCBNumber; UBaseType_t uxTaskNumber; # endif # if (configUSE_MUTEXES = = 1) UBaseType_t uxBasePriority; / / basic task priority is used for debug, and UBaseType_t uxMutexesHeld is used for priority inversion / / the number of mutex semaphores obtained by the task # endif # if (configUSE_APPLICATION_TASK_TAG = = 1) TaskHookFunction_t pxTaskTag; # endif # if (configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0) / / related to local storage void * pvThreadLocalStoragePointers [configNUM_THREAD_LOCAL_STORAGE_POINTERS]; # endif # if (configGENERATE_RUN_TIME_STATS = = 1) uint32_t ulRunTimeCounter / / used to record the total task run time # endif # if (configUSE_NEWLIB_REENTRANT = = 1) struct _ reent xNewLib_reent; / / define a newlib structure variable # endif # if (configUSE_TASK_NOTIFICATIONS = = 1) / / task notification related variable volatile uint32_t ulNotifiedValue; / / task notification value volatile uint8_t ucNotifyState / / Task notification status # endif # if (tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE! = 0) / / used to mark whether the task is created dynamically or statically, pdTURE if statically created, and pdFALSE uint8_t ucStaticallyAllocated; # endif # if (INCLUDE_xTaskAbortDelay = = 1) uint8_t ucDelayAborted; # endif} tskTCB if created dynamically / / the new version of the FreeRTOS task control block is renamed to TCB_t, but in essence it is still tskTCB, mainly for compatibility with / / older versions of applications. Typedef tskTCB TCB_t;typedef struct tskTaskControlBlock {volatile StackType_t * pxTopOfStack; / / Top of Task Stack # if (portUSING_MPU_WRAPPERS = = 1) xMPU_SETTINGS xMPUSettings; / / MPU related Settings # endif ListItem_t xStateListItem; / / status list item ListItem_t xEventListItem; / / event list item UBaseType_t uxPriority; / / Task priority StackType_t * pxStack / / Task stack start address char pcTaskName [configMAX_TASK_NAME_LEN]; / / Task name # if (portSTACK_GROWTH > 0) StackType_t * pxEndOfStack; / / bottom of task stack # endif # if (portCRITICAL_NESTING_IN_TCB = = 1) UBaseType_t uxCriticalNesting / / critical section nesting depth # endif # if (configUSE_TRACE_FACILITY = = 1) / / trace or UBaseType_t uxTCBNumber; UBaseType_t uxTaskNumber; # endif # if (configUSE_MUTEXES = = 1) UBaseType_t uxBasePriority; / / basic task priority is used for debug, and UBaseType_t uxMutexesHeld is used for priority inversion / / the number of mutex semaphores obtained by the task # endif # if (configUSE_APPLICATION_TASK_TAG = = 1) TaskHookFunction_t pxTaskTag; # endif # if (configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0) / / related to local storage void * pvThreadLocalStoragePointers [configNUM_THREAD_LOCAL_STORAGE_POINTERS]; # endif # if (configGENERATE_RUN_TIME_STATS = = 1) uint32_t ulRunTimeCounter / / used to record the total task run time # endif # if (configUSE_NEWLIB_REENTRANT = = 1) struct _ reent xNewLib_reent; / / define a newlib structure variable # endif # if (configUSE_TASK_NOTIFICATIONS = = 1) / / task notification related variable volatile uint32_t ulNotifiedValue; / / task notification value volatile uint8_t ucNotifyState / / Task notification status # endif # if (tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE! = 0) / / used to mark whether the task is created dynamically or statically, pdTURE if statically created, and pdFALSE uint8_t ucStaticallyAllocated; # endif # if (INCLUDE_xTaskAbortDelay = = 1) uint8_t ucDelayAborted; # endif} tskTCB if created dynamically / / the new version of the FreeRTOS task control block is renamed to TCB_t, but in essence it is still tskTCB, mainly for compatibility with / / older versions of applications. Typedef tskTCB TCB_t; task stack
The reason why FreeRTOS can correctly restore the operation of a task is that there is a task stack escorting. When the task is switched, the task scheduler will save the site of the current task (CPU register values, etc.) in the task stack of this task. When the task runs next, it will first restore the scene with the values saved in the stack, and then the task will start running from the last interrupted place.
When creating a task, you need to assign a stack to the task. If you use the function xTaskCreate () to create the task (dynamic method), then the task stack will be automatically created by the function xTaskCreate (), which will be explained later when analyzing xTaskCreate (). If you use the function xTaskCreateStatic () to create a task (static method), you need the programmer to define the task stack, and then pass the stack header address to the function as an argument to the function puxStackBuffer.
The data type of the task stack is StackType_t,StackType_t, which is essentially uint32_t, which is defined in portmacro.h. So the variable of type StackType_t is 4 bytes, then the actual stack size of the task should be 4 times the size we defined.
At this point, I believe you have a deeper understanding of the basic knowledge of multitasking management in FreeRTOS real-time operating system. You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.