之前的阻塞延時實現
之前爲了實現任務阻塞延時,在任務控制塊TCB中添加了個成員xTicksToDelay
,當任務需要延時時就設置xTicksToDelay
,然後把該任務掛起,這裏掛起只是將uxTopReadyPriority
中對應的位清0(注意此時還不支持時間片,即同一優先級下只有一個任務,所以能直接清0,如果支持時間片還需判斷該優先級列表上是否還有其它節點即是否還有其它任務,有就不能清0),
並沒有把該任務從任務就緒列表中刪除,每次時基來臨時(SysTick中斷),就掃描各個任務的xTicksToDelay
,大於0就減一操作,然後判斷是否爲0,爲0表示延時時間到,再把該任務添加到任務就緒列表中(就是把uxTopReadyPriority
中對應的位置1)然後進行任務切換。缺點是每個時基都要掃描所有任務費時,優點是理解簡單。
任務延時列表原理
在 FreeRTOS 中, 還有任務延時列表,當任務需要延時時,先把任務掛起,這裏是先把任務從就緒列表中刪除,然後插入到延時列表中,將uxTopReadyPriority
中對應的位清0(注意此時還不支持時間片,即同一優先級下只有一個任務,所以能直接清0,如果支持時間片還需判斷該優先級列表上是否還有其它節點即是否還有其它任務,有就不能清0)
同時更新下一個任務的解鎖時間變量xNextTaskUnblockTime
的值。
xNextTaskUnblockTime
的值等於系統時基計數器的值 xTickCount
加上任務需要延時的值 xTicksToDelay
。 當系統時基計數器 xTickCount
的值與 xNextTaskUnblockTime
相等時,就表示有任務延時到期了,需要將該任務就緒。
任務延時列表表維護着一條雙向鏈表,每個節點代表了正在延時的任務,節點按照延時時間大小做升序排列。 當每次時基中斷(SysTick 中斷)來臨時, 就拿系統時基計數器的值 xTickCount
與下一個任務的解鎖時刻變量 xNextTaskUnblockTime
的值相比較, 如果相等, 則表示有任務延時到期, 需要將該任務就緒, 否則只是單純地更新系統時基計數器xTickCount
的值, 然後進行任務切換。
這樣就不用像之前那樣掃描所有任務判斷是否延時時間到達。