嵌入式操作系統(tǒng)515_第1頁
嵌入式操作系統(tǒng)515_第2頁
嵌入式操作系統(tǒng)515_第3頁
嵌入式操作系統(tǒng)515_第4頁
嵌入式操作系統(tǒng)515_第5頁
已閱讀5頁,還剩127頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、嵌入式操作系統(tǒng)嵌入式操作系統(tǒng)FREERTOS何杰 操作系統(tǒng)操作系統(tǒng)的作用屏蔽硬件,提供軟件接口,調(diào)度應(yīng)用程序,實現(xiàn)資源分配提供硬件驅(qū)動接口,與應(yīng)用無關(guān)提供用戶操作接口(桌面)通用操作系統(tǒng)通常用于PC機、服務(wù)器等大中小型計算機操作系統(tǒng)功能的全集,極其復雜實時性不強Windows NT/XP、Linux、Unix、Mac、Solaris用過Windows的都知道,常?!八馈钡暮茈y看,連蓋茨也不放過!想象一下這樣的系統(tǒng)用在航空器或醫(yī)療設(shè)備上。嵌入式操作系統(tǒng)通常用于嵌入式系統(tǒng)通用操作系統(tǒng)功能的子集,功能復雜度降低實時性較強嵌入式Linux,Windows CE/Mobile,uC/OS,VxWorks

2、等等與桌面操作系統(tǒng)的比較嵌入式操作系統(tǒng)的分類Embedded operating system structure怎么使用一個嵌入式操作系統(tǒng)1、了解基本原理2、了解提供的APIFreeRTOS小型嵌入式系統(tǒng)FreeRTOS是一個迷你操作系統(tǒng)內(nèi)核的小型嵌入式系統(tǒng)。由于RTOS需占用一定的系統(tǒng)資源(尤其是RAM資源),只有C/OS-II、embOS、salvo、FreeRTOS等少數(shù)實時操作系統(tǒng)能在小RAM單片機上運行。功能包括:任務(wù)管理、時間管理、信號量、消息隊列、內(nèi)存管理、記錄功能等,可基本滿足較小系統(tǒng)的需要。FreeRTOS免費的嵌入式操作系統(tǒng)相對C/OS-II、embOS等商業(yè)操作系統(tǒng),F(xiàn)

3、reeRTOS操作系統(tǒng)是完全免費的操作系統(tǒng),操作系統(tǒng)是完全免費的操作系統(tǒng),具有源碼公開、可移植、可裁減、調(diào)度策略靈活的特點,可以方便地移植到各種單片機上運行。AppendixFreeRTOS官網(wǎng):/FreeRTOS 內(nèi)核使用說明:Using The FREERTOS Real Time Kernal中英文版 FreeRTOSDownload FreeRTOS demoDemon code and your code will appear here FreeRTOS source codeGet close to FreeRTOSTask manag

4、ementInter-task Communication and SynchronizationInterrupt managementResource managementMemory managementTrouble shooting table of contents2 FreeRTOS Scheduler1 Scheduling algorithm2 Define and Create a task3 Status of task4 Other APIs of task management 1 調(diào)度機制也可稱為線程,是一個獨立的小程序,每個Task 都可以看成一個獨立的應(yīng)用程序。

5、實時應(yīng)用程序的設(shè)計過程,包括如何把問題分割成多個任務(wù)例如:無線溫度監(jiān)測系統(tǒng),任務(wù)包括:溫度采集、數(shù)據(jù)發(fā)送、命令接收等等任務(wù)(Task)1 調(diào)度機制多任務(wù)運行的實現(xiàn)實際上是靠CPU(MPU)在多個任務(wù)之間轉(zhuǎn)換、調(diào)度,交錯運行CPU只有一個,輪番服務(wù)于一系列任務(wù)中的某一個,一個CPU被虛擬化為若干個CPU多任務(wù)運行很像前后臺系統(tǒng),但后臺任務(wù)有多個多任務(wù)運行使CPU的利用率得到最大的發(fā)揮,并使應(yīng)用程序模塊化在實時應(yīng)用中,多任務(wù)化使開發(fā)人員可以將很復雜的應(yīng)用程序?qū)哟位嗳蝿?wù)(Multi-task)物理世界本身是并發(fā)的!調(diào)度算法:FIFO(FCFS) Example: Three processes a

6、rrive in order P1, P2, P3.P1 CPU time: 24P2 CPU time: 3P3 CPU time: 3Waiting TimeP1: 0P2: 24P3: 27Completion Time:P1: 24P2: 27P3: 30Average Waiting Time: (0+24+27)/3 = 17Average Completion Time: (24+27+30)/3 = 27P1P2 P30242730調(diào)度算法:Round-Robin(時間片輪時間片輪詢詢)ProcessCPU TimeP124 P2 3 P3 3P1P2P3P1P1P1P1P10

7、36912 1518 21 24FCFSRound-RobinAverage Waiting Time173Average Completion Time2715FCFSRRP1P127 30P1P2P3調(diào)度算法:Round-RobinAdvantage公平性:Better for short jobs Disadvantage開銷:Context-switching time adds up for long jobs P1P2P3P1P1P1P1P1036912 1518 21 24P1P127 30調(diào)度算法:Priority-driven schedulingtime0301020604

8、050P2P2P1P3TaskP1: priority 1, execution time 10P2: priority 2, execution time 30P3: priority 3, execution time 20New TaskPriority-driven scheduling exampletime0301020604050P2P2P1P3TaskP1: priority 1, execution time 10P2: priority 2, execution time 30P3: priority 3, execution time 20New TaskP3搶占式和非搶

9、占式time0301020604050P2P2P1P3TaskP1: priority 1, execution time 10P2: priority 2, execution time 30P3: priority 3, execution time 20New TaskP2 is running非搶占式(non-Preemptive)time0301020604050P2P2P1P3TaskP1: priority 1, execution time 10P2: priority 2, execution time 30P3: priority 3, execution time 20N

10、ew TaskP3P2 is running搶占式(Preemptive)time0301020604050P2P2P1P3TaskP1: priority 1, execution time 10P2: priority 2, execution time 30P3: priority 3, execution time 20New TaskP2P3P2 is runningFreeRTOS :Round Robin+Priority+Preemptive P1P2P3P1P1P1P1P1036912 1518 21 24P127 30P1P2P3P1P1P1P1P1036912 1518

11、21 24P1P127 30Round Robin Round Robin+ Priority P1P2P3P1P1P1P1P1036 912 1518 21 24P1P127 30Round Robin+Priority+ PreemptiveP1P1Running2 Define a task/*初始化,只會執(zhí)行一次*/和定義一個我們普通函數(shù)一樣,注意:1、 必須 void類型函數(shù)2、 空循環(huán)前是初始化,只會執(zhí)行一次。3、 task內(nèi)容寫在空循環(huán)里。4、 函數(shù)形參必須是一個 void 指針 用于傳遞參數(shù)。5、如果Task不用了,要刪除6、Task內(nèi)部可以產(chǎn)生另外一個taskCreate a

12、 taskDefine a task 和 Creat a task, 相當于定義一個類和對象。 pvTaskCode:指向任務(wù)的實現(xiàn)函數(shù)的指針(效果上僅僅是函數(shù)名)。 pcName:具有描述性的任務(wù)名。用于程序員識別,但不會被FreeRTOS使用。 usStackDepth :用于告訴內(nèi)核為它分配多大的??臻g pvParameters:傳遞到任務(wù)中的參數(shù)值 uxPriority:指定任務(wù)執(zhí)行的優(yōu)先級。 pxCreatedTask :pxCreatedTask 用于傳出任務(wù)的句柄。在在 API 調(diào)用中調(diào)用中對該對該創(chuàng)建出來的任務(wù)進行引用,比如改變?nèi)蝿?wù)優(yōu)先級,或者刪除任務(wù)。創(chuàng)建出來的任務(wù)進行引用,

13、比如改變?nèi)蝿?wù)優(yōu)先級,或者刪除任務(wù)。例1創(chuàng)建并啟動兩個任務(wù),這兩個任務(wù)只是周期性地打印輸出字符串,采用原始的空循環(huán)方式來產(chǎn)生周期延遲。 方法一:創(chuàng)建兩個Task方法一:創(chuàng)建兩個TaskTASK PRIORITIES方法二:Task create task方法三: Task 傳遞參數(shù)TASK PRIORITIES如果把Task 2的優(yōu)先級設(shè)為2會有什么結(jié)果?TASK PRIORITIESIt contains several sub-states3任務(wù)狀態(tài)非運行狀態(tài)1 Blocked(阻塞)2 Suspend(掛起)3 Ready(就緒)Blocked(阻塞)客觀上,需要等待數(shù)據(jù)或者時間,無法執(zhí)行

14、任務(wù)可以進入阻塞態(tài)以等待以下兩種不同類型的事件:定時(時間相關(guān))事件:這類事件可以是延遲到期或是絕對時間到點。同步事件源于其它任務(wù)或中斷的事件。任務(wù)可以在進入阻塞態(tài)以等待同步事件時指定一個等待超時時間,這樣可以有效地實現(xiàn)阻塞狀態(tài)下同時等待兩種類型的事件。Suspend(掛起)主觀讓任務(wù)不執(zhí)行。處于掛起狀態(tài)的任務(wù)對調(diào)度器而言是不可見的。讓一個任務(wù)進入掛起狀態(tài)的唯一辦法就是調(diào)用vTaskSuspend() API 函數(shù);而把一個掛起狀態(tài)的任務(wù)喚 醒的唯一途徑就是調(diào)用 vTaskResume() 或vTaskResumeFromISR() API 函數(shù)。大多數(shù)應(yīng)用程序中都不會用到掛起狀態(tài)。Ready

15、(就緒)如果任務(wù)處于非運行狀態(tài),但既沒有阻塞也沒有掛起,則這個任務(wù)處于就緒。處于就緒態(tài)的任務(wù)能夠被運行,但只是”準備(ready)”運行,而當前尚未運行。任務(wù)狀態(tài)FreeRTOS實現(xiàn)方法: (1)阻塞任務(wù)隊列(2)就緒任務(wù)隊列THE IDLE TASKThe processor always needs something to execute there must always be that can enter the Running state.An Idle task is automatically created by the scheduler when vTaskStartSc

16、heduler() is called.Prioirty:0例子:利用阻塞狀態(tài)實現(xiàn)延遲延遲通過延遲通過 計數(shù)來實現(xiàn)的。消耗計數(shù)來實現(xiàn)的。消耗CPU資源資源例子:利用阻塞狀態(tài)實現(xiàn)延遲阻塞延遲函數(shù):阻塞延遲函數(shù): 運行vTaskDelay函數(shù),將當前任務(wù)放入“阻塞隊列”; 延遲時間到達后,將任務(wù)放回“就緒隊列”。例子:利用阻塞狀態(tài)實現(xiàn)延遲2,例子:利用阻塞狀態(tài)實現(xiàn)延遲4 任務(wù)優(yōu)先級動態(tài)設(shè)置優(yōu)先級設(shè)置函數(shù):優(yōu)先級讀取函數(shù):被查詢?nèi)蝿?wù)的句柄(目標任務(wù)) 參考xTaskCreate() API函數(shù)的參數(shù) pxCreatedTask 以了解如何得到任務(wù)句柄方面的信息。任務(wù)可以通過傳入 NULL 值來修改自

17、己的優(yōu)先級。pxTask uxNewPriority目標任務(wù)將被設(shè)置到哪個優(yōu)先級上。如果設(shè)置的值超過了最大可用優(yōu)先級(configMAX_PRIORITIES 1),則會被自動封頂為最大值。任務(wù)句柄,任務(wù)可以通過傳入 NULL 值來查詢自己的優(yōu)先級。pxTask被查詢?nèi)蝿?wù)的當前優(yōu)先級。返回值 優(yōu)先級設(shè)置例子例 具有以下行為方式: 任務(wù) 1(程序清單 22)創(chuàng)建在最高優(yōu)先級,以保證其可以最先運行。任務(wù) 1 首先打印輸出兩個字符串,然后將任務(wù)2的優(yōu)先級提升到自己之上。 任務(wù) 2 一旦擁有最高優(yōu)先級便啟動執(zhí)行(進入運行態(tài))。由于任何時候只可能有一個任務(wù)處于運行態(tài),所以當任務(wù)2運行時,任務(wù) 1處于就緒

18、態(tài)。 任務(wù)2打印輸出一個信息,然后把自己的優(yōu)先級設(shè)回低于任務(wù) 1的初始值。 任務(wù) 2 降低自己的優(yōu)先級意味著任務(wù) 1 又成為具有最高優(yōu)先級的任務(wù),所以任務(wù)1重新進入運行態(tài),任務(wù)2被強制切入就緒態(tài)。 代碼void vTask1( void *pvParameters ) unsigned portBASE_TYPE uxPriority; uxPriority = uxTaskPriorityGet( NULL ); /*傳遞一個NULL值表示說“返回我自己的優(yōu)先級”。*/ for( ; ) /* Print out the name of this task. */ vPrintString(

19、 Task1 is runningrn ); vPrintString( About to raise the Task2 priorityrn ); vTaskPrioritySet( xTask2Handle, ( uxPriority + 1 ) ); 代碼void vTask2( void *pvParameters ) unsigned portBASE_TYPE uxPriority; uxPriority = uxTaskPriorityGet( NULL ); for( ; ) vPrintString( Task2 is runningrn ); vPrintString(

20、About to lower the Task2 priorityrn ); vTaskPrioritySet( NULL, ( uxPriority - 2 ) ); 代碼xTaskHandle xTask2Handle; int main( void ) xTaskCreate( vTask1, Task 1, 1000, NULL, 2, NULL ); xTaskCreate( vTask2, Task 2, 1000, NULL, 1, &xTask2Handle ); vTaskStartScheduler(); for( ; ); 執(zhí)行過程刪除task被刪除任務(wù)的句柄(目

21、標任務(wù)) 參考xTaskCreate() API函數(shù)的參數(shù) pxCreatedTask 以了解如何得到任務(wù)句柄方面的信息。 任務(wù)可以通過傳入 NULL 值來刪除自己。 pxTaskToDelete刪除任務(wù)例子例 9. 刪除任務(wù) 任務(wù)1則 main()創(chuàng)建在優(yōu)先級1上。任務(wù) 1運行時,以優(yōu)先級 2創(chuàng)建任務(wù) 2?,F(xiàn)在任務(wù) 2 具有最高優(yōu)先級,所以會立即得到執(zhí)行。任務(wù) 2 什么也沒有做,只是刪除自己??梢酝ㄟ^傳遞 NULL 值以 vTaskDelete()來刪除自己當任務(wù)2被自己刪除之后,任務(wù) 1成為最高優(yōu)先級的任務(wù),所以繼續(xù)執(zhí)行,調(diào)用vTaskDelay()阻塞一小段時間。 當任務(wù)1進入阻塞狀態(tài)后

22、,空閑任務(wù)得到執(zhí)行的機會。任務(wù)1離開阻塞態(tài)后,再一次成為就緒態(tài)中具有最高優(yōu)先級的任務(wù),因此會搶占空閑任務(wù)。又再一次創(chuàng)建任務(wù)2,如此往復。 代碼void vTask1( void *pvParameters ) const portTickType xDelay100ms = 100 / portTICK_RATE_MS; for( ; ) vPrintString( Task1 is runningrn ); xTaskCreate( vTask2, Task 2, 1000, NULL, 2, &xTask2Handle ); vTaskDelay( xDelay100ms ); v

23、oid vTask2( void *pvParameters ) vPrintString( Task2 is running and about to delete itselfrn ); vTaskDelete( xTask2Handle ); 代碼int main( void ) /* 任務(wù)1創(chuàng)建在優(yōu)先級1上 */ xTaskCreate( vTask1, Task 1, 1000, NULL, 1, NULL ); /* The task is created at priority 1 _. */ /* Start the scheduler so the tasks start e

24、xecuting. */ vTaskStartScheduler(); /* main() should never reach here as the scheduler has been started. */ for( ; ); 結(jié)果Other Related API functionstaskYIELD()THE SCHEDULING ALGORITHMFreeRTOS 任務(wù)管理小結(jié)Round-Robin + Priority + PreemptiveOnly one task can exist in the Running state at any one time.The sch

25、eduler will always select the highest priority Ready state task to enter the Running state. Define, Create a taskRunning, Ready, Blocked, SuspendedDelete, Setpriority Get close to FreeRTOSTask managementInter-task Communication and SynchronizationInterrupt managementResource managementMemory managem

26、entTrouble shooting table of contents1、任務(wù)通信/同步的基本概念2、FreeRTOS:隊列3、FreeRTOS:信號量1、基本概念任務(wù)間通信基本概念任務(wù)同步我們把異步環(huán)境下的一組并發(fā)任務(wù)因直接制約而互相發(fā)送消息、進行互相合作、互相等待,使得各任務(wù)按一定的速度執(zhí)行的過程稱為任務(wù)間的同步。消息通信和信號量是實現(xiàn)任務(wù)同步的主要方法FreeRTOS的通信和同步都是由Queue(隊列)實現(xiàn)2、隊列QUEUE隊列:是一個隊列:是一個FIFO,有長度(隊列深度),有長度(隊列深度)可以被多個可以被多個Task訪問訪問讀隊列時阻塞讀隊列時阻塞寫隊列寫隊列時阻塞時阻塞Exa

27、mple of QueueUSING A QUEUE in FreeRTOSuxQueueLength 隊列能夠存儲的最大單元數(shù)目,即隊列深度。 uxItemSize 隊列中數(shù)據(jù)單元的長度,以字節(jié)為單位。 返回值 NULL表示沒有足夠的堆空間分配給隊列而導致創(chuàng)建失敗。 非 NULL值表示隊列創(chuàng)建成功。此返回值應(yīng)當保存下來,以作為操作此隊列的句柄。USING A QUEUE in FreeRTOSxTicksToWait 阻塞阻塞超時時間。超時時間。如果在發(fā)送時隊列已滿,讀取不成功,則如果在發(fā)送時隊列已滿,讀取不成功,則阻塞阻塞xTicksToWait 個個周期周期。xQueueSendToFr

28、ont()用于將數(shù)據(jù)發(fā)送到隊列首;xQueueSendToBack()用于將數(shù)據(jù)發(fā)送到隊列尾;xQueueSend()完全等同于 xQueueSendToBack()。USING A QUEUE in FreeRTOSxQueueReceive()用于從隊列中接收(讀?。?shù)據(jù)單元。接收到的單元同時會從隊列中刪除。 xQueuePeek()也是從從隊列中接收數(shù)據(jù)單元,不同的是并不從隊列中刪出接收到的單元。xQueuePeek()從隊列首接收到數(shù)據(jù)后,不會修改隊列中的數(shù)據(jù),也不會改變數(shù)據(jù)在隊列中的存儲序順。 USING A QUEUE in FreeRTOSuxQueueMessagesWaiti

29、ng() 用于查詢隊列中當前有效數(shù)據(jù)單元個數(shù)。Example例 10. 讀隊列時阻塞 創(chuàng)建一個保存 long 型數(shù)據(jù)單元的隊列,2個寫數(shù)據(jù)任務(wù)和1個讀數(shù)據(jù)任務(wù)。往隊列中寫數(shù)據(jù)的任務(wù)沒有設(shè)定阻塞超時時間,而讀隊列的任務(wù)設(shè)定了阻塞超時時間。讀數(shù)據(jù)任務(wù)優(yōu)先級高于寫數(shù)據(jù)任務(wù)的優(yōu)先級分析: 隊列中永遠不會保持超過一個的數(shù)據(jù)單元。因為一旦有數(shù)據(jù)被寫入隊列,讀隊列任務(wù)立即解除阻塞,搶占寫隊列任務(wù),并從隊列中接收數(shù)據(jù),同時數(shù)據(jù)從隊列中刪除,隊列再一次變?yōu)榭贞犃小?MainxQueueHandle xQueue; int main( void ) xQueue = xQueueCreate( 5, sizeof

30、( long ) ); if( xQueue != NULL ) xTaskCreate( vSenderTask, Sender1, 1000, ( void * ) 100, 1, NULL ); xTaskCreate( vSenderTask, Sender2, 1000, ( void * ) 200, 1, NULL ); xTaskCreate( vReceiverTask, Receiver, 1000, NULL, 2, NULL ); vTaskStartScheduler(); else /* 隊列創(chuàng)建失敗*/ for( ; ); vSenderTaskstatic vo

31、id vSenderTask( void *pvParameters ) long lValueToSend; portBASE_TYPE xStatus; lValueToSend = ( long ) pvParameters; for( ; ) xStatus = xQueueSendToBack( xQueue, &lValueToSend, 0 ); if( xStatus != pdPASS ) /* 發(fā)送操作由于隊列滿而無法完成 這必然存在錯誤,因為本例中的隊列不可能滿。 */ vPrintString( Could not send to the queue.rn );

32、 taskYIELD(); /* 允許其它發(fā)送任務(wù)執(zhí)行。 taskYIELD()通知調(diào)度器現(xiàn)在就切換到其它任務(wù),而不必等到本任務(wù)的時間片耗盡 */ vReceiverTaskstatic void vReceiverTask( void *pvParameters ) long lReceivedValue; portBASE_TYPE xStatus; const portTickType xTicksToWait = 100 / portTICK_RATE_MS; for( ; ) if( uxQueueMessagesWaiting( xQueue ) != 0 ) vPrintStri

33、ng( Queue should have been empty!rn ); xStatus = xQueueReceive( xQueue, &lReceivedValue, xTicksToWait ); if( xStatus = pdPASS ) vPrintStringAndNumber( Received = , lReceivedValue ); else vPrintString( Could not receive from the queue.rn ); /* 等待100ms也沒有收到任何數(shù)據(jù) */ 結(jié)果3、信號量信號量的本質(zhì)是一種數(shù)據(jù)操作鎖或者一種同步標志,它本身

34、不具有數(shù)據(jù)交換的功能。通常程序通過信號量來控制其他的通信資源(文件,外部設(shè)備)來實現(xiàn)任務(wù)間通信,實現(xiàn)數(shù)據(jù)操作的互斥、任務(wù)同步等功能?;蛘呷蝿?wù)僅僅通過信號量的數(shù)值,來判斷任務(wù)進入運行狀態(tài)或者阻塞狀態(tài),實現(xiàn)任務(wù)同步。信號量的類型二值信號量(Binary Semaphores):只有0和1, 事件發(fā)生了置1,事件處理了置0,一般用作同步。計數(shù)信號量(Counting Semaphores):沒發(fā)生一個事件,計數(shù)值+1。 事件發(fā)生可能比處理快,記錄未處理事件數(shù)量。互斥信號量(Mutex Semaphores ): 是一種特殊的二值信號量,用于控制在兩個或多個任務(wù)間訪問共享資源。 FreeRTOS信號量

35、APIxSemaphoreCreateBinary()/創(chuàng)建二值信號量創(chuàng)建二值信號量xSemaphoreCreateCounting()/創(chuàng)建計數(shù)信號量創(chuàng)建計數(shù)信號量xSemaphoreCreateMutex()/創(chuàng)建互斥信號量創(chuàng)建互斥信號量vSemaphoreDelete()/刪除信號量xSemaphoreTake()/獲取信號量獲取信號量xSemaphoreTakeFromISR()/中斷處理程序中獲取信號量中斷處理程序中獲取信號量xSemaphoreGive()/設(shè)置信號量設(shè)置信號量xSemaphoreGiveFromISR()中斷處理程序中,設(shè)置信號量中斷處理程序中,設(shè)置信號量xSem

36、aphoreGetMutexHolder()/獲取互斥信號量的使用者Get close to FreeRTOSTask managementQueue managementInterrupt managementResource managementMemory managementTrouble shooting table of contents1、中斷與事件處理2、利用二值信號量實現(xiàn)中斷與任務(wù)同步3、利用計數(shù)信號量鎖存多次中斷4、中斷中使用隊列中斷中斷1. Normal program execution2. Interrupt occurs3. Processor state save

37、d4. Interrupt routine runs5. Interrupt routine terminates6. Processor state restored7. Normal program execution resumesCPU在執(zhí)行一個程序時,對系統(tǒng)發(fā)生的某個事件(程序自身或外界的原因)作出的一種反應(yīng):CPU暫停正在執(zhí)行的程序,保留現(xiàn)場后自動轉(zhuǎn)去處理相應(yīng)的事件,處理完該事件后,到適當?shù)臅r候返回斷點,繼續(xù)完成被打斷的程序。中斷與事件處理 嵌入式實時系統(tǒng)需要對整個系統(tǒng)環(huán)境產(chǎn)生的各種事件作出反應(yīng), 這些事件對處理時間和響應(yīng)時間都有不同的要求。1. 事件如何被檢測到?通常采用中斷方式

38、,但是也可以通過查詢獲得。 2. 事件處理多少在中斷服務(wù)例程(ISR)中的處理?多少在 ISR 外處理?通常情況下,ISR越短越好。 3. 中斷如何通知到主程序?什么樣的程序結(jié)構(gòu)才能最好地適應(yīng)異步和并發(fā)事件? 2、利用二值信號量延遲處理中斷如何實現(xiàn)創(chuàng)建二創(chuàng)建二值(值(Binary)信號量)信號量void vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore );xSemaphore 所創(chuàng)建信號量的句柄 獲取信號量獲取信號量portBASE_TYPE xSemaphoreTake( xSemaphoreHandle xSemaphore, por

39、tTickType xTicksToWait ); xTicksToWait如果獲取不成功,則阻塞xTicksToWait 個tick周期中斷處理程序中設(shè)置信號量中斷處理程序中設(shè)置信號量portBASE_TYPE xSemaphoreGiveFromISR( xSemaphoreHandle xSemaphore, portBASE_TYPE *pxHigherPriorityTaskWoken ); pxHigherPriorityTaskWoken 標識符,函數(shù)內(nèi)部賦值。表示被解除阻塞的 任務(wù)優(yōu)先級是否高于當前正在執(zhí)行的任務(wù)。例 12. 利用二值信號量對任務(wù)和中斷進行同步在中斷服務(wù)例程中使

40、用一個二值信號量讓任務(wù)從阻塞態(tài)中切換出來從效果上等同于讓任務(wù)與中斷進行同步。中斷源:一個簡單的周期性任務(wù)用于每隔 500 毫秒產(chǎn)生一個軟件中斷。vPeriodicTaskstatic void vPeriodicTask( void *pvParameters ) for( ; ) /* 此任務(wù)通過每500毫秒產(chǎn)生一個軟件中斷來”模擬”中斷事件 */ vTaskDelay( 500 / portTICK_RATE_MS ); /* 產(chǎn)生中斷,并在產(chǎn)生之前和之后輸出信息,以便在執(zhí)行結(jié)果中直觀直出執(zhí)行流程 */ vPrintString( Periodic task - About to gene

41、rate an interrupt.rn ); _asm int 0 x82 /* 這條語句產(chǎn)生中斷 */ vPrintString( Periodic task - Interrupt generated.rnrnrn ); vHandlerTaskstatic void vHandlerTask( void *pvParameters ) /* As per most tasks, this task is implemented within an infinite loop. */ for( ; ) /* 使用信號量等待一個事件。信號量在調(diào)度器啟動之前,也即此任務(wù)執(zhí)行之前就已被創(chuàng)建。任

42、務(wù)被無超時阻塞,所以此函數(shù)調(diào)用也只會在成功獲取信號量之后才會返回。此處也沒有必要檢測返回值 */ xSemaphoreTake( xBinarySemaphore, portMAX_DELAY ); /* 程序運行到這里時,事件必然已經(jīng)發(fā)生。本例的事件處理只是簡單地打印輸出一個信息 */ vPrintString( Handler task - Processing event.rn ); interruptstatic void _interrupt _far vExampleInterruptHandler( void ) static portBASE_TYPE xHigherPrior

43、ityTaskWoken; xHigherPriorityTaskWoken = pdFALSE; /* Give the semaphore to unblock the task. */ xSemaphoreGiveFromISR( xBinarySemaphore, &xHigherPriorityTaskWoken ); if( xHigherPriorityTaskWoken = pdTRUE ) /* 給出信號量以使得等待此信號量的任務(wù)解除阻塞。如果解出阻塞的任務(wù)的優(yōu)先級高于當前任務(wù)的優(yōu)級 強制進行一次任務(wù)切換,以確保中斷直接返回到解出阻塞的任務(wù)(優(yōu)選級更高) */ por

44、tSWITCH_CONTEXT(); mianint main( void ) vSemaphoreCreateBinary( xBinarySemaphore ); /* 創(chuàng)建了一個二值信號量 */ _dos_setvect( 0 x82, vExampleInterruptHandler ); /* 安裝中斷服務(wù)例程 */ if( xBinarySemaphore != NULL ) /* 檢查信號量是否成功創(chuàng)建 */ xTaskCreate( vHandlerTask, “Handler”, 1000, NULL, 3, NULL );/*延遲處理任務(wù) */ xTaskCreate( v

45、PeriodicTask, “Periodic”, 1000, NULL, 1, NULL ); /*周期性任務(wù) */ /* Start the scheduler so the created tasks start executing. */ vTaskStartScheduler(); for( ; ); 結(jié)果利用計數(shù)信號量鎖存多次中斷What to do when Interrupts occurs more frequently?Only one interruptMore interrupts3、利用計數(shù)信號量鎖存多次中斷一個二值信號量最多只可以鎖存一個中斷事件。在鎖存的事件還未被

46、處理之前,如果還有中斷事件發(fā)生,那么后續(xù)發(fā)生的中斷事件將會丟失。解決方法:計數(shù)信號量事件發(fā)生時,中斷服務(wù)例程都會“給出(Give)”信號量信號量在每次被給出時其計數(shù)值加 1。延遲處理任務(wù)每處理一個任務(wù)都會”獲取(Take)”一次信號量信號量在每次被獲取時其計數(shù)值減 1。定義定義計數(shù)計數(shù)(Counting)信號量)信號量xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount );uxMaxCount 最大計數(shù)值。uxIni

47、tialCount信號量的初始計數(shù)值。返回值句柄或者Null(表示失敗)例 13. 利用計數(shù)信號量對任務(wù)和中斷進行同步用計數(shù)信號量代替二值信號量對例 12 的實現(xiàn)進行了改進。修改 main()函數(shù)調(diào)用xSemaphoreCreateCounting(),以代替對xSemaphoreCreateBinary()的調(diào)用。mianint main( void ) xCountingSemaphore = xSemaphoreCreateCounting( 10, 0 ); /* 創(chuàng)建創(chuàng)建了了計數(shù)計數(shù)信號量信號量 */ _dos_setvect( 0 x82, vExampleInterruptHan

48、dler ); /* 安裝中斷服務(wù)例程 */ if( xBinarySemaphore != NULL ) /* 檢查信號量是否成功創(chuàng)建 */ xTaskCreate( vHandlerTask, “Handler”, 1000, NULL, 3, NULL );/*延遲處理任務(wù) */ xTaskCreate( vPeriodicTask, “Periodic”, 1000, NULL, 1, NULL ); /*周期性任務(wù) */ /* Start the scheduler so the created tasks start executing. */ vTaskStartSchedule

49、r(); for( ; ); interruptstatic void _interrupt _far vExampleInterruptHandler( void ) static portBASE_TYPE xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdFALSE; /* 多次給出信號量。第一次給出時使得延遲處理任務(wù)解除阻塞。后續(xù)給出用于演示利多次給出信號量。第一次給出時使得延遲處理任務(wù)解除阻塞。后續(xù)給出用于演示利用被信號量鎖存事件用被信號量鎖存事件,以便,以便延遲處理任何依序?qū)@些中斷事件進行處理而不會丟中斷。延遲處理任何依

50、序?qū)@些中斷事件進行處理而不會丟中斷。用這種方式來模擬處理器產(chǎn)生多個中斷,用這種方式來模擬處理器產(chǎn)生多個中斷,盡管這些盡管這些事件只是在單次中斷中模擬出來的事件只是在單次中斷中模擬出來的 */ xSemaphoreGiveFromISR( xCountingSemaphore, &xHigherPriorityTaskWoken ); xSemaphoreGiveFromISR( xCountingSemaphore, &xHigherPriorityTaskWoken ); xSemaphoreGiveFromISR( xCountingSemaphore, &xHi

51、gherPriorityTaskWoken ); Free http:/www.F if( xHigherPriorityTaskWoken = pdTRUE ) portSWITCH_CONTEXT(); 結(jié)果4、中斷中使用隊列信號量用于事件同步. 隊列可以同時傳遞事件和數(shù)據(jù)。例14創(chuàng)建一個周期任務(wù)用于每 200 毫秒往隊列中發(fā)送五個數(shù)值,五個數(shù)值都發(fā)送完后便產(chǎn)生一個軟件中斷。中斷處理程序,在字符串隊列放入五個字符串由handler任務(wù)進行輸出例14 創(chuàng)建一個周期任務(wù)用于每 200 毫秒往隊列中發(fā)送五個數(shù)值,五個數(shù)值都發(fā)送完后便產(chǎn)生一個軟件中斷結(jié)果Interrupt nestingGet c

52、lose to FreeRTOSTask managementInter-task Communication and SynchronizationInterrupt managementResource managementMemory managementTrouble shooting table of contentscritical sectionmutexgatekeeper task1、多任務(wù)的風險2、臨界區(qū)3、互斥信號量1、多任務(wù)系統(tǒng)的風險當一個任務(wù)在使用某個資源的過程中,即還沒有完全結(jié)束對資源的訪問時,便被切出運行態(tài),使得資源處于非一致,不完整的狀態(tài)。如果這個時候有另一個任

53、務(wù)或者中斷來訪問這個資源,則會導致數(shù)據(jù)損壞或是其它相似的錯誤。例:數(shù)據(jù)共享問題考慮如下情形,有兩個任務(wù)都試圖往一個LCD中寫數(shù)據(jù): 任務(wù) A運行,并往 LCD寫字符串”Hello world”。 任務(wù) A被任務(wù) B搶占,但此時字符串才輸出到”Hello w”。 任務(wù) B 往 LCD寫”Abort, Retry, Fail?”,然后進入阻塞態(tài)。 任務(wù) A從被搶占處繼續(xù)執(zhí)行,完成剩余的字符輸出“orld”。 現(xiàn)在LCD 顯示的是被破壞了的字符串”Hello wAbort, Retry, Fail?orld”。 解決方法?2、臨界區(qū)(Criticl)指運行時不可被打斷的程序區(qū)域 一旦這部分程序開始執(zhí)

54、行,則不允許以任何方式中斷其運行。為確保臨界區(qū)代碼的獨占執(zhí)行,在進入臨界段之前要關(guān)中斷,而臨界段代碼執(zhí)行完以后要立即開中斷,以免系統(tǒng)實時性下降。 FreeRTOS 基本臨界區(qū)定義基本臨界區(qū)是指宏 taskENTER_CRITICAL()與 taskEXIT_CRITICAL()之間的代碼區(qū)間 在taskENTER_CRITICAL() 與 taskEXIT_CRITICAL()之間不會切換到其它任務(wù)。 中斷可以執(zhí)行,也允許嵌套,但只是針對優(yōu)先級高于configMAX_SYSCALL_INTERRUPT_PRIORITY的中斷 , 而且這些中斷不允許訪問 FreeRTOS API 函數(shù).Exam

55、ple通過掛起調(diào)度器建立臨界區(qū)基本臨界區(qū)保護一段代碼區(qū)間不被其它任務(wù)或中斷打斷。由掛起調(diào)度器實現(xiàn)的臨界區(qū)只可以保護一段代碼區(qū)間不被其它任務(wù)打斷,因為這種方式下,中斷是使能的。 如果一個臨界區(qū)太長而不適合簡單地關(guān)中斷來實現(xiàn),可以考慮采用掛起調(diào)度器的方式。但是喚醒(resuming, or un-suspending)調(diào)度器卻是一個相對較長的操作。所以評估哪種是最佳方式需要結(jié)合實際情況。 3、互斥信號量互斥量是一種特殊的二值信號量,用于控制在兩個或多個任務(wù)間訪問共享資源訪問共享資源。類似于令牌,要想訪問資源必須先獲互斥取信號量訪問完后必須歸還(Give)與二值信號量的區(qū)別:用于互斥的信號量必須歸還。二值信號量用于同步,用完就丟棄相關(guān)函數(shù)定義互斥信號量定義互斥信號量xSemaphoreHandle xSemaphoreCreateMutex( void )獲取信號量獲取信號量portBASE_TYPE xSemaphoreTake( xSemaphoreHandle xSemaphore,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論