FreeRTOS调度器挂起与解除
生活随笔
收集整理的這篇文章主要介紹了
FreeRTOS调度器挂起与解除
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
通過分析任務切換,我們知道任務切換的兩種方法:系統(tǒng)節(jié)拍器中斷、調用portYIELD產(chǎn)生PendSV中斷。
在系統(tǒng)節(jié)拍器中斷中,如果調度器被掛起,僅僅將調度器掛起時間加一(在解除掛起后需要補償這些節(jié)拍),并不會檢查是否有任務需要切換。
/* 系統(tǒng)節(jié)拍加一 */ BaseType_t xTaskIncrementTick(void) {BaseType_t xSwitchRequired = pdFALSE;/* 調度器沒有被掛起 */if(uxSchedulerSuspended == (UBaseType_t)pdFALSE){......}/* 調度器被掛起 */else{/* 掛起時間加一 */++uxPendedTicks;}/* 前面有程序因為各種原因,要求延遲到現(xiàn)在切換 */if(xYieldPending != pdFALSE){/* 請求切換任務,最終進入PendSV異常,是否切換上下文還是在于PendSV */xSwitchRequired = pdTRUE;}return xSwitchRequired; }在PendSV中斷中,如果調度器被掛起,則不進行上下文切換,通過xYieldPending將任務切換延遲到下一個節(jié)拍。
/* 任務切換上下文 */ void vTaskSwitchContext(void) {/* 調度器被掛起 */if(uxSchedulerSuspended != (UBaseType_t)pdFALSE){/* 等到下一次節(jié)拍的時候再切換上下文 */xYieldPending = pdTRUE;}/* 調度器沒有掛起 */else{......} }也就是說,只要將調度器掛起,就肯定不會進行任務切換。
?
?
掛起調度器非常簡單,只要讓uxSchedulerSuspended不等于pdFALSE(0)即可。調度器可以多次掛起,但是對應的也要進行多次解除掛起。
/* 掛起調度器 */ void vTaskSuspendAll(void) {/* 掛起層數(shù)加一 */++uxSchedulerSuspended; }當完全解除調度器掛起時,需要進行如下工作:
檢查在調度器掛起期間是否有任務進入就緒態(tài),有則要將其從掛起期間就緒任務列表中移除,重新掛接到就緒任務列表
更新下一個需要解除阻塞的任務,的解除時間
要對之前調度器掛起期間產(chǎn)生的節(jié)拍進行補償
對于延遲切換任務到下一個節(jié)拍的請求,在這里提供一次切換機會
/* 解除調度器掛起 */ BaseType_t xTaskResumeAll( void ) {TCB_t *pxTCB = NULL;BaseType_t xAlreadyYielded = pdFALSE;configASSERT(uxSchedulerSuspended);/* 進入臨界區(qū) */taskENTER_CRITICAL();{/* 調度器掛起層數(shù)減一 */--uxSchedulerSuspended;/* 調度器掛起完全解除 */if(uxSchedulerSuspended == (UBaseType_t)pdFALSE){/* 系統(tǒng)當前任務數(shù)大于0 */if(uxCurrentNumberOfTasks > (UBaseType_t)0U){/* 掛起時進入就緒的任務列表不為空 */while(listLIST_IS_EMPTY(&xPendingReadyList) == pdFALSE){/* 從掛起時進入就緒的任務列表中取出一個任務 */pxTCB = listGET_OWNER_OF_HEAD_ENTRY((&xPendingReadyList));/* 將任務從事件列表中移除 */(void)uxListRemove(&(pxTCB->xEventListItem));/* 將任務從狀態(tài)列表中移除 */(void)uxListRemove(&(pxTCB->xStateListItem));/* 將任務加入就緒任務列表 */prvAddTaskToReadyList(pxTCB);/* 如果任務優(yōu)先級高于當前任務優(yōu)先級,則請求在下一個節(jié)拍時切換 */if(pxTCB->uxPriority >= pxCurrentTCB->uxPriority){xYieldPending = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}/* 有任務在掛起期間就緒 */if(pxTCB != NULL){/* 更新下一個要解除阻塞的時間 */prvResetNextTaskUnblockTime();}{/* 調度器掛起時間 */UBaseType_t uxPendedCounts = uxPendedTicks;/* 調度器掛起時間大于1個節(jié)拍 */if(uxPendedCounts > (UBaseType_t)0U){/* 將所有節(jié)拍重新補上 */do{/* 節(jié)拍數(shù)加一,如果需要切換任務,則請求在下一個節(jié)拍時切換 */if(xTaskIncrementTick() != pdFALSE){xYieldPending = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}--uxPendedCounts;}while(uxPendedCounts > (UBaseType_t)0U);uxPendedTicks = 0;}else{mtCOVERAGE_TEST_MARKER();}}/* 原來請求在下一個節(jié)拍時切換的任務,在這里直接請求切換 */if(xYieldPending != pdFALSE){#if (configUSE_PREEMPTION != 0){/* 已經(jīng)切換過任務 */xAlreadyYielded = pdTRUE;}#endiftaskYIELD_IF_USING_PREEMPTION();}else{mtCOVERAGE_TEST_MARKER();}}}else{mtCOVERAGE_TEST_MARKER();}}/* 退出臨界區(qū) */taskEXIT_CRITICAL();/* 返回是否已經(jīng)切換過任務 */return xAlreadyYielded; }?
總結
以上是生活随笔為你收集整理的FreeRTOS调度器挂起与解除的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 结不起婚生不起娃的低欲望社会来了?这份自
- 下一篇: 不会用Photoshop抠图?Pytho