找回密码
 立即注册
首页 业界区 安全 freeRTOS源码解析4--tasks.c 6

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

屠焘 2025-6-8 13:08:56
4.2.14 退出阻塞--xTaskAbortDelay

接口:
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
形参1:xTask ,想要退出阻塞态的任务;
返回:pdPASS:退出成功;pdFAIL:退出失败。
1.gif
2.gif
  1. 1 BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
  2. 2 {
  3. 3     TCB_t * pxTCB = xTask;
  4. 4     BaseType_t xReturn;
  5. 5
  6. 6     configASSERT( pxTCB );
  7. 7
  8. 8     vTaskSuspendAll();
  9. 9     {
  10. 10         /* A task can only be prematurely removed from the Blocked state if
  11. 11          * it is actually in the Blocked state. */
  12. 12         /* 任务只有真的在阻塞态才能提前移出阻塞态 */
  13. 13         if( eTaskGetState( xTask ) == eBlocked )
  14. 14         {
  15. 15             xReturn = pdPASS;
  16. 16
  17. 17             /* Remove the reference to the task from the blocked list.  An
  18. 18              * interrupt won't touch the xStateListItem because the
  19. 19              * scheduler is suspended. */
  20. 20             ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
  21. 21
  22. 22             /* Is the task waiting on an event also?  If so remove it from
  23. 23              * the event list too.  Interrupts can touch the event list item,
  24. 24              * even though the scheduler is suspended, so a critical section
  25. 25              * is used. */
  26. 26             /* 如果任务在等待事件, 则移出事件列表, 因为调度器暂停时, 中断仍
  27. 27              * 能访问事件列表, 所以需要进入临界区 */
  28. 28             taskENTER_CRITICAL();
  29. 29             {
  30. 30                 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
  31. 31                 {
  32. 32                     ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
  33. 33
  34. 34                     /* This lets the task know it was forcibly removed from the
  35. 35                      * blocked state so it should not re-evaluate its block time and
  36. 36                      * then block again. */
  37. 37                     /* 让任务知道是被强制移出阻塞态的, 防止被重新计算阻塞时间再次进入
  38. 38                      * 阻塞态 */
  39. 39                     pxTCB->ucDelayAborted = ( uint8_t ) pdTRUE;
  40. 40                 }
  41. 41                 else
  42. 42                 {
  43. 43                     mtCOVERAGE_TEST_MARKER();
  44. 44                 }
  45. 45             }
  46. 46             taskEXIT_CRITICAL();
  47. 47
  48. 48             /* Place the unblocked task into the appropriate ready list. */
  49. 49             prvAddTaskToReadyList( pxTCB );
  50. 50
  51. 51             /* A task being unblocked cannot cause an immediate context
  52. 52              * switch if preemption is turned off. */
  53. 53             #if ( configUSE_PREEMPTION == 1 )
  54. 54             {
  55. 55                 #if ( configNUMBER_OF_CORES == 1 )
  56. 56                 {
  57. 57                     /* Preemption is on, but a context switch should only be
  58. 58                      * performed if the unblocked task has a priority that is
  59. 59                      * higher than the currently executing task. */
  60. 60                     /* 比当前任务优先级高, 等调度器运行后, 需要进行yield */
  61. 61                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
  62. 62                     {
  63. 63                         /* Pend the yield to be performed when the scheduler
  64. 64                          * is unsuspended. */
  65. 65                         xYieldPendings[ 0 ] = pdTRUE;
  66. 66                     }
  67. 67                     else
  68. 68                     {
  69. 69                         mtCOVERAGE_TEST_MARKER();
  70. 70                     }
  71. 71                 }
  72. 72                 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
  73. 73             }
  74. 74             #endif /* #if ( configUSE_PREEMPTION == 1 ) */
  75. 75         }
  76. 76         else
  77. 77         {
  78. 78             xReturn = pdFAIL;
  79. 79         }
  80. 80     }
  81. 81     ( void ) xTaskResumeAll();
  82. 82
  83. 83     return xReturn;
  84. 84 }
复制代码
xTaskAbortDelay 这个接口主要就是强制将在阻塞态的任务变成就绪态。
3.jpg

4.2.15 系统滴答时钟处理--xTaskIncrementTick

接口:
BaseType_t xTaskIncrementTick( void )
返回:pdPASS:需要切换上下文;pdFAIL:不需要切换上下文。
接口代码如下:
4.gif
5.gif
  1.   1 BaseType_t xTaskIncrementTick( void )
  2.   2 {
  3.   3     TCB_t * pxTCB;
  4.   4     TickType_t xItemValue;
  5.   5     BaseType_t xSwitchRequired = pdFALSE;
  6.   6
  7.   7     /* Tick increment should occur on every kernel timer event. Core 0 has the
  8.   8      * responsibility to increment the tick, or increment the pended ticks if the
  9.   9      * scheduler is suspended.  If pended ticks is greater than zero, the core that
  10. 10      * calls xTaskResumeAll has the responsibility to increment the tick. */
  11. 11     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
  12. 12     {
  13. 13         /* Minor optimisation.  The tick count cannot change in this
  14. 14          * block. */
  15. 15         const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
  16. 16
  17. 17         /* Increment the RTOS tick, switching the delayed and overflowed
  18. 18          * delayed lists if it wraps to 0. */
  19. 19         xTickCount = xConstTickCount;
  20. 20
  21. 21         /* tick溢出了, 交换下delay列表 */
  22. 22         if( xConstTickCount == ( TickType_t ) 0U )
  23. 23         {
  24. 24             taskSWITCH_DELAYED_LISTS();
  25. 25         }
  26. 26         else
  27. 27         {
  28. 28             mtCOVERAGE_TEST_MARKER();
  29. 29         }
  30. 30
  31. 31         /* See if this tick has made a timeout expire.  Tasks are stored in
  32. 32          * the  queue in the order of their wake time - meaning once one task
  33. 33          * has been found whose block time has not expired there is no need to
  34. 34          * look any further down the list. */
  35. 35         /* 因为delay列表的项是按唤醒时间从小到大排序的, 所以遍历过程中一旦发现
  36. 36          * 任务唤醒时间没到, 就可以停止了 */
  37. 37         if( xConstTickCount >= xNextTaskUnblockTime )
  38. 38         {
  39. 39             for( ; ; )
  40. 40             {
  41. 41                 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
  42. 42                 {
  43. 43                     /* The delayed list is empty.  Set xNextTaskUnblockTime
  44. 44                      * to the maximum possible value so it is extremely
  45. 45                      * unlikely that the
  46. 46                      * if( xTickCount >= xNextTaskUnblockTime ) test will pass
  47. 47                      * next time through. */
  48. 48                     xNextTaskUnblockTime = portMAX_DELAY;
  49. 49                     break;
  50. 50                 }
  51. 51                 else
  52. 52                 {
  53. 53                     /* The delayed list is not empty, get the value of the
  54. 54                      * item at the head of the delayed list.  This is the time
  55. 55                      * at which the task at the head of the delayed list must
  56. 56                      * be removed from the Blocked state. */
  57. 57                     /* MISRA Ref 11.5.3 [Void pointer assignment] */
  58. 58                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
  59. 59                     /* coverity[misra_c_2012_rule_11_5_violation] */
  60. 60                     pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
  61. 61                     xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
  62. 62
  63. 63                     if( xConstTickCount < xItemValue )
  64. 64                     {
  65. 65                         /* It is not time to unblock this item yet, but the
  66. 66                          * item value is the time at which the task at the head
  67. 67                          * of the blocked list must be removed from the Blocked
  68. 68                          * state -  so record the item value in
  69. 69                          * xNextTaskUnblockTime. */
  70. 70                         /* 这个任务未到唤醒时间, 但因为前面的都移出了, 所以这一定
  71. 71                          * 是下次最近唤醒的时间, 记录下来 */
  72. 72                         xNextTaskUnblockTime = xItemValue;
  73. 73                         break;
  74. 74                     }
  75. 75                     else
  76. 76                     {
  77. 77                         mtCOVERAGE_TEST_MARKER();
  78. 78                     }
  79. 79
  80. 80                     /* It is time to remove the item from the Blocked state. */
  81. 81                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
  82. 82
  83. 83                     /* Is the task waiting on an event also?  If so remove
  84. 84                      * it from the event list. */
  85. 85                     /* 等待事件的话, 移出事件列表 */
  86. 86                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
  87. 87                     {
  88. 88                         listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
  89. 89                     }
  90. 90                     else
  91. 91                     {
  92. 92                         mtCOVERAGE_TEST_MARKER();
  93. 93                     }
  94. 94
  95. 95                     /* Place the unblocked task into the appropriate ready
  96. 96                      * list. */
  97. 97                     prvAddTaskToReadyList( pxTCB );
  98. 98
  99. 99                     /* A task being unblocked cannot cause an immediate
  100. 100                      * context switch if preemption is turned off. */
  101. 101                     #if ( configUSE_PREEMPTION == 1 )
  102. 102                     {
  103. 103                         #if ( configNUMBER_OF_CORES == 1 )
  104. 104                         {
  105. 105                             /* Preemption is on, but a context switch should
  106. 106                              * only be performed if the unblocked task's
  107. 107                              * priority is higher than the currently executing
  108. 108                              * task.
  109. 109                              * The case of equal priority tasks sharing
  110. 110                              * processing time (which happens when both
  111. 111                              * preemption and time slicing are on) is
  112. 112                              * handled below.*/
  113. 113                             /* 移出的任务优先级比当前运行的任务高, 需要上下文切换 */
  114. 114                             if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
  115. 115                             {
  116. 116                                 xSwitchRequired = pdTRUE;
  117. 117                             }
  118. 118                             else
  119. 119                             {
  120. 120                                 mtCOVERAGE_TEST_MARKER();
  121. 121                             }
  122. 122                         }
  123. 123                         #endif /* #if( configNUMBER_OF_CORES == 1 ) */
  124. 124                     }
  125. 125                     #endif /* #if ( configUSE_PREEMPTION == 1 ) */
  126. 126                 }
  127. 127             }
  128. 128         }
  129. 129
  130. 130         /* Tasks of equal priority to the currently running task will share
  131. 131          * processing time (time slice) if preemption is on, and the application
  132. 132          * writer has not explicitly turned time slicing off. */
  133. 133         /* 相同优先级的任务用时间片运行, 每个时间片长是一个tick. 这里不用管更高
  134. 134          * 优先级的任务是否唤醒, 一是上面已经判断过了, 二是只是需要知道是否要上
  135. 135          * 下文切换, 这样判断就足够了, 在上下文切换的时候自然会选择合适的任务运行 */
  136. 136         #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
  137. 137         {
  138. 138             #if ( configNUMBER_OF_CORES == 1 )
  139. 139             {
  140. 140                 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U )
  141. 141                 {
  142. 142                     xSwitchRequired = pdTRUE;
  143. 143                 }
  144. 144                 else
  145. 145                 {
  146. 146                     mtCOVERAGE_TEST_MARKER();
  147. 147                 }
  148. 148             }
  149. 149             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
  150. 150         }
  151. 151         #endif /* #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
  152. 152
  153. 153         #if ( configUSE_TICK_HOOK == 1 )
  154. 154         {
  155. 155             /* Guard against the tick hook being called when the pended tick
  156. 156              * count is being unwound (when the scheduler is being unlocked). */
  157. 157             if( xPendedTicks == ( TickType_t ) 0 )
  158. 158             {
  159. 159                 vApplicationTickHook();
  160. 160             }
  161. 161             else
  162. 162             {
  163. 163                 mtCOVERAGE_TEST_MARKER();
  164. 164             }
  165. 165         }
  166. 166         #endif /* configUSE_TICK_HOOK */
  167. 167
  168. 168         #if ( configUSE_PREEMPTION == 1 )
  169. 169         {
  170. 170             #if ( configNUMBER_OF_CORES == 1 )
  171. 171             {
  172. 172                 /* For single core the core ID is always 0. */
  173. 173                 if( xYieldPendings[ 0 ] != pdFALSE )
  174. 174                 {
  175. 175                     xSwitchRequired = pdTRUE;
  176. 176                 }
  177. 177                 else
  178. 178                 {
  179. 179                     mtCOVERAGE_TEST_MARKER();
  180. 180                 }
  181. 181             }
  182. 182             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
  183. 183         }
  184. 184         #endif /* #if ( configUSE_PREEMPTION == 1 ) */
  185. 185     }
  186. 186     else
  187. 187     {
  188. 188         /* 调度器处于暂停中, 在xTaskResumeAll接口中检查xPendedTicks的值,
  189. 189          * 并调用本接口处理tick值. */
  190. 190         xPendedTicks += 1U;
  191. 191
  192. 192         /* The tick hook gets called at regular intervals, even if the
  193. 193          * scheduler is locked. */
  194. 194         #if ( configUSE_TICK_HOOK == 1 )
  195. 195         {
  196. 196             vApplicationTickHook();
  197. 197         }
  198. 198         #endif
  199. 199     }
  200. 200
  201. 201     return xSwitchRequired;
  202. 202 }
复制代码
xTaskIncrementTick   接口比较复杂,流程图就不贴了,太长。这个接口简单来讲就是如果调度器未停止,就检查每个阻塞的任务是否到了等待时间,包括本身延迟的时间和等待事件的超时时间,并加入到就绪列表中。
 
4.2.16 切换上下文--vTaskSwitchContext

切换上下文,主要作用是挑选出需要切换过去的任务。
接口:
void vTaskSwitchContext( void )
接口代码如下:
6.gif
7.gif
  1. 1 void vTaskSwitchContext( void )
  2. 2 {
  3. 3     if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
  4. 4     {
  5. 5         /* The scheduler is currently suspended - do not allow a context
  6. 6          * switch. */
  7. 7         /* 调度器暂停时, 不允许上下文切换 */
  8. 8         xYieldPendings[ 0 ] = pdTRUE;
  9. 9     }
  10. 10     else
  11. 11     {
  12. 12         xYieldPendings[ 0 ] = pdFALSE;
  13. 13
  14. 14         /* Check for stack overflow, if configured. */
  15. 15         /* 就是检查当前栈的位置有没有超过栈顶位置 */
  16. 16         taskCHECK_FOR_STACK_OVERFLOW();
  17. 17
  18. 18         /* Before the currently running task is switched out, save its errno. */
  19. 19         #if ( configUSE_POSIX_ERRNO == 1 )
  20. 20         {
  21. 21             pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
  22. 22         }
  23. 23         #endif
  24. 24
  25. 25         /* Select a new task to run using either the generic C or port
  26. 26          * optimised asm code. */
  27. 27         /* MISRA Ref 11.5.3 [Void pointer assignment] */
  28. 28         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
  29. 29         /* coverity[misra_c_2012_rule_11_5_violation] */
  30. 30         /* 选择就绪列表中优先级最高的任务 */
  31. 31         taskSELECT_HIGHEST_PRIORITY_TASK();
  32. 32
  33. 33         /* Macro to inject port specific behaviour immediately after
  34. 34          * switching tasks, such as setting an end of stack watchpoint
  35. 35          * or reconfiguring the MPU. */
  36. 36         portTASK_SWITCH_HOOK( pxCurrentTCB );
  37. 37
  38. 38         /* After the new task is switched in, update the global errno. */
  39. 39         #if ( configUSE_POSIX_ERRNO == 1 )
  40. 40         {
  41. 41             FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
  42. 42         }
  43. 43         #endif
  44. 44     }
  45. 45 }
复制代码
vTaskSwitchContext  最核心的就是“taskSELECT_HIGHEST_PRIORITY_TASK();”调用。
  4.2.17 加入到事件列表--vTaskPlaceOnEventList

把当前任务放到事件列表中,主要用于队列的实现。
接口:
void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
形参1:pxEventList,事件列表;
形参2:xTicksToWait ,最长等待时间。
接口代码如下:
8.gif
9.gif
  1. 1 void vTaskPlaceOnEventList( List_t * const pxEventList,
  2. 2                             const TickType_t xTicksToWait )
  3. 3 {
  4. 4     configASSERT( pxEventList );
  5. 5
  6. 6     /* THIS FUNCTION MUST BE CALLED WITH THE
  7. 7      * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
  8. 8
  9. 9     /* Place the event list item of the TCB in the appropriate event list.
  10. 10      * This is placed in the list in priority order so the highest priority task
  11. 11      * is the first to be woken by the event.
  12. 12      *
  13. 13      * Note: Lists are sorted in ascending order by ListItem_t.xItemValue.
  14. 14      * Normally, the xItemValue of a TCB's ListItem_t members is:
  15. 15      *      xItemValue = ( configMAX_PRIORITIES - uxPriority )
  16. 16      * Therefore, the event list is sorted in descending priority order.
  17. 17      *
  18. 18      * The queue that contains the event list is locked, preventing
  19. 19      * simultaneous access from interrupts. */
  20. 20     /* 将当前任务加入到事件列表, 列表是按升序存放的, 而一般情况下, 任务的
  21. 21      * xEventListItem的值是xItemValue=(configMAX_PRIORITIES-uxPriority),
  22. 22      * 所以事件列表是按优先级降序排列的 */
  23. 23     vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
  24. 24
  25. 25     /* 还需要放到延迟列表中, 用于最大延迟时间的唤醒 */
  26. 26     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
  27. 27 }
复制代码
vTaskPlaceOnEventList  4.2.18 加入到无序事件列表--vTaskPlaceOnUnorderedEventList

把当前任务放到无序的事件列表中,主要用于事件组。
接口:
void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,const TickType_t xItemValue, const TickType_t xTicksToWait )
形参1:pxEventList,事件列表;
形参2:xItemValue,设置的值
形参3:xTicksToWait ,最长等待时间。
接口代码如下:
10.gif
11.gif
  1. 1 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
  2. 2                                      const TickType_t xItemValue,
  3. 3                                      const TickType_t xTicksToWait )
  4. 4 {
  5. 5     configASSERT( pxEventList );
  6. 6
  7. 7     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
  8. 8      * the event groups implementation. */
  9. 9     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
  10. 10
  11. 11     /* Store the item value in the event list item.  It is safe to access the
  12. 12      * event list item here as interrupts won't access the event list item of a
  13. 13      * task that is not in the Blocked state. */
  14. 14     /* 中断只会访问处于Blocked态的事件列表项, 这里当前任务明显还未进入Blocked态 */
  15. 15     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
  16. 16
  17. 17     /* Place the event list item of the TCB at the end of the appropriate event
  18. 18      * list.  It is safe to access the event list here because it is part of an
  19. 19      * event group implementation - and interrupts don't access event groups
  20. 20      * directly (instead they access them indirectly by pending function calls to
  21. 21      * the task level). */
  22. 22     /* 主要是用于事件组的实现, 中断不会直接访问. 无序存放, 所以直接放在最后 */
  23. 23     listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
  24. 24
  25. 25     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
  26. 26 }
复制代码
vTaskPlaceOnUnorderedEventList  4.2.19 移出事件列表--xTaskRemoveFromEventList

将当前任务从事件列表中移出,主要用于队列的实现。
接口:
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
形参1:pxEventList,事件列表;
返回值:pdTRUE:需要进行上下文切换;pdFALSE:不需要。
接口代码如下:
12.gif
13.gif
  1. 1 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
  2. 2 {
  3. 3     TCB_t * pxUnblockedTCB;
  4. 4     BaseType_t xReturn;
  5. 5
  6. 6     /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION.  It can also be
  7. 7      * called from a critical section within an ISR. */
  8. 8
  9. 9     /* The event list is sorted in priority order, so the first in the list can
  10. 10      * be removed as it is known to be the highest priority.  Remove the TCB from
  11. 11      * the delayed list, and add it to the ready list.
  12. 12      *
  13. 13      * If an event is for a queue that is locked then this function will never
  14. 14      * get called - the lock count on the queue will get modified instead.  This
  15. 15      * means exclusive access to the event list is guaranteed here.
  16. 16      *
  17. 17      * This function assumes that a check has already been made to ensure that
  18. 18      * pxEventList is not empty. */
  19. 19     /* MISRA Ref 11.5.3 [Void pointer assignment] */
  20. 20     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
  21. 21     /* coverity[misra_c_2012_rule_11_5_violation] */
  22. 22     /* 按优先级降序存放的, 所以头部是优先级最高的任务 */
  23. 23     pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
  24. 24     configASSERT( pxUnblockedTCB );
  25. 25     listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );
  26. 26
  27. 27     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
  28. 28     {
  29. 29         listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
  30. 30         prvAddTaskToReadyList( pxUnblockedTCB );
  31. 31
  32. 32         #if ( configUSE_TICKLESS_IDLE != 0 )
  33. 33         {
  34. 34             /* If a task is blocked on a kernel object then xNextTaskUnblockTime
  35. 35              * might be set to the blocked task's time out time.  If the task is
  36. 36              * unblocked for a reason other than a timeout xNextTaskUnblockTime is
  37. 37              * normally left unchanged, because it is automatically reset to a new
  38. 38              * value when the tick count equals xNextTaskUnblockTime.   However if
  39. 39              * tickless idling is used it might be more important to enter sleep mode
  40. 40              * at the earliest possible time - so reset xNextTaskUnblockTime here to
  41. 41              * ensure it is updated at the earliest possible time. */
  42. 42             /* 重置最近唤醒时间 */
  43. 43             prvResetNextTaskUnblockTime();
  44. 44         }
  45. 45         #endif
  46. 46     }
  47. 47     else
  48. 48     {
  49. 49         /* The delayed and ready lists cannot be accessed, so hold this task
  50. 50          * pending until the scheduler is resumed. */
  51. 51         /* 调度器暂停, 不能访问延迟和就绪列表, 需要放到pend列表里 */
  52. 52         listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
  53. 53     }
  54. 54
  55. 55     #if ( configNUMBER_OF_CORES == 1 )
  56. 56     {
  57. 57         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
  58. 58         {
  59. 59             /* Return true if the task removed from the event list has a higher
  60. 60              * priority than the calling task.  This allows the calling task to know if
  61. 61              * it should force a context switch now. */
  62. 62             /* 取出任务的优先级更高, 需要进行上下文切换 */
  63. 63             xReturn = pdTRUE;
  64. 64
  65. 65             /* Mark that a yield is pending in case the user is not using the
  66. 66              * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
  67. 67             xYieldPendings[ 0 ] = pdTRUE;
  68. 68         }
  69. 69         else
  70. 70         {
  71. 71             xReturn = pdFALSE;
  72. 72         }
  73. 73     }
  74. 74     #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
  75. 75
  76. 76     return xReturn;
  77. 77 }
复制代码
xTaskRemoveFromEventList 
  16~19都比较简单,这里就简单过一下,下一篇学习空闲任务究竟做了什么事情以及它调用的几个小接口。
  下篇再见。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册