首页 > 编程语言 >freeRTOS源码解析4--tasks.c 4

freeRTOS源码解析4--tasks.c 4

时间:2024-09-10 22:47:09浏览次数:10  
标签:task 优先级 freeRTOS mtCOVERAGE -- else priority pxTCB 源码

4.2.9 周期任务用的延迟--xTaskDelayUntil

接口:BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )

形参1:pxPreviousWakeTime,上一次唤醒时间,第一次需要用接口xTaskGetTickCount()获取;
形参2:xTimeIncrement,想要延迟的时间。

返回值:用于判读任务是否确实需要delay。

 1 BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
 2                                 const TickType_t xTimeIncrement )
 3 {
 4     TickType_t xTimeToWake;
 5     BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
 6 
 7     configASSERT( pxPreviousWakeTime );
 8     configASSERT( ( xTimeIncrement > 0U ) );
 9 
10     vTaskSuspendAll();
11     {
12         /* Minor optimisation. The tick count cannot change in this
13          * block. */
14         const TickType_t xConstTickCount = xTickCount;
15 
16         configASSERT( uxSchedulerSuspended == 1U );
17 
18         /* Generate the tick time at which the task wants to wake. */
19         /* 计算任务下次唤醒的时间 */
20         xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
21 
22         if( xConstTickCount < *pxPreviousWakeTime )
23         {
24             /* The tick count has overflowed since this function was
25              * lasted called.  In this case the only time we should ever
26              * actually delay is if the wake time has also  overflowed,
27              * and the wake time is greater than the tick time.  When this
28              * is the case it is as if neither time had overflowed. */
29             /* tick值已经溢出了, 只有xTimeToWake也溢出并大于xConstTickCount
30              * 时, 才需要延迟 */
31             /* 假设tick是8位的, 当前值为0x5(从FF加到5), pxPreviousWakeTime为0xFD,
32              * 当xTimeIncrement为1时, xTimeToWake未溢出, 当xTimeIncrement为0x15时,
33              * xTimeToWake溢出。 显然当xTimeIncrement为1时, xTimeToWake比
34              * pxPreviousWakeTime和xConstTickCount都大, 但不需要延迟, 因为tick已过,
35              * 当xTimeIncrement为0x15时, xTimeToWake比pxPreviousWakeTime小但比xConstTickCount
36              * 大, tick要等到0x12才到延迟时间, 所以需要进行延迟. */
37             if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
38             {
39                 xShouldDelay = pdTRUE;
40             }
41             else
42             {
43                 mtCOVERAGE_TEST_MARKER();
44             }
45         }
46         else
47         {
48             /* The tick time has not overflowed.  In this case we will
49              * delay if either the wake time has overflowed, and/or the
50              * tick time is less than the wake time. */
51             /* tick没有溢出, 那么xTimeToWake溢出或比xConstTickCount小,
52              * 必然是需要延迟的. */
53             if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
54             {
55                 xShouldDelay = pdTRUE;
56             }
57             else
58             {
59                 mtCOVERAGE_TEST_MARKER();
60             }
61         }
62 
63         /* Update the wake time ready for the next call. */
64         *pxPreviousWakeTime = xTimeToWake;
65 
66         if( xShouldDelay != pdFALSE )
67         {
68             /* prvAddCurrentTaskToDelayedList() needs the block time, not
69              * the time to wake, so subtract the current tick count. */
70             /* 延迟列表记录的是阻塞时间而不是唤醒时间, 所以需要减去tick. */
71             prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
72         }
73         else
74         {
75             mtCOVERAGE_TEST_MARKER();
76         }
77     }
78     xAlreadyYielded = xTaskResumeAll();
79 
80     /* Force a reschedule if xTaskResumeAll has not already done so, we may
81      * have put ourselves to sleep. */
82     if( xAlreadyYielded == pdFALSE )
83     {
84         taskYIELD_WITHIN_API();
85     }
86     else
87     {
88         mtCOVERAGE_TEST_MARKER();
89     }
90 
91     return xShouldDelay;
92 }
xTaskDelayUntil

 4.2.10 成对的信息获取接口,一般的和带有FromISR后缀的

这类接口比较简单,主要用于获取TCB中的某些参数,这里挑选任务优先级获取接口为例,重点在于带有FromISR的接口。一般的接口很简单,这里就直接放出来即可。

 1 UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
 2 {
 3     TCB_t const * pxTCB;
 4     UBaseType_t uxReturn;
 5 
 6     taskENTER_CRITICAL();
 7     {
 8         /* If null is passed in here then it is the priority of the task
 9          * that called uxTaskPriorityGet() that is being queried. */
10         pxTCB = prvGetTCBFromHandle( xTask );
11         uxReturn = pxTCB->uxPriority;
12     }
13     taskEXIT_CRITICAL();
14 
15     return uxReturn;
16 }
 1 UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
 2 {
 3     TCB_t const * pxTCB;
 4     UBaseType_t uxReturn;
 5     UBaseType_t uxSavedInterruptStatus;
 6 
 7     /* RTOS ports that support interrupt nesting have the concept of a
 8      * maximum  system call (or maximum API call) interrupt priority.
 9      * Interrupts that are  above the maximum system call priority are keep
10      * permanently enabled, even when the RTOS kernel is in a critical section,
11      * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
12      * is defined in FreeRTOSConfig.h then
13      * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
14      * failure if a FreeRTOS API function is called from an interrupt that has
15      * been assigned a priority above the configured maximum system call
16      * priority.  Only FreeRTOS functions that end in FromISR can be called
17      * from interrupts  that have been assigned a priority at or (logically)
18      * below the maximum system call interrupt priority.  FreeRTOS maintains a
19      * separate interrupt safe API to ensure interrupt entry is as fast and as
20      * simple as possible.  More information (albeit Cortex-M specific) is
21      * provided on the following link:
22      * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
23     /* 检查调用带有FromISR后缀的中断优先级是否高于
24      * configMAX_SYSCALL_INTERRUPT_PRIORITY, 是的话会进入assert */
25     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
26 
27     /* MISRA Ref 4.7.1 [Return value shall be checked] */
28     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
29     /* coverity[misra_c_2012_directive_4_7_violation] */
30     /* 获取当前中断屏蔽优先级, 并设置中断屏蔽优先级为configMAX_SYSCALL_INTERRUPT_PRIORITY
31      * 相当于进入了临界区并返回了当前中断屏蔽优先级 */
32     uxSavedInterruptStatus = ( UBaseType_t ) taskENTER_CRITICAL_FROM_ISR();
33     {
34         /* If null is passed in here then it is the priority of the calling
35          * task that is being queried. */
36         pxTCB = prvGetTCBFromHandle( xTask );
37         uxReturn = pxTCB->uxPriority;
38     }
39     /* 将保存的中断屏蔽优先级设置回去, 相当于退出临界区 */
40     taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
41 
42     return uxReturn;
43 }

4.2.11 设置任务优先级--vTaskPrioritySet

接口虽然较长,但注释较多,且逻辑较为简单,直接看代码里的注释即可。

  1 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
  2 {
  3     TCB_t * pxTCB;
  4     UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
  5     BaseType_t xYieldRequired = pdFALSE;
  6 
  7     configASSERT( uxNewPriority < configMAX_PRIORITIES );
  8 
  9     /* Ensure the new priority is valid. */
 10     if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
 11     {
 12         uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
 13     }
 14     else
 15     {
 16         mtCOVERAGE_TEST_MARKER();
 17     }
 18 
 19     taskENTER_CRITICAL();
 20     {
 21         /* If null is passed in here then it is the priority of the calling
 22          * task that is being changed. */
 23         pxTCB = prvGetTCBFromHandle( xTask );
 24 
 25         #if ( configUSE_MUTEXES == 1 )
 26         {
 27             uxCurrentBasePriority = pxTCB->uxBasePriority;
 28         }
 29         #else
 30         {
 31             uxCurrentBasePriority = pxTCB->uxPriority;
 32         }
 33         #endif
 34 
 35         if( uxCurrentBasePriority != uxNewPriority )
 36         {
 37             /* The priority change may have readied a task of higher
 38              * priority than a running task. */
 39             if( uxNewPriority > uxCurrentBasePriority )
 40             {
 41                 /* 提升优先级 */
 42                 #if ( configNUMBER_OF_CORES == 1 )
 43                 {
 44                     if( pxTCB != pxCurrentTCB )
 45                     {
 46                         /* The priority of a task other than the currently
 47                          * running task is being raised.  Is the priority being
 48                          * raised above that of the running task? */
 49                         /* 设置的优先级比当前运行的任务高, 需要yield */
 50                         if( uxNewPriority > pxCurrentTCB->uxPriority )
 51                         {
 52                             xYieldRequired = pdTRUE;
 53                         }
 54                         else
 55                         {
 56                             mtCOVERAGE_TEST_MARKER();
 57                         }
 58                     }
 59                     else
 60                     {
 61                         /* The priority of the running task is being raised,
 62                          * but the running task must already be the highest
 63                          * priority task able to run so no yield is required. */
 64                     }
 65                 }
 66                 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 67             }
 68             else if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
 69             {
 70                 /* Setting the priority of a running task down means
 71                  * there may now be another task of higher priority that
 72                  * is ready to execute. */
 73                 /* 降低当前运行任务的优先级, 则更高优先级的就绪任务需要抢占 */
 74                 #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
 75                     if( pxTCB->xPreemptionDisable == pdFALSE )
 76                 #endif
 77                 {
 78                     xYieldRequired = pdTRUE;
 79                 }
 80             }
 81             else
 82             {
 83                 /* Setting the priority of any other task down does not
 84                  * require a yield as the running task must be above the
 85                  * new priority of the task being modified. */
 86             }
 87 
 88             /* Remember the ready list the task might be referenced from
 89              * before its uxPriority member is changed so the
 90              * taskRESET_READY_PRIORITY() macro can function correctly. */
 91             /* 获取任务当前的优先级, 有可能是继承来的优先级 */
 92             uxPriorityUsedOnEntry = pxTCB->uxPriority;
 93 
 94             #if ( configUSE_MUTEXES == 1 )
 95             {
 96                 /* Only change the priority being used if the task is not
 97                  * currently using an inherited priority or the new priority
 98                  * is bigger than the inherited priority. */
 99                 /* 只有非继承来的优先级, 或提升优先级才可以直接修改pxTCB->uxPriority */
100                 if( ( pxTCB->uxBasePriority == pxTCB->uxPriority ) || ( uxNewPriority > pxTCB->uxPriority ) )
101                 {
102                     pxTCB->uxPriority = uxNewPriority;
103                 }
104                 else
105                 {
106                     mtCOVERAGE_TEST_MARKER();
107                 }
108 
109                 /* The base priority gets set whatever. */
110                 pxTCB->uxBasePriority = uxNewPriority;
111             }
112             #else /* if ( configUSE_MUTEXES == 1 ) */
113             {
114                 pxTCB->uxPriority = uxNewPriority;
115             }
116             #endif /* if ( configUSE_MUTEXES == 1 ) */
117 
118             /* Only reset the event list item value if the value is not
119              * being used for anything else. */
120             /* xEventListItem的值未被使用, 才允许更新这个值 */
121             if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0U ) )
122             {
123                 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) );
124             }
125             else
126             {
127                 mtCOVERAGE_TEST_MARKER();
128             }
129 
130             /* If the task is in the blocked or suspended list we need do
131              * nothing more than change its priority variable. However, if
132              * the task is in a ready list it needs to be removed and placed
133              * in the list appropriate to its new priority. */
134             /* 如果任务处于就绪列表, 则需要将其放到修改后的优先级就绪列表 */
135             if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
136             {
137                 /* The task is currently in its ready list - remove before
138                  * adding it to its new ready list.  As we are in a critical
139                  * section we can do this even if the scheduler is suspended. */
140                 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
141                 {
142                     /* It is known that the task is in its ready list so
143                      * there is no need to check again and the port level
144                      * reset macro can be called directly. */
145                     portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
146                 }
147                 else
148                 {
149                     mtCOVERAGE_TEST_MARKER();
150                 }
151 
152                 prvAddTaskToReadyList( pxTCB );
153             }
154             else
155             {
156                 #if ( configNUMBER_OF_CORES == 1 )
157                 {
158                     mtCOVERAGE_TEST_MARKER();
159                 }
160                 #endif
161             }
162 
163             if( xYieldRequired != pdFALSE )
164             {
165                 /* The running task priority is set down. Request the task to yield. */
166                 /* 开始yield, 但是在退出临界区后才会进入sv中断? */
167                 taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB );
168             }
169             else
170             {
171                 mtCOVERAGE_TEST_MARKER();
172             }
173 
174             /* Remove compiler warning about unused variables when the port
175              * optimised task selection is not being used. */
176             ( void ) uxPriorityUsedOnEntry;
177         }
178     }
179     taskEXIT_CRITICAL();
180 }
vTaskPrioritySet

4.2.12 挂起任务--vTaskSuspend

还是直接看代码注释,解释得比较清楚了,接口功能可以顾名思义,逻辑也还好不复杂。

  1 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
  2 {
  3     TCB_t * pxTCB;
  4 
  5     taskENTER_CRITICAL();
  6     {
  7         /* If null is passed in here then it is the running task that is
  8          * being suspended. */
  9         pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
 10 
 11         /* Remove task from the ready/delayed list and place in the
 12          * suspended list. */
 13         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 14         {
 15             taskRESET_READY_PRIORITY( pxTCB->uxPriority );
 16         }
 17         else
 18         {
 19             mtCOVERAGE_TEST_MARKER();
 20         }
 21 
 22         /* Is the task waiting on an event also? */
 23         /* 任务挂起, 任务就不管是否在等待事件 */
 24         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
 25         {
 26             ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
 27         }
 28         else
 29         {
 30             mtCOVERAGE_TEST_MARKER();
 31         }
 32 
 33         vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
 34 
 35         /* 如果在等待通知, 也直接退出等待 */
 36         #if ( configUSE_TASK_NOTIFICATIONS == 1 )
 37         {
 38             BaseType_t x;
 39 
 40             for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
 41             {
 42                 if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
 43                 {
 44                     /* The task was blocked to wait for a notification, but is
 45                      * now suspended, so no notification was received. */
 46                     pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;
 47                 }
 48             }
 49         }
 50         #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
 51     }
 52     taskEXIT_CRITICAL();
 53 
 54     #if ( configNUMBER_OF_CORES == 1 )
 55     {
 56         UBaseType_t uxCurrentListLength;
 57 
 58         if( xSchedulerRunning != pdFALSE )
 59         {
 60             /* Reset the next expected unblock time in case it referred to the
 61              * task that is now in the Suspended state. */
 62             /* 如果下个解除阻塞的时间对应的任务正好是挂起的任务,
 63              * 无论如何重置一下下个解除阻塞的时间 */
 64             taskENTER_CRITICAL();
 65             {
 66                 prvResetNextTaskUnblockTime();
 67             }
 68             taskEXIT_CRITICAL();
 69         }
 70         else
 71         {
 72             mtCOVERAGE_TEST_MARKER();
 73         }
 74 
 75         if( pxTCB == pxCurrentTCB )
 76         {
 77             if( xSchedulerRunning != pdFALSE )
 78             {
 79                 /* The current task has just been suspended. */
 80                 /* 当前运行的任务挂起, 需要yield */
 81                 configASSERT( uxSchedulerSuspended == 0 );
 82                 portYIELD_WITHIN_API();
 83             }
 84             else
 85             {
 86                 /* The scheduler is not running, but the task that was pointed
 87                  * to by pxCurrentTCB has just been suspended and pxCurrentTCB
 88                  * must be adjusted to point to a different task. */
 89 
 90                 /* Use a temp variable as a distinct sequence point for reading
 91                  * volatile variables prior to a comparison to ensure compliance
 92                  * with MISRA C 2012 Rule 13.2. */
 93                 uxCurrentListLength = listCURRENT_LIST_LENGTH( &xSuspendedTaskList );
 94 
 95                 if( uxCurrentListLength == uxCurrentNumberOfTasks )
 96                 {
 97                     /* No other tasks are ready, so set pxCurrentTCB back to
 98                      * NULL so when the next task is created pxCurrentTCB will
 99                      * be set to point to it no matter what its relative priority
100                      * is. */
101                     /* 所有创建的任务处于挂起状态, 只能等新任务创建了 */
102                     pxCurrentTCB = NULL;
103                 }
104                 else
105                 {
106                     /* 切换下上下文, 因为挂起的是当前任务, 也有可能就绪列表为空,
107                      * 会导致pxCurrentTCB = idle, 否则会选择就绪列表中优先级最高
108                      * 任务, 这个接口在这里只是设置了pxCurrentTCB参数, 并pend了
109                      * yield, 因为当前调度器处于暂停状态 */
110                     vTaskSwitchContext();
111                 }
112             }
113         }
114         else
115         {
116             mtCOVERAGE_TEST_MARKER();
117         }
118     }
119     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
120 }
vTaskSuspend

 

  这篇就到这里了,内容也比较多,下篇开始vTaskResume和vTaskStartScheduler。

下篇再见!

标签:task,优先级,freeRTOS,mtCOVERAGE,--,else,priority,pxTCB,源码
From: https://www.cnblogs.com/freeManX1807/p/18403493

相关文章

  • 【第二周】人工智能学习内容
    1.学会了如何注册并登陆使用博客2.了解了2种搜索引擎:全文搜索、目录搜索3.使用“——”符号,搜索格式为“关键词A+空格+减号+关键词B”4.使用三种指令:(1)filetype指令搜索格式:关键词+空格+filetype:+文件格式(2)site指令搜索格式:关键词+空格+site:+网站(3)intitle指令搜索格式:intit......
  • Base/chat/instruct in LLM
    Base/chat/instructhttps://blog.csdn.net/qq_43127132/article/details/140447880大模型库中的base、chat、instruct和4bit通常指的是不同类型或配置的预训练语言模型。它们的区别主要在于训练目标、用途和模型参数的精度。以下是对这些术语的解释:1.Base模型(base)   ......
  • 开学日记2
    今天我写了一个简单的计算器程序,能够执行加法、减法、乘法和除法。程序代码如下:importjava.util.Scanner;publicclassCalculator{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);System.out.print("Enterfirstnumber:");......
  • spring boot 项目报错找不到compose.yaml文件
    springboot的项目引用了spring-boot-docker-compose,运行时没问题,但是将该项目放到了一个父项目中作为一个module后,在idea里直接运行的话会报错找不到compose.yaml文件,因为idea试图去父项目的路径下找。如果直接在子项目的路径里运行:mvnspring-boot:run是没问题的,可以启动。......
  • 智能指针
    C++智能指针解析为什么需要智能指针众所周知,Java和C/C++中间隔着一堵由内存动态分配和垃圾回收机制所围成的墙。java大佬们经常吐槽C++没有垃圾回收(GabageCollector)机制,而C++爱好者也经常攻击Java限制太死,不够灵活。其实Java并不是最早实践内存动态分配和垃圾自......
  • 动态内存管理
    C/C++malloc-free底层原理-动态内存管理关于动态内存管理这块在面试中被考察频率非常高,切入的点也很多,有从操作系统虚拟内存问起的,也有从malloc、new等开始问起的。但是无外乎就是两块内容:虚拟内存机制:物理和虚拟地址空间、TLB页表、内存映射动态内存管理:内存管理、分配......
  • 大模拟题的注意事项合集
    P2058[NOIP2016普及组]海港坑点:一开始的思路是直接建一个队列,如果队里有这个国家的人那么就不进队,根据时间不断删除队首,查询队列的size。很容易看出这个思路不可行。因为这个时刻队列中有这个国籍的人,下一次就不一定是这一个了那我们记录此时队列中有几个此国籍的人,根据......
  • 981. 基于时间的键值存储
    题目链接981.基于时间的键值存储思路哈希+二分题解链接哈希表+二分关键点理解题意时间复杂度\(O(\logn)\)空间复杂度\(O(n)\)代码实现:classTimeMap:def__init__(self):self.dct=defaultdict(list)defset(self,key:s......
  • 使用VSCode搭建UniApp + TS + Vue3 + Vite项目
    uniapp是一个使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、以及各种小程序。深受广大前端开发者的喜爱。uniapp官方也提供了自己的IDE工具HBuilderX,可以快速开发uniapp项目。但是很多前端的同学已经比较习惯使用VSCode去开发项目,为了开发uniapp项目......
  • 计算机网络
    计算机网络总分100=期中20+期末50+实验20+平时10(期中考前三章,期末考后三章)第一章概述1.1互联网两个重要基本特点:连通性、共享连通性:上网用户交换各种信息共享:指资源共享,可以是信息共享、软件共享、硬件共享1.2网络把许多计算机连接在一起,互连网把许多网络通过......