#版本信息: NAME="openEuler"VERSION="22.03 (LTS-SP4)" #網卡信息: cat /etc/sysconfig/network-scripts/ifcfg-enp125s0f1TYPE=EthernetPROXY_METHOD=noneBROWSER_ONLY= ...
4.2.14 退出阻塞--xTaskAbortDelay
介面:
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
形參1:xTask ,想要退出阻塞態的任務;
返回:pdPASS:退出成功;pdFAIL:退出失敗。
1 BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) 2 { 3 TCB_t * pxTCB = xTask; 4 BaseType_t xReturn; 5 6 configASSERT( pxTCB ); 7 8 vTaskSuspendAll(); 9 { 10 /* A task can only be prematurely removed from the Blocked state if 11 * it is actually in the Blocked state. */ 12 /* 任務只有真的在阻塞態才能提前移出阻塞態 */ 13 if( eTaskGetState( xTask ) == eBlocked ) 14 { 15 xReturn = pdPASS; 16 17 /* Remove the reference to the task from the blocked list. An 18 * interrupt won't touch the xStateListItem because the 19 * scheduler is suspended. */ 20 ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); 21 22 /* Is the task waiting on an event also? If so remove it from 23 * the event list too. Interrupts can touch the event list item, 24 * even though the scheduler is suspended, so a critical section 25 * is used. */ 26 /* 如果任務在等待事件, 則移出事件列表, 因為調度器暫停時, 中斷仍 27 * 能訪問事件列表, 所以需要進入臨界區 */ 28 taskENTER_CRITICAL(); 29 { 30 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) 31 { 32 ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); 33 34 /* This lets the task know it was forcibly removed from the 35 * blocked state so it should not re-evaluate its block time and 36 * then block again. */ 37 /* 讓任務知道是被強制移出阻塞態的, 防止被重新計算阻塞時間再次進入 38 * 阻塞態 */ 39 pxTCB->ucDelayAborted = ( uint8_t ) pdTRUE; 40 } 41 else 42 { 43 mtCOVERAGE_TEST_MARKER(); 44 } 45 } 46 taskEXIT_CRITICAL(); 47 48 /* Place the unblocked task into the appropriate ready list. */ 49 prvAddTaskToReadyList( pxTCB ); 50 51 /* A task being unblocked cannot cause an immediate context 52 * switch if preemption is turned off. */ 53 #if ( configUSE_PREEMPTION == 1 ) 54 { 55 #if ( configNUMBER_OF_CORES == 1 ) 56 { 57 /* Preemption is on, but a context switch should only be 58 * performed if the unblocked task has a priority that is 59 * higher than the currently executing task. */ 60 /* 比當前任務優先順序高, 等調度器運行後, 需要進行yield */ 61 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) 62 { 63 /* Pend the yield to be performed when the scheduler 64 * is unsuspended. */ 65 xYieldPendings[ 0 ] = pdTRUE; 66 } 67 else 68 { 69 mtCOVERAGE_TEST_MARKER(); 70 } 71 } 72 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ 73 } 74 #endif /* #if ( configUSE_PREEMPTION == 1 ) */ 75 } 76 else 77 { 78 xReturn = pdFAIL; 79 } 80 } 81 ( void ) xTaskResumeAll(); 82 83 return xReturn; 84 }xTaskAbortDelay
這個介面主要就是強制將在阻塞態的任務變成就緒態。
4.2.15 系統滴答時鐘處理--xTaskIncrementTick
介面:
BaseType_t xTaskIncrementTick( void )
返回:pdPASS:需要切換上下文;pdFAIL:不需要切換上下文。
介面代碼如下:
1 BaseType_t xTaskIncrementTick( void ) 2 { 3 TCB_t * pxTCB; 4 TickType_t xItemValue; 5 BaseType_t xSwitchRequired = pdFALSE; 6 7 /* Tick increment should occur on every kernel timer event. Core 0 has the 8 * responsibility to increment the tick, or increment the pended ticks if the 9 * scheduler is suspended. If pended ticks is greater than zero, the core that 10 * calls xTaskResumeAll has the responsibility to increment the tick. */ 11 if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) 12 { 13 /* Minor optimisation. The tick count cannot change in this 14 * block. */ 15 const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; 16 17 /* Increment the RTOS tick, switching the delayed and overflowed 18 * delayed lists if it wraps to 0. */ 19 xTickCount = xConstTickCount; 20 21 /* tick溢出了, 交換下delay列表 */ 22 if( xConstTickCount == ( TickType_t ) 0U ) 23 { 24 taskSWITCH_DELAYED_LISTS(); 25 } 26 else 27 { 28 mtCOVERAGE_TEST_MARKER(); 29 } 30 31 /* See if this tick has made a timeout expire. Tasks are stored in 32 * the queue in the order of their wake time - meaning once one task 33 * has been found whose block time has not expired there is no need to 34 * look any further down the list. */ 35 /* 因為delay列表的項是按喚醒時間從小到大排序的, 所以遍歷過程中一旦發現 36 * 任務喚醒時間沒到, 就可以停止了 */ 37 if( xConstTickCount >= xNextTaskUnblockTime ) 38 { 39 for( ; ; ) 40 { 41 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) 42 { 43 /* The delayed list is empty. Set xNextTaskUnblockTime 44 * to the maximum possible value so it is extremely 45 * unlikely that the 46 * if( xTickCount >= xNextTaskUnblockTime ) test will pass 47 * next time through. */ 48 xNextTaskUnblockTime = portMAX_DELAY; 49 break; 50 } 51 else 52 { 53 /* The delayed list is not empty, get the value of the 54 * item at the head of the delayed list. This is the time 55 * at which the task at the head of the delayed list must 56 * be removed from the Blocked state. */ 57 /* MISRA Ref 11.5.3 [Void pointer assignment] */ 58 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 59 /* coverity[misra_c_2012_rule_11_5_violation] */ 60 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); 61 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) ); 62 63 if( xConstTickCount < xItemValue ) 64 { 65 /* It is not time to unblock this item yet, but the 66 * item value is the time at which the task at the head 67 * of the blocked list must be removed from the Blocked 68 * state - so record the item value in 69 * xNextTaskUnblockTime. */ 70 /* 這個任務未到喚醒時間, 但因為前面的都移出了, 所以這一定 71 * 是下次最近喚醒的時間, 記錄下來 */ 72 xNextTaskUnblockTime = xItemValue; 73 break; 74 } 75 else 76 { 77 mtCOVERAGE_TEST_MARKER(); 78 } 79 80 /* It is time to remove the item from the Blocked state. */ 81 listREMOVE_ITEM( &( pxTCB->xStateListItem ) ); 82 83 /* Is the task waiting on an event also? If so remove 84 * it from the event list. */ 85 /* 等待事件的話, 移出事件列表 */ 86 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) 87 { 88 listREMOVE_ITEM( &( pxTCB->xEventListItem ) ); 89 } 90 else 91 { 92 mtCOVERAGE_TEST_MARKER(); 93 } 94 95 /* Place the unblocked task into the appropriate ready 96 * list. */ 97 prvAddTaskToReadyList( pxTCB ); 98 99 /* A task being unblocked cannot cause an immediate 100 * context switch if preemption is turned off. */ 101 #if ( configUSE_PREEMPTION == 1 ) 102 { 103 #if ( configNUMBER_OF_CORES == 1 ) 104 { 105 /* Preemption is on, but a context switch should 106 * only be performed if the unblocked task's 107 * priority is higher than the currently executing 108 * task. 109 * The case of equal priority tasks sharing 110 * processing time (which happens when both 111 * preemption and time slicing are on) is 112 * handled below.*/ 113 /* 移出的任務優先順序比當前運行的任務高, 需要上下文切換 */ 114 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) 115 { 116 xSwitchRequired = pdTRUE; 117 } 118 else 119 { 120 mtCOVERAGE_TEST_MARKER(); 121 } 122 } 123 #endif /* #if( configNUMBER_OF_CORES == 1 ) */ 124 } 125 #endif /* #if ( configUSE_PREEMPTION == 1 ) */ 126 } 127 } 128 } 129 130 /* Tasks of equal priority to the currently running task will share 131 * processing time (time slice) if preemption is on, and the application 132 * writer has not explicitly turned time slicing off. */ 133 /* 相同優先順序的任務用時間片運行, 每個時間片長是一個tick. 這裡不用管更高 134 * 優先順序的任務是否喚醒, 一是上面已經判斷過了, 二是只是需要知道是否要上 135 * 下文切換, 這樣判斷就足夠了, 在上下文切換的時候自然會選擇合適的任務運行 */ 136 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) 137 { 138 #if ( configNUMBER_OF_CORES == 1 ) 139 { 140 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U ) 141 { 142 xSwitchRequired = pdTRUE; 143 } 144 else 145 { 146 mtCOVERAGE_TEST_MARKER(); 147 } 148 } 149 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ 150 } 151 #endif /* #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ 152 153 #if ( configUSE_TICK_HOOK == 1 ) 154 { 155 /* Guard against the tick hook being called when the pended tick 156 * count is being unwound (when the scheduler is being unlocked). */ 157 if( xPendedTicks == ( TickType_t ) 0 ) 158 { 159 vApplicationTickHook(); 160 } 161 else 162 { 163 mtCOVERAGE_TEST_MARKER(); 164 } 165 } 166 #endif /* configUSE_TICK_HOOK */ 167 168 #if ( configUSE_PREEMPTION == 1 ) 169 { 170 #if ( configNUMBER_OF_CORES == 1 ) 171 { 172 /* For single core the core ID is always 0. */ 173 if( xYieldPendings[ 0 ] != pdFALSE ) 174 { 175 xSwitchRequired = pdTRUE; 176 } 177 else 178 { 179 mtCOVERAGE_TEST_MARKER(); 180 } 181 } 182 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ 183 } 184 #endif /* #if ( configUSE_PREEMPTION == 1 ) */ 185 } 186 else 187 { 188 /* 調度器處於暫停中, 在xTaskResumeAll介面中檢查xPendedTicks的值, 189 * 並調用本介面處理tick值. */ 190 xPendedTicks += 1U; 191 192 /* The tick hook gets called at regular intervals, even if the 193 * scheduler is locked. */ 194 #if ( configUSE_TICK_HOOK == 1 ) 195 { 196 vApplicationTickHook(); 197 } 198 #endif 199 } 200 201 return xSwitchRequired; 202 }xTaskIncrementTick
介面比較複雜,流程圖就不貼了,太長。這個介面簡單來講就是如果調度器未停止,就檢查每個阻塞的任務是否到了等待時間,包括本身延遲的時間和等待事件的超時時間,並加入到就緒列表中。
4.2.16 切換上下文--vTaskSwitchContext
切換上下文,主要作用是挑選出需要切換過去的任務。
介面:
void vTaskSwitchContext( void )
介面代碼如下:
1 void vTaskSwitchContext( void ) 2 { 3 if( uxSchedulerSuspended != ( UBaseType_t ) 0U ) 4 { 5 /* The scheduler is currently suspended - do not allow a context 6 * switch. */ 7 /* 調度器暫停時, 不允許上下文切換 */ 8 xYieldPendings[ 0 ] = pdTRUE; 9 } 10 else 11 { 12 xYieldPendings[ 0 ] = pdFALSE; 13 14 /* Check for stack overflow, if configured. */ 15 /* 就是檢查當前棧的位置有沒有超過棧頂位置 */ 16 taskCHECK_FOR_STACK_OVERFLOW(); 17 18 /* Before the currently running task is switched out, save its errno. */ 19 #if ( configUSE_POSIX_ERRNO == 1 ) 20 { 21 pxCurrentTCB->iTaskErrno = FreeRTOS_errno; 22 } 23 #endif 24 25 /* Select a new task to run using either the generic C or port 26 * optimised asm code. */ 27 /* MISRA Ref 11.5.3 [Void pointer assignment] */ 28 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 29 /* coverity[misra_c_2012_rule_11_5_violation] */ 30 /* 選擇就緒列表中優先順序最高的任務 */ 31 taskSELECT_HIGHEST_PRIORITY_TASK(); 32 33 /* Macro to inject port specific behaviour immediately after 34 * switching tasks, such as setting an end of stack watchpoint 35 * or reconfiguring the MPU. */ 36 portTASK_SWITCH_HOOK( pxCurrentTCB ); 37 38 /* After the new task is switched in, update the global errno. */ 39 #if ( configUSE_POSIX_ERRNO == 1 ) 40 { 41 FreeRTOS_errno = pxCurrentTCB->iTaskErrno; 42 } 43 #endif 44 } 45 }vTaskSwitchContext
最核心的就是“taskSELECT_HIGHEST_PRIORITY_TASK();”調用。
4.2.17 加入到事件列表--vTaskPlaceOnEventList
把當前任務放到事件列表中,主要用於隊列的實現。
介面:
void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
形參1:pxEventList,事件列表;
形參2:xTicksToWait ,最長等待時間。
介面代碼如下:
1 void vTaskPlaceOnEventList( List_t * const pxEventList, 2 const TickType_t xTicksToWait ) 3 { 4 configASSERT( pxEventList ); 5 6 /* THIS FUNCTION MUST BE CALLED WITH THE 7 * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ 8 9 /* Place the event list item of the TCB in the appropriate event list. 10 * This is placed in the list in priority order so the highest priority task 11 * is the first to be woken by the event. 12 * 13 * Note: Lists are sorted in ascending order by ListItem_t.xItemValue. 14 * Normally, the xItemValue of a TCB's ListItem_t members is: 15 * xItemValue = ( configMAX_PRIORITIES - uxPriority ) 16 * Therefore, the event list is sorted in descending priority order. 17 * 18 * The queue that contains the event list is locked, preventing 19 * simultaneous access from interrupts. */ 20 /* 將當前任務加入到事件列表, 列表是按升序存放的, 而一般情況下, 任務的 21 * xEventListItem的值是xItemValue=(configMAX_PRIORITIES-uxPriority), 22 * 所以事件列表是按優先順序降序排列的 */ 23 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); 24 25 /* 還需要放到延遲列表中, 用於最大延遲時間的喚醒 */ 26 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); 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 ,最長等待時間。
介面代碼如下:
1 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, 2 const TickType_t xItemValue, 3 const TickType_t xTicksToWait ) 4 { 5 configASSERT( pxEventList ); 6 7 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by 8 * the event groups implementation. */ 9 configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); 10 11 /* Store the item value in the event list item. It is safe to access the 12 * event list item here as interrupts won't access the event list item of a 13 * task that is not in the Blocked state. */ 14 /* 中斷只會訪問處於Blocked態的事件列表項, 這裡當前任務明顯還未進入Blocked態 */ 15 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); 16 17 /* Place the event list item of the TCB at the end of the appropriate event 18 * list. It is safe to access the event list here because it is part of an 19 * event group implementation - and interrupts don't access event groups 20 * directly (instead they access them indirectly by pending function calls to 21 * the task level). */ 22 /* 主要是用於事件組的實現, 中斷不會直接訪問. 無序存放, 所以直接放在最後 */ 23 listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) ); 24 25 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); 26 }vTaskPlaceOnUnorderedEventList
4.2.19 移出事件列表--xTaskRemoveFromEventList
將當前任務從事件列表中移出,主要用於隊列的實現。
介面:
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
形參1:pxEventList,事件列表;
返回值:pdTRUE:需要進行上下文切換;pdFALSE:不需要。
介面代碼如下: