In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces the relevant knowledge of "how to realize the blocking delay of idle tasks in FreeRTOS real-time operating system". The editor shows you the operation process through an actual case, and the operation method is simple, fast and practical. I hope this article "how to realize the blocking delay of idle tasks in FreeRTOS real-time operating system" can help you solve the problem.
What is blocking delay and why idle tasks are needed
The delay in RTOS is called blocking delay, that is, when a task needs a delay, the task will give up the right to use cpu, and cpu will do something else instead. When the task delay time is up, the task will re-request to obtain the right to use cpu.
But when all the tasks are blocked, in order not to leave cpu idle to do, you need a free task for cpu to do.
Implementation of idle tasks
There is no difference between the implementation of idle tasks and the creation of ordinary tasks. Idle tasks are created inside the call to the vTaskStartScheduler function, as follows
/ / define idle stack # define configMINIMAL_STACK_SIZE ((unsigned short) 128) StackType_t IdleTaskStack [configMinimal _ STACK_SIZE]; / / idle task control block TCB_t IdleTaskTCB; / / set idle task parameters void vApplicationGetIdleTaskMemory (TCB_t * * ppxIdleTaskTCBBuffer, StackType_t * * ppxIdleTaskStackBuffer, uint32_t * pulIdleTaskStackSize) {* ppxIdleTaskTCBBuffer=&IdleTaskTCB * ppxIdleTaskStackBuffer=IdleTaskStack; * pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;} void vTaskStartScheduler (void) {TCB_t * pxIdleTaskTCBBuffer = NULL;// idle task control block pointer StackType_t * pxIdleTaskStackBuffer= NULL;// idle task stack pointer uint32_t ulIdleTaskStackSize / / idle task stack size / / set the idle task parameter vApplicationGetIdleTaskMemory (& pxIdleTaskTCBBuffer, & pxIdleTaskStackBuffer) & ulIdleTaskStackSize) / / create idle task xIdleTaskHandle = xTaskCreateStatic ((TaskFunction_t) prvIdleTask, (char *) "IDLE", (uint32_t) ulIdleTaskStackSize (void*) NULL, (StackType_t*) pxIdleTaskStackBuffer, (TCB_t*) pxIdleTaskTCBBuffer) / / add free tasks to the ready list vListInsertEnd (& (pxReadyTasksLists [0]), & (TCB_t *) pxIdleTaskTCBBuffer)-> xStateListItem)); / / manually specify the first task to run pxCurrentTCB = & Task1TCB / / start the scheduler if (xPortStartScheduler ()! = pdFALSE) {/ / if it starts successfully, it will not run here}} the implementation of blocking delay
Blocking delay requires the use of xTicksToDelay, which is a member of the TCB to record how much longer it will be blocked.
Typedef struct tskTaskControlBlock {volatile StackType_t * pxTopOfStack; ListItem_t xStateListItem; StackType_t * pxStack; char pcTaskName [configMAX _ TASK_NAME_LEN]; TickType_t xTicksToDelay; / / for delay} tskTCB
So that's how blocking delay is implemented.
Void vTaskDelay (const TickType_t xTicksToDelay) {TCB_t * pxTCB = NULL; pxTCB = pxCurrentTCB; / / set delay time pxTCB- > xTicksToDelay = xTicksToDelay; / / perform a task switch taskYIELD ();}
Due to the introduction of blocking delay, the task switching function needs to be rewritten, because when all tasks are blocked, you need to switch to idle tasks to run.
Void vTaskSwitchContext (void) {/ / if the current idle task, try to execute Task 1 or Task 2, and continue to execute the idle task if (pxCurrentTCB = = & IdleTaskTCB) {if (Task1TCB.xTicksToDelay = = 0) {pxCurrentTCB = & Task1TCB if their delay time is not up. } else if (Task2TCB.xTicksToDelay = = 0) {pxCurrentTCB = & Task2TCB;} else {return }} else / / if the current task is not idle, Task 1 or Task 2 will be executed here {/ / check another task / / if another task is not in delay, it will switch to that task / / otherwise, determine whether the current task is in delay, yes, switch to idle task, / / otherwise Do not switch any if (pxCurrentTCB = = & Task1TCB) {if (Task2TCB.xTicksToDelay = = 0) {pxCurrentTCB = & Task2TCB } else if (pxCurrentTCB- > xTicksToDelay! = 0) {pxCurrentTCB = & IdleTaskTCB } else {return }} else if (pxCurrentTCB = = & Task2TCB) {if (Task1TCB.xTicksToDelay = = 0) {pxCurrentTCB = & Task1TCB } else if (pxCurrentTCB- > xTicksToDelay! = 0) {pxCurrentTCB = & IdleTaskTCB } else {return;}} xTicksToDelay decrement
After the xTicksToDelay member is set in vTaskDelay, the decrement operation is realized through SystTick interrupt.
Void xPortSysTickHandler (void) {int x = portSET_INTERRUPT_MASK_FROM_ISR (); xTaskIncrementTick (); portCLEAR_INTERRUPT_MASK_FROM_ISR (x);} void xTaskIncrementTick (void) {TCB_t * pxTCB = NULL; BaseType_t iTuno; const TickType_t xConstTickCount = xTickCount + 1; xTickCount = xConstTickCount; for (iTun0; ixTicksToDelay > 0) {pxTCB- > xTicksToDelay-- / / decrement here}} portYIELD () } SysTick initialization / / systick control register # define portNVIC_SYSTICK_CTRL_REG (* (volatile uint32_t *) 0xe000e010) / / systick reload register # define portNVIC_SYSTICK_LOAD_REG (* ((volatile uint32_t *) 0xe000e014)) / / systick clock source selection # ifndef configSYSTICK_CLOCK_HZ # define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ # define portNVIC_SYSTICK_CLK_BIT (1UL
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.