




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、傻瓜實現(xiàn)FreeRTOS系統(tǒng)如果你1 希望修改FreeRTOS源代碼2 移植實時內(nèi)核到另一個微控制器或者原型板(prototyping board)3 第一次接觸FreeRTOS,希望得到關(guān)于它們在操作和實現(xiàn)上的更多信息這些文檔會有用。本文檔分為兩個章節(jié):1. 基本原理和RTOS概念包括多任務(wù)的背景信息和基本實時概念,這是為初學(xué)者準(zhǔn)備的(is intended for beginners)2. 從底向上(from the bottom up)解釋實時內(nèi)核源代碼FreeRTOS實時內(nèi)核已經(jīng)移植到許多不同的微控制器架構(gòu)下。這份文檔是以Atmel A
2、VR為范例,因為:1. AVR架構(gòu)簡單2. 有免費可用的開發(fā)工具 WinAVR (GCC) development tools. 3. 非常便宜的原型板STK500 prototyping board在本文的最后,還一步一步地詳細(xì)描述了一個完整的上下文切換(context switch)。RTOS基本原理多任務(wù)調(diào)度上下文切換實時應(yīng)用實時調(diào)度這一節(jié)提供一個關(guān)于實時和多任務(wù)概念的簡介。讀下一節(jié)之前必須理解這些概念。多任務(wù)(Multitasking)在一個操作系統(tǒng)內(nèi)部,內(nèi)核kernel是最核心的部件。像Linux那樣的操作系統(tǒng)使用的內(nèi)核,從表面上看(seem
3、ingly),允許用戶并發(fā)(simultaneously)訪問 計算機。多個用戶似乎(apparently)可以并行(concurrently)執(zhí)行多個程序。在操作系統(tǒng)的控制下,每個正在執(zhí)行的程序就是一個任務(wù)task。如果一個操作系統(tǒng)能夠以這種方法執(zhí)行多個任務(wù),這就叫做多任務(wù)multitasking.多任務(wù)操作系統(tǒng)的使用可以簡化應(yīng)用程序的設(shè)計:1 操作系統(tǒng)的多任務(wù)和任務(wù)間通信的機制允許復(fù)雜的應(yīng)用程序被分成一系列更小的和更多的可以管理的任務(wù)。2 (程序的)劃分(partitioning)讓軟件測試更容易, 團隊工作分解(work breakdown within teams)
4、,也有利于代碼復(fù)用。3 復(fù)雜的定時和先后順序的細(xì)節(jié) 可以從應(yīng)用程序代碼中 刪除。(因為)這成為操作系統(tǒng)的職責(zé)。多任務(wù)Vs 并發(fā)傳統(tǒng)的(conventional)的處理器同時只能執(zhí)行一個任務(wù)。但通過快速的任務(wù)切換,一個多任務(wù)操作系統(tǒng)可以使它看起來(appear)好像每個任務(wù)并行執(zhí)行一樣。這可以下面的示意圖來描述(depicted)。它顯示了有關(guān)(with respect to)時間的3個任務(wù)的執(zhí)行模式。任務(wù)名用顏色標(biāo)注出來,寫在左手邊。時間從左到右增加,相應(yīng)的顏色的線條 顯示該任務(wù)在某個特殊時間正在執(zhí)行。上面的圖 演示的是用戶所覺察到的并行執(zhí)行模式,下面的圖是實際的多任務(wù)執(zhí)行模式。-所
5、有可用的任務(wù)都好像在執(zhí)行,但實際上在任何一個時刻都只有一個任務(wù)在執(zhí)行調(diào)度調(diào)度器(scheduler)是內(nèi)核中負(fù)責(zé) 決定在某個特殊時間 哪個任務(wù)應(yīng)該執(zhí)行的部分。內(nèi)核可以在任務(wù)的生命期(lifetime) 掛起(suspend) / 恢復(fù)(resume)一個任務(wù)許多次。調(diào)度策略(scheduling policy)是調(diào)度器用來決定哪個任務(wù)在哪個時間點執(zhí)行的算法。一個(非實時)多用戶系統(tǒng)的策略很可能分配(allow)給每個任務(wù)一個"公平"(fair)的處理器時間片(proportion of processor time)。用在實時系統(tǒng)/嵌入式系統(tǒng)的策略稍后再描述。除了被RTOS
6、內(nèi)核無意的掛起外,一個任務(wù)還可以自己掛起自己。如果一個任務(wù)想延遲一段固定的時間(也就是sleep),或者等待(也就是block)某個資源可用(比如一個串口),或者等待一個事件出現(xiàn)(比如一個鍵按下)。一個阻塞或者睡眠的任務(wù)是不能執(zhí)行的,不會為它分配任何處理時間。上圖中提到的編號:1) Task1正在運行2) 內(nèi)核掛起Task13) 恢復(fù)任務(wù)Task24) Task2正在執(zhí)行,為獨占訪問(exclusive access),它鎖定一個處理器外設(shè) 5) 內(nèi)核 掛起Task26) 恢復(fù)Task37) Task3試圖訪問同樣的處理器外
7、設(shè),發(fā)現(xiàn)它被鎖定,Task3不能繼續(xù),所以自己掛起自己。8) 內(nèi)核恢復(fù)Task1.9) 接下來(the next time),Task2在9處執(zhí)行。它完成了對處理器外設(shè)的訪問,所以解鎖它10) 再下來,Task3在10處執(zhí)行。它發(fā)現(xiàn) 現(xiàn)在可以訪問處理器外設(shè)了,于是開始執(zhí)行,直到被內(nèi)核掛起。上下文切換跟任何其他程序一樣,一個任務(wù)執(zhí)行時,它使用 處理器/微控制器 的寄存器,訪問RAM ROM。這些資源(處理器的寄存器,stack等)一起組成任務(wù)的執(zhí)行上下文(the task execution context).一個任務(wù)是一個連續(xù)有序的代碼片斷。它并不知道它將何時被內(nèi)
8、核掛起或者恢復(fù),甚至不知道這些事情(掛起或者恢復(fù))在什么時候已經(jīng)發(fā)生了。下面考查(Consider)的這個例子是用來求兩個處理器中的寄存器值之和,該任務(wù)在執(zhí)行1條指令后就立即被掛起。->任務(wù)將要執(zhí)行ADD指令時,被掛起->先前的指令已經(jīng)把數(shù)取到寄存器(Reg1,Reg2)中了,而這些寄存器(Reg1,Reg2)將要被ADD指令用到。當(dāng)這個任務(wù)被恢復(fù)后,ADD就是要執(zhí)行的第1條指令。這個任務(wù)不知道是否有另一個的任務(wù)會在中間時期 修改 Reg1或者Reg2)當(dāng)這個任務(wù)掛起時,其他任務(wù)繼續(xù)執(zhí)行,可能會修改處理器寄存器的值。在恢復(fù)之后,這個任務(wù)也不知道處理器的寄存器被修改過(altered
9、).如果它使用這個修改過的值,就會導(dǎo)致計算的和的結(jié)果不正確。為了避免這類錯誤,必須保證,在恢復(fù)一個任務(wù)之后,其上下文環(huán)境跟 即將掛起前是一樣的。操作系統(tǒng)內(nèi)核有責(zé)任 通過在任務(wù)掛起前保存其上下文 來確保這種狀況。當(dāng)任務(wù)恢復(fù)時,保存的上下文 就被 操作系統(tǒng)內(nèi)核恢復(fù)到先前的執(zhí)行情況。保存一個被掛起的任務(wù)的上下文 并在 任務(wù)恢復(fù)時 恢復(fù)其上下文的這個處理過程就叫做上下文切換(context switching)實時應(yīng)用實時操作系統(tǒng)(RTOS's)通過同樣的原理達(dá)到多任務(wù)的目的。但他們的目標(biāo)與那些非實時系統(tǒng)相比是很不一樣的。不同的目標(biāo)影響到不同的調(diào)度策略。實時/嵌入式系統(tǒng)設(shè)計成提供一個對 真實世
10、界的事件的及時響應(yīng)(timely response)。出現(xiàn)在真實世界中的事件可能有一個時間限制(deadline),在此期限之前,實時/嵌入式系統(tǒng)必須給出響應(yīng),RTOS調(diào)度策略必須確保時間限制是恰當(dāng)?shù)?met).為了達(dá)到這個目的,軟件工程師必須首先為每個任務(wù)設(shè)置一個優(yōu)先級(priority)。RTOS的調(diào)度策略 只是簡單地確認(rèn) 能被執(zhí)行的最高優(yōu)先級別的任務(wù) 是分配了處理時間的任務(wù)(the task given processing time)。這可能要求在相同優(yōu)先級的 任務(wù)之間公平的共享 處理時間,如果他們準(zhǔn)備并發(fā)運行的話。代碼示例:最基本的例子是 一個由鍵盤和LCD組成的實時系統(tǒng)。用戶必須
11、在合理的時段 為 每個鍵盤按下 取得視覺反饋(visual feedback).。如果用戶不能 在這時段 看到 鍵盤按下 已經(jīng)被接受,軟件產(chǎn)品將會很難使用(be awkward to use)。如果最長的接受期是100ms,那么在0到100ms的響應(yīng) 可被接受。這個功能可以用一個 下面這樣的結(jié)構(gòu)的獨立(autonomous)任務(wù) 實現(xiàn):void vKeyHandlerTask( void *pvParameters ) /鍵盤處理是一個連續(xù)的過程。就像大多實時任務(wù)那樣,這個任務(wù) /也是用
12、一個無限循環(huán)實現(xiàn)的。 for( ; ) Suspend waiting for a key press Process the key press 現(xiàn)在假設(shè) 實時系統(tǒng)也執(zhí)行一個依賴數(shù)字濾波輸入的控制功能。這個輸入必須被取樣(sampled),濾波(f
13、iltered),并且 每2ms執(zhí)行一次控制循環(huán)。為了讓濾波器正常操作,取樣的時間規(guī)律(the temporal regularity)必須精確到0.5ms。 這個功能可以 用下面這個結(jié)構(gòu)的 獨立任務(wù) 實現(xiàn):void vControlTask( void *pvParameters ) for( ; ) Suspend waiting for 2ms since the start of t
14、he previous cycleSample the input Filter the sampled input Perform control algorithm Output result
15、0; 軟件工程師必須設(shè)置 控制任務(wù)為 最高的優(yōu)先級,因為:1 控制任務(wù)的時間限制(deadline) 比 鍵盤處理任務(wù)的 要嚴(yán)格;2 控制任務(wù)錯過最后期限(deadline)的后果 比 鍵盤處理任務(wù) 要嚴(yán)重。下面將演示 這些任務(wù)是如何被實時操作系統(tǒng)調(diào)度的.實時調(diào)度下面的圖 演示 前面定義的那些任務(wù)是如何被時實操作系統(tǒng)調(diào)度的。RTOS自己已經(jīng)建立了一個任務(wù)-idle task-它只在沒有其他任務(wù)執(zhí)行的時候才被執(zhí)行。RTOS idle task 總是處于可以執(zhí)行的狀態(tài)(注:也就是它不可能會因為等待什么外設(shè)資源而被阻塞,而是處于一種隨時待命的狀
16、態(tài)).上圖中:1. 在最開始,我們的兩個任務(wù)都不能被執(zhí)行-vControlTask等待合適(correct)的時間開始新的控制循環(huán),vKeyHandlerTask等待鍵盤按下。處理器時間分配給 RTOS的idle task.2. 在t1時刻,一個鍵盤按下(事件)出現(xiàn). VKeyHandlerTask任務(wù)現(xiàn)在可以執(zhí)行,它比RTOS的idle task有更高的優(yōu)先級,所以處理器時間給它。3. 在t2時刻,vKeyHandlerTask已經(jīng)完成了對按鍵的處理,并更新了LCD。它不能繼續(xù),直到另一個鍵被按下,所以必須掛起它自己。RTOS idle task又被恢復(fù)執(zhí)行。4
17、. 在t3時刻,一個定時器事件預(yù)示(indicates),可以執(zhí)行下一個控制循環(huán)了。VControlTask現(xiàn)在可以執(zhí)行,作為最高優(yōu)先級的任務(wù)被立刻分配(scheduled)到處理器時間。5. 在t3和t4之間,當(dāng)vControlTask任務(wù)還在執(zhí)行的時候,一個鍵按下。VKeyHandlerTask不能被執(zhí)行,因為它沒有vControlTask的優(yōu)先級高。不能分配(scheduled)到任何處理器時間。6. 在t4時刻,vControlTask完成了控制循環(huán)的處理,不能夠重新開始,直到下一個時間事件出現(xiàn),所以它自己掛起自己。而vKeyHandlerTask現(xiàn)在是最
18、高優(yōu)先級的任務(wù),可以運行了,所以,為了處理先前的鍵盤事件,分配(scheduled)到了處理器時間.7. 在t5時刻,鍵盤已經(jīng)被處理。VkeyHandlerTask為了等待下一個鍵盤事件,自己掛起自己。現(xiàn)在,我們的兩個任務(wù)再度不能執(zhí)行了。RTOS idle task分配到處理器時間。8. 在t5和t6之間,一個定時器事件被處理,但是沒有更多的鍵盤事件出現(xiàn)。9. 下一個鍵盤按下出現(xiàn)在t6時刻,但在vKeyHandlerTask完成處理鍵之前,一個定時器事件出現(xiàn)了。現(xiàn)在兩個任務(wù)都能被執(zhí)行,而vControlTask比vKeyHandlerTask 有更多的優(yōu)先級,所以
19、vKeyHandlerTask在它完成處理鍵盤之前就被掛起了。VControlTask分配到處理器時間。10. 在t8時刻,vControlTask完成處理控制循環(huán),掛起自己以等待下一個事件。VKeyHandlerTask再次成為最高優(yōu)先級的任務(wù),能夠運行,所以分配到處理器時間,從而鍵盤按下事件 處理能夠完成。RTOS實現(xiàn)模塊(Building Block)詳細(xì)實例(Detailed Example)這一節(jié)從底向上描述了RTOS上下文切換的源代碼。使用FreeRTOS Atmel AVR微控制器移植的代碼作為例子。本節(jié)的最后還一步一步地瀏覽(step by step look)了一個
20、完整的上下文切換。C開發(fā)工具FreeRTOS的目標(biāo)是簡單且易于理解。為了達(dá)到這個目標(biāo)(To this end),RTOS的源代碼的大部分都是用C寫的,而不是匯編。這里演示的例子使用了 WinAVR development tools。 WinAVR是一個自由/免費的在windows下的AVR交叉編譯器,它是基于GCC的。RTOS Tick睡眠時,一個任務(wù)將指定多長時間后它會醒來。阻塞時,一個任務(wù)將指定一個 希望最多等多久的時間。FreeRTOS實時內(nèi)核用tick count變量 來度量時間的。定時器中斷(RTOS tick interrupt) 用嚴(yán)格的時間精度(temporal accura
21、cy )來增加 tick count- 允許實時內(nèi)核 用一個指定的 定時器中斷頻率的精度(resolution)來測量 時間。每次tick count增加后,實時內(nèi)核 必須檢查,看現(xiàn)在是否 解除阻塞 或者 喚醒 一個任務(wù)。一個 比被中斷的任務(wù)有更高的優(yōu)先級的 任務(wù) 在 tick ISR期間 被 喚醒或者解除阻塞 是可能的。如果是這種情況,tick ISR應(yīng)該返回到新的喚醒/解鎖的任務(wù)-實際(effectively)中斷一個任務(wù),卻返回到另一個任務(wù)。如下所述:上圖提到的幾個點:1) RTOS idle task正在運行2) RTOS tick出現(xiàn),控制轉(zhuǎn)移到tic
22、k ISR(3)3) RTOS tick ISR使得vControlTask準(zhǔn)備運行,當(dāng)vControlTask比RTOS idle task有更高的優(yōu)先級,切換上下文到 vControlTask.。4) 現(xiàn)在的執(zhí)行上下文是vControlTask的。從ISR(4)退出 返回到vControlTask,vControlTask從(5)開始執(zhí)行。以這種方式出現(xiàn)的上下文切換,稱為Preemptive。 因為被中斷的任務(wù) 沒有自愿(voluntarily)地掛起它自己就被搶占了(preempted)。FreeRTOS的AVR移植版本 用一個在定時器1(timer1)的比較匹配(c
23、ompare match)事件來產(chǎn)生RTOS tick. 后續(xù)將描述RTOS tick ISR是如何用WinAVR開發(fā)工具實現(xiàn)的。GCC信號屬性(Signal Attribute)GCC development tools允許用C來寫中斷程序。一個在AVR 定時器1外設(shè)的比較匹配事件 可以用下面的 語法(syntax)實現(xiàn):void SIG_OUTPUT_COMPARE1A( void ) _attribute_ ( ( signal ) );void SIG_OUTPUT_COMPARE1A( void ) /* ISR C code for
24、RTOS tick. */ vPortYieldFromTick();在函數(shù)原型前的 '_attribute_ ( ( signal ) )' 指示符 告知 編譯器,這個函數(shù)是一個ISR,會引起編譯器輸出的兩個重要改變:1. signal屬性保證,每個在ISR 期間 被修改的 處理器的寄存器,在從ISR中退出時恢復(fù)到它原來的值。這就要求,當(dāng)中斷將要執(zhí)行時,編譯器不能做任何假定。所以,不能優(yōu)化哪個處理器寄存器要求保護或者不保護。 2'signal'也強制使用 一個 從中斷返回('return from int
25、errupt')指令(RETI),而不是返回(return)指令RET. AVR微控制器 在進入ISR前禁止中斷,RETI指令要求在 退出時重新打開中斷。下面是由編譯器輸出的代碼:;void SIG_OUTPUT_COMPARE1A( void ); ; - ; CODE GENERATED BY THE COMPILER TO SAVE ; THE REGISTERS THAT GET ALTERED BY THE ; APPLI
26、CATION CODE DURING THE ISR. PUSH R1 PUSH R0 IN R0,0x3F
27、0; PUSH R0 CLR R1 PUSH
28、; R18 PUSH R19 PUSH R20
29、; PUSH R21 PUSH R22
30、160; PUSH R23 PUSH R24 PUSH R25
31、60; PUSH R26 PUSH R27 &
32、#160; PUSH R30 PUSH R31 ; - ; COD
33、E GENERATED BY THE COMPILER FROM THE ; APPLICATION C CODE. ;vTaskIncrementTick(); CALL 0x0000029B ;Call subroutine; ; - ; CODE GENERATED BY THE COMPILER TO
34、 ; RESTORE THE REGISTERS PREVIOUSLY ; SAVED. POP R31 POP R30
35、; POP R27 POP R26
36、0; POP R25 POP R24 POP
37、 R23 POP R22 POP R21
38、160; POP R20 POP R19 &
39、#160; POP R18 POP R0 OUT
40、0; 0x3F,R0 POP R0 POP R1 RETI
41、 ; -GCC Naked 屬性前一節(jié)講述了如何在C中用 signal屬性來寫一個ISR.,以及它是如何使 執(zhí)行上下文自動保存的(只有那些被ISR修改過的處理器寄存器才會得到保存)。然而,執(zhí)行一個上下文切換需要保存完整的上下文。應(yīng)用程序代碼能夠 在進入ISR時,明確(explicitly)地 保存所有寄存器,但是這樣會使 某些處理器寄存器 保存兩次-一次是由編譯器生成的代碼,另一次是由應(yīng)用程序自己。這不是我們所需要的,可以在'signal'屬性后 添加
42、39;naked'屬性來避免:void SIG_OUTPUT_COMPARE1A( void ) _attribute_ ( ( signal, naked ) );void SIG_OUTPUT_COMPARE1A( void ) /* ISR C code for RTOS tick. */ vPortYieldFromTick();'naked'屬性阻止編譯器生成任何函數(shù)入口或退出代碼。現(xiàn)在變異這段代碼,會得到更少的編譯器輸出:;void SIG_OUTPUT_COMPARE1A( void
43、); ; - ; NO COMPILER GENERATED CODE HERE TO SAVE ; THE REGISTERS THAT GET ALTERED BY THE ; ISR. ; - ; CODE GENERATED BY THE COMPILER FROM THE ; APPLICATION C CODE.
44、0; ;vTaskIncrementTick(); CALL 0x0000029B ;Call subroutine ; - ; NO COMPILER GENERATED CODE HERE TO RESTORE ; THE REGISTERS OR RETURN FROM THE ISR. ;
45、-;看看,入口 和 出口代碼都沒有了吧使用 naked 屬性,編譯器不會生成任何入口和出口代碼,所以必須明確(explicitly)加入。portSAVE_CONTEXT()和portRESTORE_CONTEXT()這兩個宏 是用來保存和恢復(fù)完整的執(zhí)行上下文的:void SIG_OUTPUT_COMPARE1A( void ) _attribute_ ( ( signal, naked ) );void SIG_OUTPUT_COMPARE1A( void ) /* Macro that explicitly saves the execution
46、60; context. */ portSAVE_CONTEXT(); /* ISR C code for RTOS tick. */ vPortYieldFromTick(); /* Macro that explicitly restores the execution context. */ portRESTORE_CONTEXT(); &
47、#160; /* The return from interrupt call must also be explicitly added. */ asm volatile ( "reti" );naked屬性給了應(yīng)用程序完整的控制權(quán),在何時 ,怎么樣保存AVR的上下文。如果應(yīng)用程序代碼在進入ISR前保存了完整的上下文,在執(zhí)行上下文切換時不必再保存,所以不會有處理器的寄存器被保存兩次。FreeRTOS Tick CodeFreeRTOS的AVR移植版本的實際源代碼 與 前一節(jié)的例子有些輕微的
48、不同。VPortYieldFromTick()是作為一個naked函數(shù)的 它自己的實現(xiàn),上下文在vPortYieldFromTick().里被保存和恢復(fù)。這樣做的目的是為了實現(xiàn)一個non-preemptive的上下文切換(這里,一個任務(wù)自己阻塞自己).這里暫時不講這種non-preemptive切換。RTOS tick是這樣在FreeRTOS中實現(xiàn)的(看代碼中注釋片斷獲取更多細(xì)節(jié)):void SIG_OUTPUT_COMPARE1A( void ) _attribute_ ( ( signal, naked ) );void vPortYieldFromTick( void ) _attrib
49、ute_ ( ( naked ) );/*-*/* RTOS tick中斷服務(wù)程序. */void SIG_OUTPUT_COMPARE1A( void ) /*調(diào)用tick函數(shù). */vPortYieldFromTick();/*從中斷返回. 如果出現(xiàn)上下文切換,將返回到一個不同的任務(wù)中 */ asm volatile ( "reti" );/*-*/void vPortYieldFromTick( void ) /* 這是一個naked 函數(shù),所以需要保存上下文
50、*/portSAVE_CONTEXT();/* 增加tick count,檢查新的tick count值是否引起一個延遲周期過期,這個函數(shù)調(diào)用可導(dǎo)致一個任務(wù)變成準(zhǔn)備運行. */vTaskIncrementTick();/*檢查是否要求上限文切換。如果 由vTaskIncrementTick()準(zhǔn)備好的任務(wù)比已經(jīng)中斷的任務(wù)有更高優(yōu)先級,就切換過去 */vTaskSwitchContext();/*恢復(fù)上下文.如果發(fā)生了上下文切換,這將恢復(fù)要繼續(xù)運行的任務(wù)的上下文 */portRESTORE_CONTEXT();/*從這naked 函數(shù)返回. */ asm vo
51、latile ( "ret" );/*-*/The AVR Context上下文切換要求保存完整的上下文。在AVR MCU中,上下文包括1 32位通用寄存器。Gcc開發(fā)工具假定寄存器R1設(shè)定為02 狀態(tài)寄存器。狀態(tài)寄存器的值影響指令的執(zhí)行,必須通過上下文切換保存(preserved)3 程序計數(shù)器(PC).恢復(fù)執(zhí)行后,一個任務(wù)必須從上次被掛起的地方繼續(xù)執(zhí)行。(a task must continue execution from the instruction that was about to be executed immediately
52、prior to its suspension.)4 兩個stack指針寄存器Saving the Context每個時實任務(wù)都有它自己的stack 內(nèi)存區(qū)域,所以上下文可 簡單的通過將寄存器壓入到任務(wù)棧 來保存上下文。保存AVR的上下文是一個不可避免的要使用到匯編語言的地方。portSAVE_CONTEXT() 是作為一個宏來實現(xiàn)的,源代碼在下面給出#define portSAVE_CONTEXT() asm volatile (
53、; "push r0 nt" (1) "in r0,
54、 _SREG_ nt" (2) "cli nt" (3) "push r0
55、60; nt" (4) "push r1 nt" (5) "clr r1
56、0; nt" (6) "push r2 nt" (7) "push r3
57、0; nt" "push r4 nt" "push r5
58、0; nt" : : : "push r30
59、60; nt" "push r31 nt" "lds r26, pxCurrentTCB nt" (8) "lds r27, pxCurrentTCB + 1 nt
60、" (9) "in r0, _SP_L_ nt" (10) "st x+, r0 nt" (11) "in
61、r0, _SP_H_ nt" (12) "st x+, r0 nt" (13);在上面的源代碼中:1 寄存器R0首先被保存,因為當(dāng)狀態(tài)寄存器被保存時,它會被用到。所以必須先把它的原始值保存下來。2 狀態(tài)寄存器被搬移
62、到 R0 (2),所以它能保存到stack (4)3 禁止處理器中斷。如果portSAVE_CONTEXT(),只是從ISR中調(diào)用,就不需要明確的禁止中斷,因為AVR已經(jīng)這么做了。portSAVE_CONTEXT()宏用在中斷服務(wù)程序的外部(一個任務(wù)自己掛起自己的時候),中斷應(yīng)該盡可能早的明確清除(也就是禁止中斷 CLI)4 從ISR 的C源代碼中,由編譯器生成的代碼假定R1被設(shè)置為0。R1的原始值 在R1被清除(6)前保存(5)5. 在(7)和(8),所有寄存器都被按順序保存6. 現(xiàn)在被掛起的任務(wù)的棧中還有一個任務(wù)執(zhí)行上下文的
63、拷貝。內(nèi)核保存任務(wù)的棧指針,所以 當(dāng)任務(wù)恢復(fù)執(zhí)行時,上下文可以取得并恢復(fù)。The X processor register is loaded with the address to which the stack pointer is to be saved (8 and 9). 載入棧指針7. 棧指針保存,先低位(10,11)后高位(12 13)Restoring the ContextportRESTORE_CONTEXT()是portSAVE_CONTEXT().的逆過程。要恢復(fù)執(zhí)行的任務(wù)的上下文被預(yù)先存儲到任務(wù)棧中。實時內(nèi)核為該任務(wù)取得棧指針,然后彈出POP上下文到
64、0; 正確的寄存器中。#define portRESTORE_CONTEXT() asm volatile ( "lds r26, pxCurrentTCB nt" (1) "lds r27, pxCurrentTCB + 1 nt" (2) "ld
65、 r28, x+ nt" "out _SP_L_, r28 nt" (3) "ld r29, x+
66、160; nt" "out _SP_H_, r29 nt" (4) "pop r31 nt"
67、; "pop r30 nt" : : : "pop r1
68、0; nt" "pop r0 nt" (5) "out _SREG_, r0 nt" (6) "po
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 思政館設(shè)計合同協(xié)議
- 2025電子競技俱樂部技術(shù)轉(zhuǎn)讓合同
- 正規(guī)民宿轉(zhuǎn)讓合同協(xié)議
- 2025企業(yè)環(huán)境保護經(jīng)濟責(zé)任合同范文
- 2025寧波存量房買賣合同模板
- 員工終止合同協(xié)議
- 2025勞動合同法中關(guān)于加班工作時間的規(guī)定
- 2025標(biāo)準(zhǔn)的服務(wù)合同范本
- 2025網(wǎng)絡(luò)證券交易合同模板
- 2025室內(nèi)廣告位租賃合同范本
- 租電動車電子合同協(xié)議
- 紡織服裝產(chǎn)業(yè)鏈的韌性及其空間演變研究
- 福建省漳州地區(qū)校聯(lián)考2024-2025學(xué)年七年級下學(xué)期期中考試語文試卷(含答案)
- 2025年便利店店員勞動合同
- 2025-2030中國公路瀝青行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略研究報告
- 2025年人教版五年級(下)期中數(shù)學(xué)試卷
- GB/T 196-2025普通螺紋基本尺寸
- 2025年陜西省漢中市寧強縣中考一模道德與法治試題(含答案)
- 快遞云倉合同協(xié)議
- 2025-2030功能性飼料行業(yè)市場發(fā)展分析及發(fā)展前景與投資機會研究報告
- 江蘇省常州市2024-2025學(xué)年高一下學(xué)期4月期中考試英語試題(含答案)
評論
0/150
提交評論