


版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、標(biāo)簽: freertos轉(zhuǎn):FreeRTOS任務(wù)管理分析轉(zhuǎn)自:是一個輕量級的rtos ,它目前實現(xiàn)了一個微內(nèi)核, 并且port到arm7, avr, pic18, coldfire 等眾多處理器上;目前已經(jīng)在rtos 的市場上占有不少的份額。它當(dāng)然不是一個與vxworks之類的rtos競爭的操作系統(tǒng),它的目標(biāo)在 于低性能小RAM的處理器上。整個系統(tǒng)只有3個文件,外加上port的和處理器相關(guān)的兩個文件,實現(xiàn)是很簡潔的。與ucosii不同,它是free的,ucosii不是free的,雖然它的代碼是公開的。FreeRTOS提供的功能包括:任務(wù)管理、時間管理、信號量、消息隊列、內(nèi)存管理。FreeRTO
2、S內(nèi)核支持優(yōu)先級調(diào)度算法,每個任務(wù)可根據(jù)重要程度的不同被賦予一定的優(yōu)先級,CPU總是讓處于就緒態(tài)的、優(yōu)先級最高的任務(wù)先運行。FreeRTOS內(nèi)核同時支持輪換調(diào)度算法,系統(tǒng)允許不同的任務(wù)使用相同的優(yōu)先級,在沒有更高優(yōu)先級任務(wù)就緒的情況下,同一優(yōu)先級的任務(wù)共享CPU的使用時間。這一點是和ucosii不同的。另外一點不同是freertos既可以配置為可搶占內(nèi)核也可以配置為不可搶占內(nèi)核。當(dāng)FreeRTOS被設(shè)置為可剝奪型內(nèi)核時,處于就緒態(tài)的高優(yōu)先級任務(wù)能剝奪低優(yōu)先級任務(wù)的CPU使用權(quán),這樣可保證系統(tǒng)滿足實時性的要求;當(dāng)FreeRTOS被設(shè)置為不可剝奪型內(nèi)核時,處于就緒態(tài)的高優(yōu)先級任務(wù)只有等當(dāng)前運行任務(wù)
3、主動釋放CPU的使用權(quán)后才能獲得運行,這樣可提高CPU的運行效率。這篇文章是以freertos版本的代碼為例子分析下它的任務(wù)管理方面的實現(xiàn)。時間關(guān)系可能沒有太多時間寫的很詳細(xì)了。1.鏈表管理freertos 里面的任務(wù)管理,queue,semaphore管理等都借助于雙向鏈表,它定義了個通用的數(shù)據(jù)結(jié)構(gòu)struct xLIST_ITEMportTickType xItemValue; To initialise the list the list end is insertedas the only list entry. */pxList-pxlndex = ( xListItem * ) &
4、( pxList-xListEnd );/* The list end value is the highest possible value in the list toensure it remains at the end of the list. */pxList- = portMAX_DELAY;/* The list end next and previous pointers point to itself so we knowwhen the list is empty. */pxList- = ( xListItem * ) &( pxList-xListEnd );pxLi
5、st- = ( xListItem * ) &( pxList-xListEnd );pxList-uxNumberOfltems = 0;把一個節(jié)點插入到鏈表尾部:void vListlnsertEnd( xList *pxList, xListltem *pxNewListItem )volatile xListltem * pxlndex;/* Insert a new list item into pxList, but rather than sort the list,makes the new list item the last item to be removed by a
6、call to pvListGetOwnerOfNextEntry. This means it has to be the item pointed to by the pxlndex member. */pxlndex = pxList-pxIndex;pxNewListltem-pxNext = pxIndex-pxNext;pxNewListltem-pxPrevious = pxList-pxIndex;pxlndex-pxNext-pxPrevious = ( volatile xListltem * ) pxNewListltem; pxIndex-pxNext = ( vola
7、tile xListltem * ) pxNewListltem;pxList-pxIndex = ( volatile xListltem * ) pxNewListltem;/* Remember which list the item is in. */pxNewListltem-pvContainer = ( void * ) pxList;(pxList-uxNumberOfltems )+;這些就不多說了。2.任務(wù)控制塊typedef struct tskTaskControlBlockfreertos將任務(wù)根據(jù)他們的狀態(tài)分成幾個鏈表。所有就緒狀態(tài)的任務(wù)根據(jù)任務(wù)優(yōu)先級加到對應(yīng)的就緒
8、鏈表中。系統(tǒng)為每個優(yōu)先級定義了一個xList。如下:static xList pxReadyTasksLists configMAX_PRIORITIES ;/* Prioritised ready tasks. */此外,所有延時的任務(wù)參加到兩個延時鏈表之一。static xList xDelayedTaskList1;static xList xDelayedTaskList2;還定義了兩個指向延時鏈表的指針:static xList * volatile pxDelayedTaskList;static xList * volatile pxOverflowDelayedTaskList
9、;freertos弄岀兩個延時鏈表是因為它的延時任務(wù)管理的需要。freertos 根據(jù)任務(wù)延時時間的長短按序?qū)⑷蝿?wù)插入這兩個鏈表之一。在插入前先把任務(wù)將要延時的xTicksToDelay數(shù)加上系統(tǒng)當(dāng)前tick數(shù),這樣得到了一個任務(wù)延時due time 到期時間的絕對數(shù)值。但是有可能這個相加操作會導(dǎo)致溢出,如果溢出那么參加到 pxOverflowDelayedTaskList 指向的那個鏈表,否那么參加pxDelayedTaskList指向的鏈表。freertos 還定義了個 pending鏈表:static xList xPendingReadyList;這個鏈表用在調(diào)度器被lock 就是禁止
10、調(diào)度了的時期,如果一個任務(wù)從非就緒狀態(tài)變?yōu)榫途w狀態(tài),它不直接加到就緒鏈表中,而是加到這個pending鏈表中。等調(diào)度器重新啟動unlock的時候再檢查這個鏈表,把里面的任務(wù)加到就緒鏈表中static volatile xList xTasksWaitingTermination;/* Tasks that have been deleted - but the theirmemory not yet freed. */static volatile unsigned portBASE_TYPE uxTasksDeleted = unsigned portBASE_TYPE 0;一個任務(wù)被刪除的
11、時候參加到xTasksWaitingTermination鏈表中,uxTasksDeleted 跟中系統(tǒng)中有多少任務(wù)被刪除即加到xTasksWaitingTermination鏈表的任務(wù)數(shù)目.static xList xSuspendedTaskList;/* Tasks that arecurrently suspended. */這個鏈表記錄著所有被 xTaskSuspend掛起的任務(wù),注意這不是那些等待信號量的任務(wù)。static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks;記錄了當(dāng)前系統(tǒng)任務(wù)的數(shù)目;記錄當(dāng)前系統(tǒng)中處于就緒狀
12、態(tài)的最高優(yōu)先級。;表示當(dāng)前調(diào)度器是否在運行,也即內(nèi)核是否啟動了static volatile unsigned portBASE_TYPE uxTopReadyPrioritystatic volatile signed portBASE_TYPE xSchedulerRunning4.任務(wù)管理freertos 與ucosii不同,它的任務(wù)控制塊并不是靜態(tài)分配的,而是在創(chuàng)立任務(wù)的時候動態(tài)分配。另外,freertos的優(yōu)先級是優(yōu)先級數(shù)越大優(yōu)先級越高,和ucosii正好相反。任務(wù)控制塊中也沒有任務(wù)狀態(tài)的成員變量,這是因為freertos中的任務(wù)總是根據(jù)他們的狀態(tài)連入對應(yīng)的鏈表,沒有必要在任務(wù)控制塊
13、中維護(hù)一個狀態(tài)。此外freertos對任務(wù)的數(shù)量沒有限制,而且同一個優(yōu)先級可以有多個任務(wù)。先看任務(wù)創(chuàng)立:*參數(shù):pvTaskCode- 任務(wù)函數(shù)名稱* pcName-任務(wù)名字,可選*ucStackDepth- 任務(wù)堆棧的深度,即大小* pvParamenters-參數(shù),即傳給任務(wù)函數(shù)的參數(shù),所有的任務(wù)函數(shù)原型是void task (void *pvParameters)* uxPriority任務(wù)優(yōu)先級* pxCreatedTask 可選,通過它返回被創(chuàng)立任務(wù)的tcb*/signed portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, cons
14、t signed portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask )signed portBASE_TYPE xReturn;tskTCB * pxNewTCB;#if ( configUSE_TRACE_FACILITY = 1 )static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static
15、 is deliberate - this is guarded beforeuse. */#endif/*動態(tài)分配tcb和任務(wù)堆棧*/ pxNewTCB = prvAllocateTCBAndStack( usStackDepth );/* 如果分配成功的話 */if( pxNewTCB != NULL )portSTACK_TYPE *pxTopOfStack;/* 初始化 tcb*/prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority );/* 計算堆棧的頂 */#if portSTACK_GROWTH pxStack + ( u
16、sStackDepth - 1 );#elsepxTopOfStack = pxNewTCB-pxStack;#endif/* 初始化任務(wù)堆棧,并將返回地址保存在 tcb 中的 pxTopOfStack 變量 */ pxNewTCB-pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pvTaskCode, pvParameters );/* 關(guān)中斷 */portENTER_CRITICAL(); /* 更新系統(tǒng)的任務(wù)數(shù) */uxCurrentNumberOfTasks+;if( uxCurrentNumberOfTasks = ( unsi
17、gned portBASE_TYPE ) 1 )/* 如果這是系統(tǒng)中第一個任務(wù),那么把它設(shè)為當(dāng)前任務(wù) */ pxCurrentTCB = pxNewTCB;實際*/* 如果這是系統(tǒng)中的第一個任務(wù), 那也就意味著內(nèi)核剛準(zhǔn)備啟動,上這第一個任務(wù)一定是 idle 任務(wù),這個時候我們要做一些系統(tǒng)初始化,即初始化那些全局鏈表 prvInitialiseTaskLists();else /* 如果內(nèi)核還沒有運行,那么把當(dāng)前任務(wù)設(shè)成已經(jīng)創(chuàng)立的任務(wù)中優(yōu)先級 最高的那個 , 將來內(nèi)核一旦運行,調(diào)度器會馬上選擇它運行 */if( xSchedulerRunning = pdFALSE )if( pxCurrent
18、TCB-uxPriority uxPriority uxTopUsedPriority )uxTopUsedPriority = pxNewTCB-uxPriority;#if ( configUSE_TRACE_FACILITY = 1 )/* Add a counter into the TCB for tracing only. */ pxNewTCB-uxTCBNumber = uxTaskNumber; uxTaskNumber+;#endif/* 把新創(chuàng)立的任務(wù)加到就緒鏈表 */ prvAddTaskToReadyQueue( pxNewTCB );xReturn = pdPASS
19、;traceTASK_CREATE( pxNewTCB );portEXIT_CRITICAL();/* 如果分配內(nèi)存失敗,我們返回錯誤 */elsexReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;traceTASK_CREATE_FAILED( pxNewTCB ); if( xReturn = pdPASS )if( ( void * ) pxCreatedTask != NULL )/* 將新創(chuàng)立任務(wù)的 tcb 返回給調(diào)用者*pxCreatedTask = ( xTaskHandle ) pxNewTCB;/* 如果調(diào)度器已經(jīng)運行 */if
20、( xSchedulerRunning != pdFALSE )/* 如果新創(chuàng)立的任務(wù)的優(yōu)先級高于當(dāng)前正在運行的任務(wù),那么調(diào)度 */if( pxCurrentTCB-uxPriority pxStack = ( portSTACK_TYPE * ) pvPortMalloc( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) );if( pxNewTCB-pxStack = NULL )/* Could not allocate the stack.Delete the allocated TCB. */vPortFree( pxNew
21、TCB );pxNewTCB = NULL;else/* Just to help debugging. */memset( pxNewTCB-pxStack, tskSTACK_FILL_BYTE, usStackDepth sizeof( portSTACK_TYPE ) );return pxNewTCB;再看任務(wù)刪除。freertos 的任務(wù)刪除分兩步完成,第一步在vTaskDelete中完成,F(xiàn)reeRTOS先把要刪除的任務(wù)從就緒任務(wù)鏈表和事件等待鏈表中刪除, 然后把此任務(wù)添加到任務(wù)刪除鏈表 (即那個 xTasksWaitingTermination ),假設(shè)刪除的任務(wù)是當(dāng)前運行任務(wù)
22、, 系統(tǒng)就執(zhí)行任務(wù)調(diào)度函數(shù) 第 2 步那么是在 idle 任務(wù)中完成, idle 任務(wù)運行時,檢查 xTasksWaitingTermination 鏈表,如果有任務(wù)在這個表上,釋放該任務(wù)占用 的內(nèi)存空間,并把該任務(wù)從任務(wù)刪除鏈表中刪除。/* 參數(shù): pxTaskToDelete 是一個指向被刪除任務(wù)的句柄,這里其實就是等價于任務(wù)控制塊*如果這個句柄=NULL那么表示要刪除當(dāng)前任務(wù)*/void vTaskDelete( xTaskHandle pxTaskToDelete )tskTCB *pxTCB;taskENTER_CRITICAL();/* 如果刪除的是當(dāng)前任務(wù),那么刪除完成后需要進(jìn)行
23、調(diào)度 */if( pxTaskToDelete = pxCurrentTCB )pxTaskToDelete = NULL;/* 通過傳進(jìn)來的任務(wù)句柄得到對應(yīng)的 tcb*/pxTCB = prvGetTCBFromHandle( pxTaskToDelete );traceTASK_DELETE( pxTCB );/* 把任務(wù)從就緒鏈表或者延時鏈表或者掛起鏈表中刪除 */vListRemove( &( pxTCB-xGenericListItem ) );/* 判斷任務(wù)是否在等待事件 (semaphore 消息隊列等 ) */if( pxTCB- )*/( void ) pvParameter
24、s;for( ; )/* See if any tasks have been deleted. */prvCheckTasksWaitingTermination();這里 prvCheckTasksWaitingTermination() 就是干這第 2 步的工作:每次調(diào)用它刪除一個任務(wù) static void prvCheckTasksWaitingTermination( void )#if ( INCLUDE_vTaskDelete = 1 )portBASE_TYPE xListIsEmpty;/* ucTasksDeleted is used to prevent vTaskSu
25、spendAll() being calledtoo often in the idle task. */if( uxTasksDeleted ( unsigned portBASE_TYPE ) 0 ) If this was the case then theremoved task will have been added to the xPendingReadyList.Once thescheduler has been resumed it is safe to move all the pending readytasks from this list into their ap
26、propriate ready list. */portENTER_CRITICAL();*/#if configUSE_PREEMPTION = 1xYieldRequired = pdTRUE;#endif if( ( xYieldRequired = pdTRUE ) | ( xMissedYield = pdTRUE )xAlreadyYielded = pdTRUE;xMissedYield = pdFALSE;taskYIELD();portEXIT_CRITICAL();return xAlreadyYielded;任務(wù)掛起與喚醒freertos 的任務(wù)關(guān)起與ucosii也不大一
27、樣。它把所有掛起的任務(wù)加到xSuspendedTaskList中,而且一旦調(diào)用 vTaskSuspend()函數(shù)掛起一個任務(wù),該任務(wù)就將從所有它原先連入的鏈表中刪除(包括就緒表,延時表和它等待的事件鏈表),也就是說,和ucosii不同,一旦一個任務(wù)被掛起,它將取消先前它的延時和對事件的等待。ucosii中是不同的,在 ucosii里面一個任務(wù)被掛起僅僅是把任務(wù)的狀態(tài)或上一個OS_STAT_SUSPE并從就緒表中刪除,如果先前這個任務(wù)正在等待某事件,那么并不取消等待。*/if( pxTaskToSuspend = pxCurrentTCB )pxTaskToSuspend = NULL;/* 得
28、到對應(yīng)任務(wù) tcb */pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );traceTASK_SUSPEND( pxTaskToSuspend );/* 把任務(wù)從就緒表或者延時鏈表中刪除 */那么取消等待vListRemove( &( pxTCB-xGenericListItem ) );/* 如 果 任 務(wù) 也 在 等 待 某 事 件*/if( pxTCB- )vListRemove( &( pxTCB-xEventListItem ) );*/pxTCB = ( tskTCB * ) pxTaskToResume;/* The parameter
29、 cannot be NULL as it is impossible to resume thecurrently executing task. */if( pxTCB != NULL )taskENTER_CRITICAL();if( prvIsTaskSuspended( pxTCB ) = pdTRUE )traceTASK_RESUME( pxTCB );/* As we are in a critical section we can access the ready lists even if the scheduler is suspended. */ vListRemove
30、( &( pxTCB-xGenericListltem );prvAddTaskToReadyQueue( pxTCB );/* We may have just resumed a higher priority task. */if( pxTCB-uxPriority = pxCurrentTCB-uxPriority )/* This yield may not cause the task just resumed to run, butwill leave the lists in the correct state for the next yield. */taskYIELD()
31、;taskEXIT_CRITICAL();任務(wù)調(diào)度freertos 支持多個任務(wù)具有相同的優(yōu)先級,因此,當(dāng)它被配置為可搶占內(nèi)核時,調(diào)度算法既支持基于優(yōu)先級的調(diào)度,也支持時間片輪流調(diào)度。任何時候調(diào)度器運行時它都選擇處于就緒狀態(tài)下的優(yōu)先級最高的那個任務(wù);如果有多個任務(wù)處于同一優(yōu)先級,那么freertos 每個時鐘節(jié)拍的中斷效勞程序中,將對這些任務(wù)應(yīng)用換調(diào)度算法*輪流執(zhí)行這些任務(wù)。系統(tǒng)用uxTopReadyPriority全局變量記錄當(dāng)前處于就緒態(tài)的任務(wù)的最高優(yōu)先級。調(diào)度的時候就根據(jù)這個uxTopReadyPriority 直接找到就緒鏈表中 pxReadyTasksLists uxTopReady
32、Priority 的任務(wù),進(jìn)行運行。一個任務(wù)可以通過調(diào)用taskYIELD()讓出cpu,從而調(diào)度令一個任務(wù)運行。它的實現(xiàn)如下:#define taskYIELD()portYIELD()而portYIELD()是一個體系結(jié)構(gòu)相關(guān)的函數(shù),對于不同的mcu需要實現(xiàn)這么一個函數(shù)完成調(diào)度。我拿atmel的atmega323 mcu為例子,說明下具體實現(xiàn)。/* Kernel utilities. */extern void vPortYield( void ) _attribute_ ( ( naked );vPortYield()#define portYIELD() /* can use a na
33、ked attribute.*/void vPortYield( void ) _attribute_ ( ( naked ) );void vPortYield( void )portSAVE_CONTEXT();vTaskSwitchContext();portRESTORE_CONTEXT();asm volatile ( ret );portYIELD() 就 是 vportYield(), 它 保 存 現(xiàn) 場 , 然 后 調(diào) 用 vTaskSwitchContext ( ) 這 個 函 數(shù) 選 擇 下 一 個 運 行 的 任 務(wù) , 然 后portRESTORE_CONTEXT完成任務(wù)切換。void vTaskSwitchContext( void )traceTASK_SWITCHED_OUT();if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )/* 當(dāng)前調(diào)度器被禁止,因此不允許調(diào)度,設(shè) xMissedYield=TRUE*/xMissedYield = pdTRUE;return; taskCHECK_FOR_STACK_OVERFLOW();/* 找到包含有就緒任務(wù)的最高優(yōu)先級隊列 */while( listLIST_IS_EMPTY( &( pxReadyTas
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 課題開題報告:初中思政課素養(yǎng)導(dǎo)向型課程文化建設(shè)研究
- 課題開題報告:產(chǎn)教協(xié)同推進(jìn)教師專業(yè)發(fā)展研究
- 天然植物染眉膏行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報告
- 二零二五年度公司員工加班費及休息日補償補充協(xié)議
- 二零二五年度戀愛雙方旅游及休閑活動安排合同
- 中藥材飲片加工工廠行業(yè)跨境出海戰(zhàn)略研究報告
- 2025年度股東協(xié)議補充協(xié)議:應(yīng)對氣候變化的環(huán)境保護(hù)責(zé)任約定
- 上衣服裝企業(yè)數(shù)字化轉(zhuǎn)型與智慧升級戰(zhàn)略研究報告
- 二零二五年度車輛過戶手續(xù)辦理及責(zé)任界定協(xié)議
- 資源綜合利用質(zhì)量評估服務(wù)企業(yè)數(shù)字化轉(zhuǎn)型與智慧升級戰(zhàn)略研究報告
- 2025中鐵集裝箱運輸有限責(zé)任公司招聘46人(京外地區(qū)崗位)筆試參考題庫附帶答案詳解
- 中國農(nóng)業(yè)大學(xué)人文與發(fā)展學(xué)院管理服務(wù)崗位招聘筆試真題2023
- 2023-2024 中國滑雪產(chǎn)業(yè)白皮書
- 風(fēng)電場觸電急救培訓(xùn)課件
- 二年級下冊數(shù)學(xué)課件-1.3 分草莓 北師大版(共14張PPT)
- 2022年中小學(xué)心理健康教育指導(dǎo)綱要
- 中國紅十字會救護(hù)員培訓(xùn)理論考試試卷 (1)附答案
- 高架橋梁混凝土工程專項施工方案
- 銀行案件風(fēng)險排查實施細(xì)則
- 亞馬遜品牌授權(quán)書(英文模板)
- 10級空乘《形體訓(xùn)練3》課程標(biāo)準(zhǔn)(共14頁)
評論
0/150
提交評論