1. 程式人生 > >FreeRTOS一些知識筆記【1】

FreeRTOS一些知識筆記【1】

【FreeRTOS列表和列表項】
列表項有兩種,全功能版的列表項xLIST_ITEM和迷你版的列表項xMINI_LIST_ITEM
全功能版的列表項有  檢查完整性,列表項值,pnext,pprevious,TCB,pcontainer
迷你版的列表項有    檢查完整性,列表項值,pnext,pprevious
一個List中,ListEnd就是一個mini列表項
List排序通過ListItemValue來排序的




【任務建立詳解】
1.建立任務堆疊和任務TCB,實際是申請任務堆疊和TCB堆疊
2.初始化任務TCB必要的欄位
3.初始化任務堆疊
4.進入臨界區
5.當前任務數量增加1
6.更新任務就緒列表pxReadyTasksLists[priority],priority就是新建任務的
  優先順序,保證同一個優先順序的任務可以放在同一個列表下,且可以快速找到
7.更新當前正在執行的任務 TCB 指標 pxCurrentTCB(主要看優先順序)
8.退出臨界區
9.執行上下文切換




【任務排程器】
任務啟動和任務切換主要使用
SVC      系統服務函式,用於任務啟動
PendSV   可掛起系統呼叫,用於完成任務切換
SysTick  產生系統時鐘節拍,提供時間片


任務排程器
1.建立空閒任務
2.是否使能軟體定時器
3.關中斷
4.初始化滴答定時器,FPU,PendSV
5.獲取MSP初始值
6.使能中斷
7.使用匯編指令svc 0觸發SVC中斷引起SVC中斷
8.開啟第一個任務
9.以後的任務切換用PendSV中斷服務函式


【任務切換】
FreeRTOS有兩種方法觸發任務切換:
1.執行系統呼叫,比如普通任務可以使用taskYIELD()強制任務切換,中斷服務程式
中使用portYIELD_FROM_ISR()強制任務切換;
2.系統節拍時鐘中斷


對於Cortex-M3平臺,這兩種方法的實質是一樣的,都會使能一個PendSV中斷,在
PendSV中斷服務程式中,找到最高優先順序的就緒任務,然後讓這個任務獲得CPU運
行權,從而完成任務切換。


在PendSV中
1.使用PSP程序堆疊指標,將PC,LR,R12,R3~R0壓棧
2.開始使用MSP主堆疊指標
3.將R11~R4壓棧
4.進入臨界區
5.切換上下文,找到下一個要執行的任務,pxCurrentTCB指向下一個任務TCB
6.退出臨界區
7.獲取下一個任務TCB的堆疊地址,將R11~R4出棧
8.跟新PSP程序堆疊指標,使之指向任務堆疊
9.退出中斷,將PC,LR,R12,R3~R0出棧




【FreeRTOS佇列分析】
二進位制訊號量、計數訊號量、互斥量和遞迴互斥量都是使用佇列來實現的


二進位制訊號量其實是一個佇列項為1,大小為0的佇列,其本質是呼叫
uxMessageWaiting 來實現的。
獲取二進位制:對於二進位制訊號量和計數訊號量,可以簡化為三種情況:
第一,如果佇列不為空,佇列結構體成員 uxMessageWaiting 減1,判斷
是否有因入隊而阻塞的任務,有的話解除阻塞,然後返回成功資訊(pdPASS);
第二,如果佇列為空並且阻塞時間為0,則直接返回錯誤碼(errQUEUE_EMPTY),
表示佇列為空;
第三,如果佇列為空並且阻塞時間不為0,則任務會因為等待信
號量而進入阻塞狀態,任務會被掛接到延時列表中。


【FreeRTOS任務通知分析】
volatile uint32_t ulNotifiedValue;  
/*任務通知值*/    
volatile uint8_t ucNotifyState; 
/*任務通知狀態,標識任務是否在等待通知等*/  
任務通知的侷限性:只能有一個任務接收通知事件


【FreeRTOS系統延時分析】
相對延時函式其實是相對於呼叫vTaskDelay()開始計時的
絕對延時函式其實是保證任務按一定頻率週期性的阻塞和執行


如果要想正真精確週期性執行某個任務,可以使用系統節拍鉤子函式
vApplicationTickHook(),它在系統節拍中斷服務函式中被呼叫,因
此這個函式中的程式碼必須簡潔。


【FreeRTOS系統時鐘節拍分析】
系統節拍中斷服務程式會呼叫函式xTaskIncrementTick()來完成主要
工作,如果該函式返回值為真(不等於pdFALSE),說明處於就緒態任
務的優先順序比當前執行的任務優先順序高。這會觸發一次PendSV中斷,
進行上下文切換。


xTickCount+xTicksToDelay會被記錄到任務TCB中,隨著任務一起掛接
到延時列表。如果核心判斷出xTickCount+ xTicksToDelay溢位
(大於32位可以表示的最大值),就將當前任務掛接到列表指標
pxOverflowDelayedTaskList指向的列表中,否則就掛接到列表
指標pxDelayedTaskList指向的列表中。任務按照延時時間,順序
的插入到延時列表中。
所以當系統節拍中斷次數計數器xTickCount溢位時,必須將延時
列表指標pxDelayedTaskList和溢位延時列表指標pxOverflowDelayedTaskList
交換以便正確處理延時的任務。


【FreeRTOS空閒任務分析】
1.vTaskDelete(NULL),有任務刪除了自己,他的TCB和堆疊就交給空閒任務來釋放
2.鉤子函式


流程:
1.釋放自己刪自己的那個任務的記憶體
2.是否使用搶佔式核心,沒用的話就強行發起一次任務切換,保證最高優先順序任務能得到響應
3.使用搶佔式核心的話,就執行同優先順序的其他任務,不需要使用者自己強制任務切換了
4.使能鉤子函式的話,就呼叫鉤子函式
5.是否使能Tickless低功耗模式,使能的話就進入低功耗


【FreeRTOS臨界段】
由於在臨界段中要關中斷和開中斷,所以實際操作的是BASEPRI暫存器,
向暫存器BASEPRI寫入MAX,那麼優先順序低於MAX的中斷就會被遮蔽。


FreeRTOS有四個臨界段程式碼保護函式,兩個任務級,兩個中斷級
在臨界段程式碼保護中,優先順序低於configMAX_SYSCALL_INTERRUPT_PRIORITY(優先順序數一樣)
的中斷將得不到響應,所以,在中斷級臨界段段中,那個中斷函式的優先順序一定要低於
configMAX_SYSCALL_INTERRUPT_PRIORITY。


在F103的FreeRTOS例程中
#define configMAX_SYSCALL_INTERRUPT_PRIORITY
( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
configPRIO_BITS=4,configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY =5,
這樣一來,configMAX_SYSCALL_INTERRUPT_PRIORITY =80,那不是所有中斷都可以呼叫臨界段
了。