前言
本系列文章將以RTA-OS為例詳細(xì)介紹AUTOSAR OS標(biāo)準(zhǔn)及概念,并分享實(shí)際使用的一些案例,本文為符合AUTOSAR標(biāo)準(zhǔn)的RTA-OS--Task介紹。
符合AUTOSAR標(biāo)準(zhǔn)的RTA-OS --功能簡介
正文
2.任務(wù)Task
必須同時(shí)執(zhí)行許多不同活動(dòng)的系統(tǒng)稱為并發(fā)。這些活動(dòng)可能包含一些軟件部分,因此提供這些活動(dòng)的程序必須同時(shí)執(zhí)行。這些程序必須在任何必要的時(shí)候進(jìn)行合作,例如,當(dāng)它們需要共享數(shù)據(jù)時(shí)。
實(shí)時(shí)系統(tǒng)中的每個(gè)并發(fā)活動(dòng)都由一個(gè)任務(wù)來表示。大多數(shù)應(yīng)用程序代碼都存在于任務(wù)中。如果有許多必須同時(shí)執(zhí)行的任務(wù),那么將需要提供一種允許并發(fā)性的方法。其中一種方法是為每個(gè)任務(wù)都有一個(gè)單獨(dú)的處理器??梢允褂貌⑿杏?jì)算機(jī),但這個(gè)解決方案對(duì)許多應(yīng)用程序來說太昂貴了。
實(shí)現(xiàn)并發(fā)行為的一個(gè)更經(jīng)濟(jì)有效的方法是在單個(gè)處理器上一次運(yùn)行一個(gè)任務(wù)。然后可以在任務(wù)之間切換,以便它們看起來同時(shí)執(zhí)行。
2.1 調(diào)度Scheduling
RTA-OS提供了一個(gè)調(diào)度器,它根據(jù)在配置時(shí)分配的固定優(yōu)先級(jí)在任務(wù)之間切換。優(yōu)先級(jí)只是反映了任務(wù)的相對(duì)緊迫性。可以使用許多方案來分配任務(wù)的優(yōu)先級(jí),常見方案有:
Deadline Monotonic Assignment: 更高的優(yōu)先級(jí)被分配給最后期限較短的任務(wù)。
Rate Monotonic Assignment: 更高的優(yōu)先級(jí)被分配給需要更頻繁地運(yùn)行的任務(wù)。
無論選擇分配優(yōu)先級(jí),任務(wù)執(zhí)行的順序由調(diào)度策略決定。調(diào)度策略決定任務(wù)何時(shí)實(shí)際運(yùn)行。
AUTOSAR操作系統(tǒng)支持兩種調(diào)度策略:
1.搶占式調(diào)度Preemptive Scheduling.
固定優(yōu)先級(jí)搶占式調(diào)度算法很簡單:運(yùn)行準(zhǔn)備運(yùn)行的最高優(yōu)先級(jí)任務(wù)。如果任務(wù)正在運(yùn)行,而優(yōu)先級(jí)較高的任務(wù)準(zhǔn)備運(yùn)行,則優(yōu)先級(jí)較高的任務(wù)優(yōu)先于正在運(yùn)行的任務(wù)。這叫做任務(wù)切換。當(dāng)高優(yōu)先級(jí)任務(wù)完成后,搶占任務(wù)恢復(fù)。
對(duì)于所有任務(wù)都需要在運(yùn)行時(shí)滿足其最后期限的系統(tǒng),搶占式的調(diào)度是最有效的調(diào)度策略,并將保證任務(wù)被激活(準(zhǔn)備運(yùn)行)和終止之間的最短時(shí)間。這個(gè)時(shí)間被稱為對(duì)該任務(wù)的響應(yīng)時(shí)間。搶占式調(diào)度的系統(tǒng)需要考慮搶占對(duì)共享數(shù)據(jù)的影響,并且可能需要引入并發(fā)控制機(jī)制。
圖2.1 任務(wù)的搶占式調(diào)度
2.非搶占式調(diào)度 Non-Preemptive scheduling.
操作系統(tǒng)運(yùn)行優(yōu)先級(jí)已準(zhǔn)備運(yùn)行的最高任務(wù),和搶占式調(diào)度一樣。然而,搶占式調(diào)度不同的是,如果一個(gè)更高優(yōu)先級(jí)的任務(wù)準(zhǔn)備好了,那么它就會(huì)一直準(zhǔn)備好運(yùn)行,直到正在運(yùn)行的任務(wù)終止——它不會(huì)搶占正在允許的低優(yōu)先級(jí)的任務(wù)。這意味著,開始運(yùn)行的非搶占式任務(wù)將始終運(yùn)行到完成,然后終止。
非搶占式調(diào)度導(dǎo)致系統(tǒng)比搶占式調(diào)度的響應(yīng)性更低(即任務(wù)通常有更長的響應(yīng)時(shí)間),但系統(tǒng)不需要擔(dān)心訪問共享數(shù)據(jù)時(shí)出現(xiàn)的并發(fā)問題,因?yàn)檎{(diào)度模型不允許并發(fā)訪問共享數(shù)據(jù)。
實(shí)際上,AUTOSAR OS提供了第三種類型的調(diào)度支持,因?yàn)樗试S非搶占任務(wù)告訴操作系統(tǒng)什么時(shí)候可以被搶占。我們說AUTOSAR操作系統(tǒng)支持2個(gè)策略的原因是只有兩個(gè)配置——第三個(gè)配置,必須自己構(gòu)建。
圖2.2 任務(wù)的非搶占式調(diào)度
3.協(xié)同調(diào)度Cooperative scheduling.
操作系統(tǒng)將運(yùn)行優(yōu)先級(jí)最高的準(zhǔn)備運(yùn)行的任務(wù)。如果一個(gè)更高優(yōu)先級(jí)的任務(wù)準(zhǔn)備好了,那么它會(huì)一直準(zhǔn)備運(yùn)行直到:正在運(yùn)行的任務(wù)終止(就像非搶占式調(diào)度);或者正在運(yùn)行的任務(wù)調(diào)用Schedule() API來告訴操作系統(tǒng)它可以被搶占。當(dāng)Schedule()調(diào)用時(shí),高優(yōu)先級(jí)任務(wù)搶占正在運(yùn)行的任務(wù),任務(wù)切換就發(fā)生了(就像搶占調(diào)度一樣)。當(dāng)高優(yōu)先級(jí)任務(wù)完成后,被搶占的任務(wù)恢復(fù)。
通過仔細(xì)的設(shè)計(jì),協(xié)同模式提供的系統(tǒng)雖然不像完全搶占式系統(tǒng)那樣響應(yīng)迅速,但不會(huì)像非搶占式調(diào)度那樣缺乏響應(yīng)能力。
圖2.3 任務(wù)的協(xié)同調(diào)度
對(duì)于所有這些類型的調(diào)度,重要的是要意識(shí)到任何任務(wù),無論是否搶占人,都可以被中斷服務(wù)例程中斷(搶占)。
2.2基本和擴(kuò)展任務(wù)Basic and Extended Tasks
RTAOS支持兩種類型的Task:
l基本任務(wù)Basic Task
基本任務(wù)的開始、執(zhí)行和結(jié)束(通常稱為單次任務(wù)模式)。一個(gè)基本任務(wù)只有在它被終止或被一個(gè)更高優(yōu)先級(jí)的任務(wù)搶占時(shí)才釋放處理器。這種行為使它們非常適合嵌入式控制功能?;救蝿?wù)是快速高效的。
l擴(kuò)展任務(wù)Extended Task
擴(kuò)展任務(wù)啟動(dòng)、執(zhí)行、等待事件和(可選)終止。擴(kuò)展任務(wù)在執(zhí)行期間自動(dòng)掛起自身的能力為任務(wù)提供了一種具有同步點(diǎn)的方法。這個(gè)特性使得擴(kuò)展任務(wù)比基本任務(wù)更適合需要執(zhí)行中間同步的功能(例如,等待用戶交互)。
2.2.1 任務(wù)狀態(tài)Task State
基本任務(wù)在三狀態(tài)模型上運(yùn)行?;救蝿?wù)有以下幾種狀態(tài):
l掛起Suspended
l準(zhǔn)備Ready
l允許Running
擴(kuò)展任務(wù)可以在等待事件時(shí)進(jìn)入一個(gè)額外的狀態(tài):
l等待Waiting
圖2.4展示了任務(wù)3或者4狀態(tài)模型。
所有任務(wù)的默認(rèn)狀態(tài)是掛起。任務(wù)通過激活過程進(jìn)入就緒狀態(tài)。重要的是要理解激活并不會(huì)導(dǎo)致任務(wù)運(yùn)行——它只是讓任務(wù)準(zhǔn)備好運(yùn)行。激活可以通過多種方式發(fā)生,例如在代碼中調(diào)用ActivateTask()API,或者作為某些觸發(fā)器的結(jié)果,例如警報(bào)(Alarm)到期或調(diào)度表到期點(diǎn)( schedule table expiry point)。
當(dāng)一個(gè)任務(wù)成為系統(tǒng)中優(yōu)先級(jí)最高的任務(wù)時(shí),RTA-OS將該任務(wù)移至運(yùn)行狀態(tài),并在任務(wù)中的第一條語句開始執(zhí)行任務(wù)。這通常被稱為調(diào)度任務(wù)。一個(gè)任務(wù)可能在執(zhí)行過程中被其他準(zhǔn)備就緒的高優(yōu)先級(jí)任務(wù)搶占。
圖2.4 任務(wù)狀態(tài)模型
如果有更高優(yōu)先級(jí)的任務(wù)準(zhǔn)備運(yùn)行,則當(dāng)前正在執(zhí)行的任務(wù)將被搶占,并從運(yùn)行狀態(tài)移至就緒狀態(tài)。這意味著在同一時(shí)間內(nèi)只能有一個(gè)任務(wù)處于運(yùn)行狀態(tài)。
任務(wù)終止后返回掛起狀態(tài)。任務(wù)可以在以后再次準(zhǔn)備好,整個(gè)過程可以重復(fù)。
基本任務(wù)和擴(kuò)展任務(wù)在準(zhǔn)備、運(yùn)行和掛起狀態(tài)方面表現(xiàn)相同。但是,擴(kuò)展任務(wù)也可以進(jìn)入等待狀態(tài)。當(dāng)擴(kuò)展任務(wù)通過等待事件自動(dòng)掛起自己時(shí),它將從運(yùn)行狀態(tài)轉(zhuǎn)移到等待狀態(tài)。
事件只是一個(gè)OS對(duì)象,用于為系統(tǒng)事件提供指示器。事件的例子包括數(shù)據(jù)準(zhǔn)備使用或傳感器值正在讀取。
當(dāng)擴(kuò)展任務(wù)進(jìn)入等待狀態(tài)時(shí),操作系統(tǒng)將分派準(zhǔn)備運(yùn)行的最高優(yōu)先級(jí)任務(wù)。當(dāng)設(shè)置事件時(shí),任務(wù)將從等待狀態(tài)移動(dòng)到準(zhǔn)備狀態(tài)。注意,擴(kuò)展任務(wù)返回到就緒狀態(tài),而不是運(yùn)行狀態(tài)。這是因?yàn)椋跀U(kuò)展任務(wù)處于等待狀態(tài)期間,其他一些更高優(yōu)先級(jí)的任務(wù)可能已經(jīng)被激活,然后被分派。
2.2.2 任務(wù)優(yōu)先級(jí)Task Priorities
AUTOSAR OS允許任務(wù)共享優(yōu)先級(jí)。當(dāng)任務(wù)具有相同優(yōu)先級(jí)時(shí),具有共享優(yōu)先級(jí)的每個(gè)任務(wù)將相互排斥運(yùn)行。這意味著如果一個(gè)任務(wù)正在運(yùn)行,那么它的執(zhí)行將與所有其他具有相同優(yōu)先級(jí)的任務(wù)序列化。
當(dāng)任務(wù)共享優(yōu)先級(jí)時(shí),它們將按照先進(jìn)先出(FIFO)的順序從就緒狀態(tài)釋放。
Note:當(dāng)共享優(yōu)先級(jí)和排隊(duì)任務(wù)激活一起使用時(shí),RTA-OS在優(yōu)先級(jí)級(jí)別上維護(hù)一個(gè)內(nèi)部隊(duì)列。如果想要一個(gè)快速高效的操作系統(tǒng),你應(yīng)該避免這種類型的配置。
如果需要序列化一組任務(wù)的執(zhí)行,那么最好使用惟一的優(yōu)先級(jí)和AUTOSAR OS的內(nèi)部資源來實(shí)現(xiàn),而不是共享任務(wù)優(yōu)先級(jí)。使用內(nèi)部資源保證了序列化,就像共享優(yōu)先級(jí)一樣,任務(wù)優(yōu)先級(jí)的唯一性意味著當(dāng)多個(gè)任務(wù)同時(shí)就緒時(shí),操作系統(tǒng)有一個(gè)靜態(tài)定義的分派順序。
Note:在任務(wù)之間共享優(yōu)先級(jí)是一種糟糕的實(shí)時(shí)編程實(shí)踐,因?yàn)樗鼤?huì)阻止您在系統(tǒng)上執(zhí)行可調(diào)度性分析。這是因?yàn)?,在一般情況下,共享優(yōu)先級(jí)使得任務(wù)的釋放點(diǎn)(即測量響應(yīng)時(shí)間的點(diǎn))在計(jì)算上無法計(jì)算。如果不可能計(jì)算出何時(shí)發(fā)布,那么就不可能決定任務(wù)是否會(huì)在截止日期前完成!
2.2.3 任務(wù)隊(duì)列激活Queued Task Activation
在大多數(shù)情況下,只能在任務(wù)處于掛起狀態(tài)時(shí)激活它。AUTOSAR OS在任務(wù)處于就緒、運(yùn)行或等待狀態(tài)時(shí)將其激活視為錯(cuò)誤情況。
然而,在某些情況下,我們可能需要實(shí)現(xiàn)這樣一個(gè)系統(tǒng):相同的任務(wù)必須多次激活,但連續(xù)激活之間的最短時(shí)間可能小于運(yùn)行任務(wù)所需的時(shí)間。例如,您可能正在一個(gè)任務(wù)中解包CAN總線幀,并且需要處理網(wǎng)絡(luò)上幀的瞬時(shí)爆發(fā)( transient bursting)。
這意味著我們需要在運(yùn)行時(shí)排隊(duì)等待任務(wù)激活。AUTOSAR OS操作系統(tǒng)允許排隊(duì)激活基本任務(wù),以幫助構(gòu)建這類應(yīng)用程序。與自動(dòng)共享操作系統(tǒng)中的其他東西一樣,任務(wù)隊(duì)列的大小也是靜態(tài)配置的。我們必須指定該任務(wù)可以掛起的最大激活數(shù)。
如果在嘗試激活任務(wù)時(shí)隊(duì)列已滿,則這將作為錯(cuò)誤處理,激活將被忽略。
當(dāng)然,您可能會(huì)有共享優(yōu)先級(jí)并使用隊(duì)列激活的任務(wù)。在這種情況下,任務(wù)按FIFO順序在一個(gè)隊(duì)列中排隊(duì),其長度等于共享相同優(yōu)先級(jí)的每個(gè)任務(wù)的隊(duì)列長度之和。但是,每個(gè)任務(wù)只能使用它自己的條目數(shù)量。
2.2.4 異步任務(wù)激活A(yù)synchronous Task Activation
AUTOSAR OS允許從內(nèi)核激活任務(wù),而不是任務(wù)實(shí)際運(yùn)行的內(nèi)核。雖然這可能很有用,但可能會(huì)有性能影響,因?yàn)橐耆嫒軦UTOSAR,所有任務(wù)激活(包括SetEvent)必須阻塞調(diào)用方,直到任務(wù)狀態(tài)更新。在內(nèi)部,操作系統(tǒng)必須使用內(nèi)部自旋鎖與擁有的核協(xié)調(diào)狀態(tài)更改。這可能會(huì)對(duì)所有核的性能產(chǎn)生重大影響。
RTA-OS提供了一個(gè)OS選項(xiàng)異步任務(wù)激活,它改變了激活的行為,這樣就不會(huì)阻塞內(nèi)核,而是將消息發(fā)送到擁有要激活任務(wù)的內(nèi)核上的隊(duì)列。擁有的核心是執(zhí)行任務(wù)的實(shí)際激活的核心,因此它是唯一更改任務(wù)狀態(tài)的核心。不使用任務(wù)自旋鎖,因?yàn)椴恍枰Wo(hù)任何狀態(tài)。
任務(wù)激活隊(duì)列的大小默認(rèn)設(shè)置為10。如果該隊(duì)列已滿,則返回錯(cuò)誤碼E_OS_SYS_XCORE_QFULL。隊(duì)列大小可以使用AsyncQ OS選項(xiàng)更改。
Note: 當(dāng)選擇異步TASK激活時(shí),E_OS_LIMIT指示會(huì)在擁有該任務(wù)的核上發(fā)出,而不是在激活它的核上。
2.3 一致性類Conformance Classes
我們現(xiàn)在知道,任務(wù)可以:
l基本的或擴(kuò)展的
l可以共享優(yōu)先級(jí)
l可以排隊(duì)激活
然而,AUTOSAR操作系統(tǒng)對(duì)一起使用的特性進(jìn)行了一些限制。這些特性被稱為一致性類,用于對(duì)任務(wù)特征進(jìn)行分組,以便于理解,支持標(biāo)準(zhǔn)的部分實(shí)現(xiàn),并為不同類別的應(yīng)用程序提供了可伸縮性。
AUTOSAR操作系統(tǒng)有四個(gè)一致性類:
BCC1-基本任務(wù),唯一的優(yōu)先級(jí)和沒有排隊(duì)的激活( Basic tasks, unique priority and no queued activation).
BCC2- 基本任務(wù)、共享優(yōu)先級(jí)和/或排隊(duì)激活(Basic tasks, shared priorities and/or queued activation).
ECC1- 擴(kuò)展的任務(wù),唯一的優(yōu)先級(jí)和沒有排隊(duì)的激活。ECC1任務(wù)類似于BCC1任務(wù),但它可以等待事件(Extended tasks, unique priority and no queued activation. An ECC1 task is like
a BCC1 task, but it can wait on events.)
ECC2- 擴(kuò)展的任務(wù),共享的優(yōu)先級(jí)和沒有排隊(duì)的激活。請(qǐng)注意,與BCC2任務(wù)不同,ECC2任務(wù)不能排隊(duì)激活(Extended tasks, shared priorities and no queued activation. Note that, unlike
BCC2 tasks, ECC2 tasks cannot queue activations.)
下表給出了可以在不同類型的AUTOSAR操作系統(tǒng)中使用的任務(wù)類型的快速摘要:
每個(gè)一致性級(jí)別都需要更多的資源——BCC1的系統(tǒng)將比ECC2的系統(tǒng)更快更小。您不需要關(guān)心使用哪個(gè)一致性類- RTA-OS支持所有一致性類,并將從您的操作系統(tǒng)配置中計(jì)算一致性類。
1但僅針對(duì)ECC2系統(tǒng)中的基本任務(wù)。擴(kuò)展任務(wù)的激活不能被排隊(duì)。
2.4 最大化性能和最小化內(nèi)存Maximizing Performance and Minimizing Memory
RTA-OS被設(shè)計(jì)成非常積極地最小化目標(biāo)應(yīng)用程序上的代碼和數(shù)據(jù)使用。它將分析應(yīng)用程序的特性,并生成一個(gè)只包含所需特性的系統(tǒng)。
任務(wù)特征的選擇對(duì)最終應(yīng)用程序的大小和速度有很大影響。所以當(dāng)你在應(yīng)用程序中添加使用更高級(jí)任務(wù)類型的任務(wù)時(shí),系統(tǒng)將不可避免地變得稍微大一點(diǎn)和慢一點(diǎn)。
具有一個(gè)或多個(gè)BCC2任務(wù)的系統(tǒng)比僅具有BCC1任務(wù)的系統(tǒng)具有更大的開銷。一個(gè)沒有共享優(yōu)先級(jí)的系統(tǒng),即使允許進(jìn)行多個(gè)激活,也將比一個(gè)具有共享優(yōu)先級(jí)的系統(tǒng)更有效。
帶有ECC1任務(wù)的系統(tǒng)開銷更大,而具有一個(gè)或多個(gè)ECC2任務(wù)的系統(tǒng)開銷是最大的。
為了使RTA-OS盡可能高效,您應(yīng)該只使用基本任務(wù),而不是共享優(yōu)先級(jí)。
2.5 任務(wù)配置Task Confifiguration
與您可能見過的其他實(shí)時(shí)操作系統(tǒng)不同,AU TOSAR OS(因此,RTA-OS)中的任務(wù)是靜態(tài)定義的。
這種技術(shù)被廣泛使用,因?yàn)樗?jié)省了RAM和執(zhí)行時(shí)間。
任務(wù)不能動(dòng)態(tài)創(chuàng)建或銷毀。關(guān)于任務(wù)的大部分信息可以離線計(jì)算,允許它存儲(chǔ)在ROM中。
RTA-OS支持的最大任務(wù)數(shù)取決于您的端口,您應(yīng)該參考目標(biāo)/編譯器端口指南了解更多細(xì)節(jié)。
對(duì)于所有端口,RTA-OS可以提供一個(gè)高度優(yōu)化的系統(tǒng),如果你限制你的任務(wù)數(shù)量到你的微控制器的本機(jī)字大小。
在配置任務(wù)屬性時(shí),您很可能會(huì)使用rtaoscfg配置工具。圖2.5顯示了任務(wù)配置條目。
圖2.5 任務(wù)配置
一個(gè)AUTOSAR任務(wù)有5個(gè)屬性:
Name.該名稱用于引用或提供要用來實(shí)現(xiàn)任務(wù)功能的C代碼的句柄。
Priority.調(diào)度程序使用優(yōu)先級(jí)來確定任務(wù)何時(shí)運(yùn)行。優(yōu)先值不能動(dòng)態(tài)更改。在RTA-OS中,0是最低的任務(wù)優(yōu)先級(jí)。更高的任務(wù)優(yōu)先級(jí)由更大的整數(shù)表示。任務(wù)可以共享優(yōu)先級(jí),但如果您正在構(gòu)建一個(gè)實(shí)時(shí)系統(tǒng),那么就不應(yīng)該這樣做,因?yàn)樗荒鼙环治觥?/p>
Scheduling.任務(wù)可以完全搶先運(yùn)行,也可以非搶先運(yùn)行。一般來說,為了獲得最佳的應(yīng)用程序性能,應(yīng)該選擇完全搶占式調(diào)度而不是非搶占式調(diào)度。
Activations.可在就緒狀態(tài)下排隊(duì)的任務(wù)激活的最大數(shù)量。對(duì)于一個(gè)BCC1、ECC1和ECC2任務(wù),激活的次數(shù)為1。這意味著這些類型的任務(wù)只有在處于掛起狀態(tài)時(shí)才能被激活。任何嘗試在未掛起的情況下激活這樣的任務(wù)都會(huì)導(dǎo)致錯(cuò)誤。大于1的值表示操作系統(tǒng)將排隊(duì)激活(例如平滑應(yīng)用程序中的瞬時(shí)峰值負(fù)載)。
Autostart.這將控制在啟動(dòng)操作系統(tǒng)時(shí)是否自動(dòng)啟動(dòng)任務(wù)。
Note: 可以為每個(gè)目標(biāo)定義的任務(wù)的數(shù)量是固定的(通常是256或1024,這取決于目標(biāo)處理器)。目標(biāo)的目標(biāo)/編譯器端口指南將包含更多的信息。
2.5.1 調(diào)度策略Scheduling Policy
完全可搶占的任務(wù)可以被更高優(yōu)先級(jí)的任務(wù)搶占。這意味著當(dāng)一個(gè)更高優(yōu)先級(jí)的任務(wù)準(zhǔn)備好運(yùn)行時(shí),它將優(yōu)先運(yùn)行。
可以通過在配置時(shí)將任務(wù)聲明為不可搶占來防止其被搶占。聲明為非搶占的任務(wù)不能被其他任務(wù)搶占。當(dāng)一個(gè)非搶占任務(wù)移動(dòng)到運(yùn)行狀態(tài)時(shí),它將運(yùn)行到完成,然后終止(除非它進(jìn)行Schedule()調(diào)用)。因此,使任務(wù)具有非搶占性意味著,如果低優(yōu)先級(jí)任務(wù)在高優(yōu)先級(jí)任務(wù)之前啟動(dòng),那么在低優(yōu)先級(jí)任務(wù)運(yùn)行期間,高優(yōu)先級(jí)任務(wù)將被阻止執(zhí)行。這叫做阻塞。通常情況下,使用非搶占式任務(wù)的系統(tǒng)比搶先式運(yùn)行的系統(tǒng)響應(yīng)速度要慢。
即使一個(gè)任務(wù)不是可搶占的,它仍然可以被ISR中斷。
使用不可搶占的任務(wù)是不必要的,因?yàn)橛衅渌线m的方法可以用來實(shí)現(xiàn)相同的效果。如果使用這些其他技術(shù),通常會(huì)產(chǎn)生一個(gè)響應(yīng)性更強(qiáng)的系統(tǒng)。稍后將介紹更多關(guān)于這些技巧的內(nèi)容,其中包括:
l使用標(biāo)準(zhǔn)資源來序列化對(duì)數(shù)據(jù)或設(shè)備的訪問。
l使用內(nèi)部資源來精確地指定哪些其他任務(wù)不能導(dǎo)致?lián)屨肌?/p>
2.5.2 排隊(duì)激活Queued Activation
在大多數(shù)情況下,只有在任務(wù)處于掛起狀態(tài)時(shí)才會(huì)激活它。但是,可能需要實(shí)現(xiàn)一個(gè)系統(tǒng),其中同一任務(wù)必須被激活多次,并且連續(xù)激活之間的最短時(shí)間小于運(yùn)行任務(wù)所需的時(shí)間。
如果發(fā)生這種情況,將在任務(wù)處于就緒狀態(tài)或運(yùn)行狀態(tài)時(shí)激活該任務(wù)。這意味著激活將會(huì)丟失。
要防止失去激活,必須指定任務(wù)所需的多次激活的最大激活數(shù)。
Note: 根據(jù)AUTOSAR操作系統(tǒng)標(biāo)準(zhǔn),此功能僅可用于基本任務(wù)。您不能為擴(kuò)展的任務(wù)指定多個(gè)激活。
您將使用rtaoscfg指定同時(shí)激活任務(wù)的最大數(shù)量。圖2.6顯示,對(duì)于本例中的任務(wù),最大激活次數(shù)已設(shè)置為20。
圖2.6 指定排隊(duì)激活的數(shù)量
當(dāng)指定多個(gè)激活時(shí),RTA-OS會(huì)自動(dòng)識(shí)別該任務(wù)是BCC2。在構(gòu)建應(yīng)用程序時(shí),RTA-OS將計(jì)算每個(gè)BCC2任務(wù)所需的多個(gè)激活隊(duì)列的最大大小。
當(dāng)BCC2任務(wù)共享優(yōu)先級(jí)時(shí),RTA-OS使用FIFO隊(duì)列來保存掛起的激活。如果一個(gè)BCC2任務(wù)在您的AUTOSAR OS應(yīng)用程序中具有唯一的優(yōu)先級(jí),那么RTA-OS將自動(dòng)優(yōu)化排隊(duì)策略以計(jì)數(shù)激活。計(jì)數(shù)激活法比先進(jìn)先出激活法效率高得多,應(yīng)在任何可能的地方使用。
2.5.3 自動(dòng)啟動(dòng)任務(wù)Auto-starting Tasks
任務(wù)可以自動(dòng)啟動(dòng),這意味著當(dāng)操作系統(tǒng)啟動(dòng)時(shí),它們將在StartOS()期間自動(dòng)激活。
對(duì)于啟動(dòng)、運(yùn)行然后終止的基本任務(wù),自動(dòng)啟動(dòng)任務(wù)將使它只運(yùn)行一次,然后才返回掛起狀態(tài)(在那里它可以再次被激活)。
自動(dòng)啟動(dòng)主要用于啟動(dòng)等待事件的擴(kuò)展任務(wù),因?yàn)樗恍枰帉懘a來激活任務(wù)。
Rtaoscfg可用于指定任務(wù)僅在特定應(yīng)用程序模式下自動(dòng)激活,選擇相關(guān)的應(yīng)用程序模式并選擇您希望自動(dòng)激活的任務(wù)。
在圖2.7中,TaskD在OSDEFAULTAPPMODE和ServiceMode應(yīng)用程序模式下是自動(dòng)啟動(dòng)的,而在LimpHomeMode和NormalOperatingMode下不是自動(dòng)啟動(dòng)的。
圖2.7 配置自動(dòng)啟動(dòng)的任務(wù)
2.6 棧管理Stack Management
RTA-OS使用單堆棧模型,這意味著所有任務(wù)和ISR都運(yùn)行在單個(gè)堆棧上。單個(gè)堆棧就是應(yīng)用程序的C堆棧。
當(dāng)任務(wù)運(yùn)行時(shí),它的堆棧使用量會(huì)正常增長和減少。當(dāng)任務(wù)被搶占時(shí),更高優(yōu)先級(jí)任務(wù)的堆棧使用將繼續(xù)在同一堆棧上進(jìn)行(就像標(biāo)準(zhǔn)函數(shù)調(diào)用一樣)。當(dāng)任務(wù)終止時(shí),它所使用的堆??臻g將被回收,然后重新用于運(yùn)行下一個(gè)最高優(yōu)先級(jí)的任務(wù)(同樣,就像標(biāo)準(zhǔn)函數(shù)調(diào)用一樣)。圖2.8顯示了單個(gè)堆棧在聲明、搶占和終止任務(wù)時(shí)的行為。
圖2.8 單堆棧行為
在單堆棧模型中,堆棧大小與系統(tǒng)中優(yōu)先級(jí)的數(shù)量成正比,而不是任務(wù)/ ISR的數(shù)量。這意味著共享優(yōu)先級(jí)的任務(wù),無論是直接共享,還是通過共享內(nèi)部資源,或者通過配置為非搶占,都不能同時(shí)在堆棧上。在硬件上共享優(yōu)先級(jí)的ISR也是如此。這意味著您可以通過簡單地更改配置來交換系統(tǒng)響應(yīng)性(即任務(wù)或ISR完成所需的時(shí)間),以換取堆??臻g。
圖2.9顯示了相同任務(wù)集的執(zhí)行,具有與圖2.8相同的到達(dá)模式,但這次任務(wù)是非搶先調(diào)度的。您可以看到,高優(yōu)先級(jí)任務(wù)的響應(yīng)時(shí)間比t時(shí)要長得多,但總體堆棧消耗要低得多。
單堆棧模型還顯著簡化了鏈接時(shí)的堆??臻g分配,因?yàn)槟恍枰獮檎麄€(gè)系統(tǒng)堆棧分配一個(gè)內(nèi)存部分,就像您完全不使用操作系統(tǒng)一樣。
2.6.1 使用擴(kuò)展任務(wù)Working with Extended Tasks
RTA-OS獨(dú)特地?cái)U(kuò)展了單堆棧模型,以提供對(duì)擴(kuò)展任務(wù)的支持,而對(duì)基本任務(wù)的性能沒有任何影響。
在RTA-OS中,擴(kuò)展任務(wù)的生命周期如下:
Suspended ? Ready該任務(wù)將被添加到已準(zhǔn)備就緒的隊(duì)列中。
Ready ? Running任務(wù)被分派了,但與基本任務(wù)不同的是,上下文被放置在堆棧的頂部,上下文被放置在堆??臻g中,位于所有低優(yōu)先級(jí)任務(wù)的預(yù)先計(jì)算的最壞情況搶占深度。
Running ? Ready擴(kuò)展任務(wù)被搶占。如果搶占任務(wù)是一個(gè)基本任務(wù),那么它將正常地在堆棧頂部分派。如果搶占任務(wù)是一個(gè)擴(kuò)展任務(wù),那么它將按照所有低優(yōu)先級(jí)任務(wù)預(yù)先計(jì)算的最壞情況搶占深度進(jìn)行分派。
Running ? Waiting任務(wù)的等待事件堆棧上下文,包括操作系統(tǒng)上下文、本地?cái)?shù)據(jù)、函數(shù)調(diào)用的堆棧幀等,被保存到一個(gè)內(nèi)部操作系統(tǒng)緩沖區(qū)。
圖2.9 具有非搶占式任務(wù)的單堆棧行為
Waiting ? Ready該任務(wù)將被添加到已準(zhǔn)備就緒的隊(duì)列中。
Ready ? Running任務(wù)的“等待事件堆?!鄙舷挛膹膬?nèi)部操作系統(tǒng)緩沖區(qū)復(fù)制到堆棧中,并以所有低優(yōu)先級(jí)任務(wù)的預(yù)先計(jì)算的最壞情況搶占深度進(jìn)行計(jì)算。
此流程允許管理擴(kuò)展任務(wù)的額外成本僅應(yīng)用于擴(kuò)展任務(wù)本身。包含擴(kuò)展任務(wù)的系統(tǒng)中的基本任務(wù)與僅包含基本任務(wù)的系統(tǒng)具有相同的性能。
這個(gè)生命周期的關(guān)鍵部分是在最壞情況下的分派/恢復(fù),以及在堆棧上和從堆棧上復(fù)制。在最壞情況搶占點(diǎn)的分派可以保證,無論何時(shí)擴(kuò)展任務(wù)在等待后恢復(fù),它都可以在內(nèi)存中完全相同的位置恢復(fù)其局部變量。它保證了低優(yōu)先級(jí)任務(wù)的每種可能的搶占模式都不會(huì)超過擴(kuò)展任務(wù)的分派點(diǎn)。擴(kuò)展任務(wù)D的調(diào)度-等待-恢復(fù)周期如圖2.10所示。
復(fù)制和打開允許恢復(fù)擴(kuò)展任務(wù)堆棧上下文。這是必要的,因?yàn)楦邇?yōu)先級(jí)任務(wù)和/或isr可能在擴(kuò)展任務(wù)等待時(shí)發(fā)生。這些可能會(huì)消耗比最壞情況搶占點(diǎn)更大的堆棧空間(記住,最壞情況搶占點(diǎn)只適用于較低優(yōu)先級(jí)的對(duì)象),因此會(huì)超過寫入擴(kuò)展任務(wù)的上下文。但是,固定優(yōu)先級(jí)搶占調(diào)度。
圖2.10 具有擴(kuò)展任務(wù)的單堆棧管理
保證在擴(kuò)展任務(wù)恢復(fù)時(shí)沒有更高優(yōu)先級(jí)的任務(wù)可以準(zhǔn)備好運(yùn)行(如果是這種情況,它就不能恢復(fù))。
擴(kuò)展任務(wù)管理需要告訴RTA-OS任務(wù)和ISR使用了多少堆棧。下面幾節(jié)描述各種配置參數(shù)。
2.6.2 強(qiáng)制性堆棧信息Mandatory Stack Information
計(jì)算出的最壞情況分派點(diǎn)定義了字節(jié)數(shù),相對(duì)于調(diào)用StartOS()時(shí)堆棧指針的地址,擴(kuò)展任務(wù)需要從該地址開始。這些偏移量作為ROM數(shù)據(jù)存儲(chǔ)在擴(kuò)展任務(wù)控制塊中,并在運(yùn)行時(shí)添加到堆棧的基址中。
這意味著需要告訴RTA-OS有關(guān)堆棧使用的各種參數(shù)。捕獲的值是特定于端口的,您應(yīng)該閱讀您的端口的目標(biāo)/編譯器端口指南以獲得額外的指導(dǎo)。
RTA-OS提供了運(yùn)行時(shí)特性,用于測量任務(wù)和ISR的最壞情況下的堆棧值。
通常,所有端口都將允許您指定以下值。所有數(shù)字均以字節(jié)為單位:
用于C啟動(dòng)的堆棧(Stack used for C-startup,SpPreStartOS)在調(diào)用StartOS()時(shí)已經(jīng)在使用的堆棧量。
該值被簡單地添加到操作系統(tǒng)在運(yùn)行時(shí)支持所有任務(wù)和中斷所需的總堆棧大小中。
通常,您使用它來獲得鏈接器必須分配的堆棧數(shù)量。
在計(jì)算最壞情況分派點(diǎn)時(shí)不需要這個(gè)值,可以安全地將其設(shè)置為零,除非您希望在堆棧使用情況報(bào)告中計(jì)算最壞情況的總體堆棧使用情況。
正常情況下,當(dāng)操作系統(tǒng)配置發(fā)生變化時(shí),該值不會(huì)改變。
空閑時(shí)使用的堆棧(Stack used when idle,SpStartOS)
操作系統(tǒng)處于空閑狀態(tài)(通常在Os_Cbk_Idle()內(nèi)部)時(shí)使用的最大堆棧量。這只是調(diào)用StartOS()時(shí)使用的堆棧與沒有任務(wù)或中斷運(yùn)行時(shí)使用的堆棧之間的區(qū)別。如果沒有使用Os_Cbk_Idle(),該值可以為零。它必須包含在空閑狀態(tài)下被調(diào)用的任何函數(shù)所使用的堆棧。
正常情況下,當(dāng)操作系統(tǒng)配置發(fā)生變化時(shí),該值不會(huì)改變。
ISR激活的堆棧開銷(Stack overheads for ISR activation,SpIDisp)
與從task中激活任務(wù)相比,從ISR中激活任務(wù)所需的額外堆棧量。如果一個(gè)任務(wù)在類別2 ISR中被激活,并且該任務(wù)比任何當(dāng)前運(yùn)行的任務(wù)具有更高的優(yōu)先級(jí),那么對(duì)于一些與激活優(yōu)先級(jí)較低的任務(wù)相比,目標(biāo)操作系統(tǒng)可能需要使用更多的堆棧。這個(gè)值說明了這一點(diǎn)。在大多數(shù)目標(biāo)上,這個(gè)值為零。
該值用于最壞情況下的堆棧大小計(jì)算。
當(dāng)操作系統(tǒng)配置有較大變化時(shí),該值可能會(huì)發(fā)生變化。
ECC任務(wù)的堆棧開銷(Stack overheads for ECC tasks,SpECC)
啟動(dòng)ECC任務(wù)所需的額外堆棧量。ECC任務(wù)在啟動(dòng)時(shí)需要比BCC任務(wù)在堆棧上保存更多的狀態(tài)。此值包含差值。
這個(gè)值可以通過測量堆棧值得到:
l在基本任務(wù)(向上)激活之前,立即在被激活任務(wù)的入口函數(shù)中。
l在擴(kuò)展任務(wù)(向上)激活之前,立即在激活任務(wù)的入口函數(shù)中。
然后用第一個(gè)值減去第二個(gè)值。
當(dāng)操作系統(tǒng)配置有較大變化時(shí),該值可能會(huì)發(fā)生變化。還需要注意的是,如果你正在使用堆棧重定位(將不受信任的代碼堆棧對(duì)齊以適應(yīng)MPU),那么你將需要減少調(diào)整量的值。
ISR的堆棧開銷(Stack overheads for ISR SpPreemption)
圖2.11 基本堆棧值
用于服務(wù)第二類ISR的堆棧數(shù)量。當(dāng)二類ISR中斷一個(gè)任務(wù)時(shí),它通常會(huì)在堆棧上放置一些數(shù)據(jù)。如果ISR測量堆棧以確定被搶占的任務(wù)是否超過了它的堆棧預(yù)算,那么它將高估堆棧使用情況,除非從測量的大小中減去這個(gè)值。
該值也用于計(jì)算系統(tǒng)最壞情況下的堆棧使用情況。該值可以通過在中斷之前測量堆棧值,并在測試期間立即在類別2 ISR的輸入函數(shù)中獲得。注意要準(zhǔn)確地設(shè)置這個(gè)值。如果它的值太高,那么當(dāng)發(fā)生減法時(shí),就會(huì)發(fā)生32位下溢,并導(dǎo)致操作系統(tǒng)認(rèn)為已經(jīng)檢測到預(yù)算超支。
當(dāng)操作系統(tǒng)配置有較大變化時(shí),該值可能會(huì)發(fā)生變化。
Note: 除了ISR (SpPreemption)的堆棧開銷外,所有的強(qiáng)制堆棧值都會(huì)在檢查期間添加到堆棧值中。這意味著指定比實(shí)際發(fā)生的更大的值是安全的。但是,ISR的堆棧開銷(SpPreemption)將從進(jìn)入ISR時(shí)的堆棧指針的當(dāng)前值中減去,以檢查被搶占的任務(wù)或ISR是否已經(jīng)超過了它的堆棧使用量。因此,在這里指定一個(gè)大的值可能會(huì)導(dǎo)致報(bào)告一個(gè)沒有發(fā)生的錯(cuò)誤(即RTA-OS堆棧管理將報(bào)告一個(gè)“false positive”。
2.6.3 指定任務(wù)堆棧分配Specifying Task Stack Allocation
在只包含基本任務(wù)的系統(tǒng)中,沒有必要告訴RTA-OS任何堆棧分配,除非正在進(jìn)行堆棧監(jiān)控。只需要在鏈接器/定位器中為應(yīng)用程序分配一個(gè)足夠大的堆棧部分。這是單棧架構(gòu)的好處之一。
對(duì)于使用擴(kuò)展任務(wù)的應(yīng)用程序,可以像以前一樣分配鏈接器部分,但是還必須告訴RTA-OS配置中優(yōu)先級(jí)低于最高優(yōu)先級(jí)擴(kuò)展任務(wù)的每個(gè)任務(wù)的堆棧分配,即使它們是基本任務(wù)。RTA-OS使用堆棧分配信息為每個(gè)離線擴(kuò)展任務(wù)計(jì)算最壞情況下的搶占點(diǎn)。
指定的堆棧分配是用于該任務(wù)的整個(gè)堆棧,包括:
?操作系統(tǒng)上下文
?任務(wù)主體中局部變量的空間
?任務(wù)體中調(diào)用的任何函數(shù)(以及它們的局部函數(shù))所需的空間
可以使用RTA-OS的堆棧度量特性來獲取堆棧分配的準(zhǔn)確值。
Note: RTA-OS僅使用提供的堆棧信息來計(jì)算最壞情況下的搶占點(diǎn)。RTA-OS不保留任何堆??臻g。必須按照與普通應(yīng)用程序相同的方式指定堆棧應(yīng)用程序堆棧空間。
圖2.12顯示了如何配置堆棧分配。
圖2.12 堆棧分配配置Stack Allocation Configuration
雖然RTA-OS使用單堆棧模型,但在某些端口上,這并不一定意味著只使用一個(gè)物理堆棧。
可能是編譯器或硬件自動(dòng)將數(shù)據(jù)強(qiáng)制放到不同的堆棧上。例如,TriCore設(shè)備使用CSA內(nèi)存快速保存呼叫上下文。RTA-OS將其視為等同于堆棧。當(dāng)在你的配置中輸入堆棧值時(shí),你應(yīng)該提供兩個(gè)逗號(hào)分隔的值;第一個(gè)用于Supervisor堆棧,第二個(gè)用于Context堆棧。
即使有多個(gè)物理堆棧,RTA-OS仍然提供了單一堆棧架構(gòu)的好處——當(dāng)任務(wù)和/或isr共享優(yōu)先級(jí)時(shí),每個(gè)物理堆棧上所需的堆棧空間可以疊加。但是,為了使堆棧分配正確工作,您需要指定每個(gè)堆棧上所需的空間。
如果您配置了需要此信息的目標(biāo),RTA-OS將要求您提供多個(gè)堆棧值。圖2.13顯示了這樣一個(gè)配置的對(duì)話框,其中有兩個(gè)堆棧:' Supervisor '和' Context '。
圖2.13針對(duì)多個(gè)堆棧的堆棧分配配置Stack Allocation Configuration for multiple stacks
圖2.14 指定WaitEvent()堆棧分配
2.6.4 優(yōu)化擴(kuò)展任務(wù)上下文保存Optimizing the Extended Task context save
回顧第2.6.1節(jié),每當(dāng)擴(kuò)展任務(wù)進(jìn)入等待狀態(tài)時(shí),RTA-OS保存任務(wù)的“等待事件堆棧”上下文,當(dāng)任務(wù)重新進(jìn)入運(yùn)行狀態(tài)時(shí),上下文將恢復(fù)。
RTA-OS將“等待事件堆?!鄙舷挛谋4嬖趦?nèi)部緩沖區(qū)中。默認(rèn)情況下,RTAOS分配的緩沖區(qū)等于您為該任務(wù)指定的最壞情況堆棧分配。假設(shè)您的堆棧分配是正確的,這應(yīng)該總是足以在調(diào)用WaitEvent()時(shí)保持最壞情況下的堆棧使用情況。
不過,大多數(shù)使用擴(kuò)展任務(wù)的應(yīng)用程序通常只從任務(wù)的入口函數(shù)調(diào)用WaitEvent()。此時(shí),堆棧上只有少量本地?cái)?shù)據(jù)(可能為零)。在使用擴(kuò)展任務(wù)時(shí),您可以通過僅分配足夠的緩沖區(qū)空間來保存最壞情況下的“等待事件堆?!鄙舷挛?,而不是任務(wù)所需的絕對(duì)最壞情況空間,從而最小化RTA-OS預(yù)留的RAM大小。
可以通過在WaitEvent()執(zhí)行時(shí)給出RTA-OS最差的值(圖4.14)來指定為這個(gè)緩沖區(qū)保留多少字節(jié)。請(qǐng)記住,最壞情況的值可能包括WaitEvent()調(diào)用本身使用的一些堆棧。獲得正確值的一種方法是從一個(gè)小值開始,一直增加它,直到在Os_Cbk_StackOverrunHook()調(diào)用中不再看到OS_ECC_WAIT錯(cuò)誤。如果無法保存堆棧上下文,RTA-OS將不會(huì)將ECC TASK置于等待狀態(tài)。
Note: 如果保留等待事件()堆棧分配為“未定義的”,那么RTA-OS將默認(rèn)使用您為堆棧分配指定的字節(jié)數(shù)。
使用默認(rèn)值
雖然您應(yīng)該為每個(gè)任務(wù)設(shè)置一個(gè)堆棧值,但RTA-OS允許您設(shè)置一個(gè)被所有任務(wù)使用的全局默認(rèn)值。這可以在常規(guī)?默認(rèn)堆棧值中找到。
如果沒有為任務(wù)配置堆棧分配,則RTA-OS將使用默認(rèn)值:
l計(jì)算最壞情況下的堆棧偏移量
l配置等待事件(WaitEvent())保存/恢復(fù)區(qū)域
l堆棧監(jiān)控(當(dāng)配置時(shí))
特定于任務(wù)/ ISR的堆棧分配的規(guī)范將覆蓋默認(rèn)值。
2.6.5 處理堆棧溢出Handling Stack Overrun
如果您提供給RTA-OS的堆棧分配數(shù)字是錯(cuò)誤的(即它們太小),那么在運(yùn)行時(shí)這是一個(gè)潛在的錯(cuò)誤來源。
有三件事可能會(huì)出錯(cuò):
1. 當(dāng)RTA-OS試圖分發(fā)補(bǔ)丁擴(kuò)展任務(wù)時(shí),由于堆棧指針的當(dāng)前值高于計(jì)算出的最壞情況分派點(diǎn),因此無法啟動(dòng)擴(kuò)展任務(wù)。這意味著堆棧上的一個(gè)(或多個(gè))低優(yōu)先級(jí)任務(wù)消耗了太多空間。
后面章節(jié)中描述的堆棧監(jiān)視可用于確定哪個(gè)任務(wù)出現(xiàn)故障。
2. 擴(kuò)展任務(wù)不能從等待狀態(tài)恢復(fù),因?yàn)槎褩V羔樃哂谒鼞?yīng)有的位置。當(dāng)為擴(kuò)展任務(wù)正在等待的事件調(diào)用SetEvent()并且擴(kuò)展任務(wù)現(xiàn)在是系統(tǒng)中最高優(yōu)先級(jí)的任務(wù)時(shí),可能會(huì)發(fā)生這種情況。
3.擴(kuò)展任務(wù)不能進(jìn)入等待狀態(tài),因?yàn)樵撊蝿?wù)當(dāng)前使用的堆棧數(shù)量大于配置的' WaitEvent()堆棧'的大小。
當(dāng)RTA-OS檢測到擴(kuò)展任務(wù)堆棧管理的問題時(shí),它將調(diào)用ShutdownOS(),錯(cuò)誤代碼為E_OS_STACKFAULT。
如果你想調(diào)試這個(gè)問題,那么你可以啟用堆棧故障鉤子,如圖2.15所示。
圖2.15 使能Os_Cbk_StackOverrunHook()
#ifdef OS_STACKOVERRUNHOOK FUNC(void, OS_CALLOUT_CODE) Os_Cbk_StackOverrunHook(Os_StackSizeType Overrun, Os_StackOverrunType Reason) { /* Identify problem */ for(;;) { /* Do not return! */ } } #endif /* OS_STACKOVERRUNHOOK */
Example 2.1: Minimum recommended Os_Cbk_StackOverrunHook()
當(dāng)配置了Os_Cbk_StackOverrunHook(),當(dāng)發(fā)生堆棧故障時(shí),RTA-OS將調(diào)用用戶提供的回調(diào)Os_Cbk_StackOverrunHook(),而不是關(guān)閉OS()。該回調(diào)被傳遞了兩個(gè)參數(shù):
1.溢出數(shù)的字節(jié)數(shù)
2.溢出原因
對(duì)于未啟用堆棧監(jiān)視的擴(kuò)展任務(wù)系統(tǒng),溢出可以是以下情況之一:
?OS_ECC_START—擴(kuò)展任務(wù)無法啟動(dòng),因?yàn)楫?dāng)前堆棧指針超過了構(gòu)建時(shí)計(jì)算的最壞情況分派點(diǎn)。此故障的原因是一個(gè)(或多個(gè))低優(yōu)先級(jí)任務(wù)超過了配置的堆棧分配。要解決這個(gè)問題,您需要確定哪個(gè)任務(wù)出錯(cuò)了。棧監(jiān)控和測量章節(jié)解釋了如何使用RTA-OS的堆棧監(jiān)視特性來做到這一點(diǎn)。
?OS_ECC_RESUME—擴(kuò)展任務(wù)不能從等待中恢復(fù),因?yàn)楫?dāng)前堆棧指針超過了構(gòu)建時(shí)計(jì)算的最壞情況分派點(diǎn)。此故障的原因是一個(gè)(或多個(gè))低優(yōu)先級(jí)任務(wù)超過了配置的堆棧分配。
要解決這個(gè)問題,您需要確定哪個(gè)任務(wù)出錯(cuò)了。棧監(jiān)控和測量章節(jié)解釋了如何使用RTA-OS的堆棧監(jiān)視特性來做到這一點(diǎn)。
?OS_ECC_WAIT—擴(kuò)展任務(wù)使用的堆??臻g超過WaitEvent()設(shè)置的堆棧大小,無法進(jìn)入等待狀態(tài)。要解決這個(gè)問題,您應(yīng)該至少將WaitEvent()堆棧大小增加到溢出參數(shù)所指示的字節(jié)數(shù)。
2.7 實(shí)現(xiàn)任務(wù)Implementing Tasks
任務(wù)類似于C函數(shù),當(dāng)它們被RTA-OS調(diào)用時(shí),它會(huì)實(shí)現(xiàn)某種形式的系統(tǒng)功能。
TASK(task_identifier) { /* Your code */ }
Note: 不需要為任務(wù)輸入功能提供任何C函數(shù)原型。這些都是通過RTA-OS生成的Os.h頭文件提供的。
當(dāng)任務(wù)開始運(yùn)行時(shí),將從任務(wù)輸入函數(shù)開始執(zhí)行。任務(wù)輸入函數(shù)是使用示例2.2中的C語法編寫的。
請(qǐng)記住,基本的任務(wù)是一次性的。這意味著它們從固定的任務(wù)入口點(diǎn)執(zhí)行,并在完成后終止。
示例2.3顯示了一個(gè)名為BCC_Task的基本任務(wù)的代碼。
#include
Example 2.3: A Basic Task
現(xiàn)在,將示例2.3中的示例與示例2.4進(jìn)行比較。示例2.4顯示,擴(kuò)展的任務(wù)不一定需要終止,并且可以保持在一個(gè)循環(huán)中等待事件。
#include
Example 2.4: Extended Task Waiting for Events
2.8 激活任務(wù)Activating Tasks
任務(wù)只有激活后才能運(yùn)行。激活可以將任務(wù)從掛起狀態(tài)移動(dòng)到就緒狀態(tài),也可以將另一個(gè)條目添加到就緒任務(wù)隊(duì)列(如果任務(wù)支持多個(gè)激活)。該任務(wù)將為每個(gè)激活運(yùn)行一次。
超過激活計(jì)數(shù)是一個(gè)錯(cuò)誤,當(dāng)這種情況發(fā)生時(shí),應(yīng)用程序?qū)⑸蒃_OS_LIMIT錯(cuò)誤(即使在標(biāo)準(zhǔn)構(gòu)建狀態(tài)下)。
任務(wù)可以從兩個(gè)任務(wù)和(第2類)ISRs中激活。
激活任務(wù)并不會(huì)使任務(wù)立即開始執(zhí)行,它只是使任務(wù)準(zhǔn)備好運(yùn)行。然而,RTA-OS需要檢查激活的任務(wù)是否比當(dāng)前運(yùn)行的任務(wù)具有更高的優(yōu)先級(jí),如果是,則導(dǎo)致上下文切換,以便新任務(wù)可以搶占當(dāng)前運(yùn)行的任務(wù)。
當(dāng)您從另一個(gè)任務(wù)激活一個(gè)任務(wù)RTA-OS時(shí),確切的行為取決于相對(duì)的任務(wù)優(yōu)先級(jí)。如果激活的任務(wù)優(yōu)先級(jí)高于當(dāng)前運(yùn)行的任務(wù),則新激活的任務(wù)將搶占當(dāng)前任務(wù)。否則,該任務(wù)將保持在就緒隊(duì)列中,直到它成為最高優(yōu)先級(jí)的就緒任務(wù)。在一個(gè)設(shè)計(jì)良好的實(shí)時(shí)系統(tǒng)中,一個(gè)任務(wù)激活一個(gè)更高優(yōu)先級(jí)的任務(wù)是不尋常的。通常isr捕獲系統(tǒng)觸發(fā)器,然后激活任務(wù)以執(zhí)行任何相關(guān)處理。反過來,這些任務(wù)可能激活較低優(yōu)先級(jí)的任務(wù),以實(shí)現(xiàn)具有較長截止日期的觸發(fā)器響應(yīng)。
觀察這一事實(shí)導(dǎo)致了RTA-OS中的一個(gè)主要優(yōu)化。如果指定任務(wù)從不激活高優(yōu)先級(jí)任務(wù),RTA-OS可以消除測試每次激活后是否需要上下文切換的內(nèi)部代碼。這是通過選擇“禁止向上激活”優(yōu)化來配置的。
這類似于從ISR激活任務(wù)時(shí)的行為。所有ISR都有一個(gè)嚴(yán)格高于最高任務(wù)優(yōu)先級(jí)的優(yōu)先級(jí)。
當(dāng)一個(gè)任務(wù)從ISR激活時(shí),它永遠(yuǎn)不會(huì)立即進(jìn)入運(yùn)行狀態(tài),因此不需要檢查上下文切換。
只有在離開ISR時(shí)才需要這樣的檢查。
2.8.1 直接激活Direct Activation
任務(wù)可以通過許多不同的方式激活。任務(wù)激活的基本機(jī)制是ActivateTask() API調(diào)用,它直接激活任務(wù)。ActivateTask(TaskID)調(diào)用將指定任務(wù)置于就緒狀態(tài)。ChainTask(TaskID)調(diào)用終止了調(diào)用任務(wù)(見2.11節(jié)),并將命名任務(wù)置于就緒狀態(tài)。
2.8.2 間接激活I(lǐng)ndirect Activation
除了直接激活任務(wù)外,還可以使用其他AUTOSAR OS機(jī)制間接激活任務(wù)。這些方法在后面的章節(jié)中有更詳細(xì)的描述。
報(bào)警激活(Activation by an Alarm)。對(duì)于系統(tǒng)中的每個(gè)告警,您可以指定每次告警過期時(shí)激活的任務(wù)。
#include
Example 2.5: Using Direct Activation Chains
通過調(diào)度表激活(Activation by a Schedule Table)。對(duì)于系統(tǒng)中的每個(gè)調(diào)度表,可以指定在表上的一個(gè)或多個(gè)到期點(diǎn)上激活的任務(wù)。
2.9 控制任務(wù)執(zhí)行順序Controlling Task Execution Ordering
在許多情況下,您需要限制特定任務(wù)的執(zhí)行順序。在基于數(shù)據(jù)流的設(shè)計(jì)中尤其如此,其中一個(gè)任務(wù)需要在另一個(gè)任務(wù)使用計(jì)算值之前執(zhí)行一些計(jì)算。如果執(zhí)行順序不受約束,則可能出現(xiàn)競態(tài)條件,應(yīng)用程序行為將不可預(yù)知??梢酝ㄟ^以下方式控制任務(wù)的執(zhí)行順序:
?直接激活鏈(見2.9.1節(jié))。
?優(yōu)先級(jí)(見章節(jié)2.9.2)。
?非搶占任務(wù)
2.9.1 直接激活鏈Direct Activation Chains
當(dāng)使用直接激活鏈來控制執(zhí)行順序時(shí),任務(wù)對(duì)必須在進(jìn)行調(diào)用的任務(wù)之后執(zhí)行的任務(wù)執(zhí)行ActivateTask()調(diào)用。
有三個(gè)任務(wù)Task1、Task2和Task3,它們必須按照Task1、Task2、Task3的順序執(zhí)行。
示例2.5給出了任務(wù)體示例。
圖2.16顯示了假設(shè)Task1優(yōu)先級(jí)最高,Task 3優(yōu)先級(jí)最低,這些任務(wù)將如何執(zhí)行。
圖2.16 控制任務(wù)執(zhí)行順序的直接激活
2.9.2 使用優(yōu)先級(jí)Using Priority Levels
約束任務(wù)執(zhí)行順序的優(yōu)先級(jí)級(jí)方法可以用來利用搶占調(diào)度策略的性質(zhì)來控制激活順序。
回顧第2.1節(jié),在固定優(yōu)先級(jí)搶占調(diào)度下,調(diào)度器總是運(yùn)行最高優(yōu)先級(jí)的任務(wù)。如果許多任務(wù)被釋放到就緒隊(duì)列中,它們將按優(yōu)先級(jí)順序執(zhí)行。這意味著您可以使用任務(wù)優(yōu)先級(jí)來控制執(zhí)行順序。
從前面的例子來看,在例2.5中,讓我們假設(shè)Task1的優(yōu)先級(jí)最高,Task3的優(yōu)先級(jí)最低。這意味著可以重寫任務(wù)主體以利用優(yōu)先級(jí)控制的激活。這可以在例2.6中看到。
圖2.17顯示了如何執(zhí)行這些任務(wù)。
#include
Example 2.6: Using Priority Level Controlled Activation
圖2.17 使用優(yōu)先級(jí)來控制任務(wù)的執(zhí)行順序
2.10 RTA-OS中的合作調(diào)度Co-operative Scheduling in RTA-OS
當(dāng)一個(gè)任務(wù)是非搶占式運(yùn)行時(shí),它會(huì)阻止任何任務(wù)(包括那些高優(yōu)先級(jí)的任務(wù))的執(zhí)行。然而,有時(shí)對(duì)于非搶占式任務(wù)來說,提供可以進(jìn)行重調(diào)度的顯式位置是有用的。這比簡單地非搶先運(yùn)行更有效,因?yàn)楦邇?yōu)先級(jí)任務(wù)對(duì)系統(tǒng)刺激的響應(yīng)時(shí)間更短。在一個(gè)系統(tǒng)中,任務(wù)以非搶先的方式運(yùn)行,并為重新調(diào)度提供點(diǎn),這種系統(tǒng)被稱為協(xié)作調(diào)度系統(tǒng)。
Schedule() API調(diào)用可用于暫時(shí)消除非搶占任務(wù)和使用內(nèi)部資源的任務(wù)施加的搶占約束。
當(dāng)調(diào)用Schedule()時(shí),允許運(yùn)行任何優(yōu)先級(jí)高于調(diào)用任務(wù)的就緒任務(wù)。Schedule()直到所有高優(yōu)先級(jí)任務(wù)結(jié)束才返回。
例2.7展示了一個(gè)非搶占任務(wù)Cooperative,它包括一系列函數(shù)調(diào)用。一旦啟動(dòng),每個(gè)函數(shù)運(yùn)行到完成時(shí)不會(huì)搶占,但是任務(wù)本身可以在每個(gè)函數(shù)調(diào)用之間被搶占。
圖2.18顯示了Task1和Task2這兩個(gè)相互協(xié)作的任務(wù)在戰(zhàn)時(shí)如何發(fā)揮作用。白色部分表示不可搶占的代碼部分。
#include
Example 2.7: Making a task run co-operatively
圖2.18 合作任務(wù)Co-operative tasks
2.10.1 優(yōu)化Schedule() API Optimizing out the Schedule() API
Schedule()在完全搶占式系統(tǒng)中沒有用處。如果不打算使用它,可以使用“優(yōu)化,RTA-OS, disallow Schedule()”來禁止在rtaoscfg中調(diào)用Schedule()。如果不允許對(duì)Schedule()的調(diào)用,那么將看到系統(tǒng)的最差情況堆棧需求降低了。
2.11 終止任務(wù)Terminating Tasks
在AUTOSAR操作系統(tǒng)中終止的任務(wù)必須通過API調(diào)用來告訴操作系統(tǒng)正在發(fā)生這種情況。AUTOSAR OS標(biāo)準(zhǔn)為任務(wù)終止定義了兩個(gè)API調(diào)用。必須使用其中一個(gè)來終止任何任務(wù)。這些API調(diào)用是:
?TerminateTask ()
?ChainTask (TaskID)
當(dāng)一個(gè)任務(wù)完成時(shí),它必須調(diào)用這些API中的一個(gè)。這確保RTA-OS可以正確地調(diào)度下一個(gè)準(zhǔn)備運(yùn)行的任務(wù)。
TerminateTask()強(qiáng)制調(diào)用任務(wù)進(jìn)入掛起狀態(tài)。然后RTA-OS將在就緒狀態(tài)下運(yùn)行下一個(gè)優(yōu)先級(jí)最高的任務(wù)。
ChainTask(TaskID)終止調(diào)用任務(wù),激活任務(wù)TaskID。因此,該API就像執(zhí)行一個(gè)TerminateTask(),然后立即執(zhí)行ActivateTask(TaskID)。鏈接任務(wù)將指定的任務(wù)置于就緒狀態(tài)。
2.11.1 優(yōu)化RTA-OS中的任務(wù)終止Optimizing Termination in RTA-OS
AUTOSAR OS標(biāo)準(zhǔn)允許任務(wù)在任何時(shí)候調(diào)用任務(wù)終止API調(diào)用,包括在嵌套很深的函數(shù)調(diào)用集中。
這是一種糟糕的編程實(shí)踐——相當(dāng)于goto的使用。
在運(yùn)行時(shí),RTA-OS必須存儲(chǔ)允許它在任務(wù)終止時(shí)清除堆棧的信息,而不是入口函數(shù)。這通常使用setjmp/longjmp對(duì)來完成。
例2.8顯示了對(duì)其他函數(shù)進(jìn)行嵌套調(diào)用的任務(wù)。Task1運(yùn)行時(shí),它調(diào)用Function1()。
Function1()然后調(diào)用Function2()。Function2()包含可以終止調(diào)用任務(wù)的代碼(在本例中是Task1)。
然而,單堆棧架構(gòu)的一個(gè)關(guān)鍵好處是,在其入口函數(shù)中終止的任務(wù)可以簡單地返回- TerminateTask()不需要做任何事情。如果所有的任務(wù)都沒有終止,或者只是在它們的入口函數(shù)中終止,那么RTA-OS保存的允許從任何地方返回的上下文都不需要存儲(chǔ)。
RTA-OS允許您使用快速終止優(yōu)化(Optimizations?fast Terminate)來開發(fā)良好的應(yīng)用程序設(shè)計(jì)。當(dāng)所有執(zhí)行TerminateTask()或ChainTask() api的任務(wù)只在它們的entry函數(shù)中執(zhí)行此優(yōu)化時(shí),您可以啟用此優(yōu)化。優(yōu)化告訴RTA-OS不生成代碼以節(jié)省不必要的上下文,從而節(jié)省堆??臻g。
#include
Example 2.8: Terminating a Task
2.12 延遲任務(wù)Delayed Tasks
OS選項(xiàng)“支持延遲任務(wù)執(zhí)行”可用于添加對(duì)api Os_SetDelayedTasks()、Os_AddDelayedTasks()和Os_RemoveDelayedTasks()的支持。
這些api允許您告訴RTA-OS延遲一組任務(wù)的執(zhí)行。延遲任務(wù)可以被激活,但直到從集合中刪除它們才會(huì)實(shí)際運(yùn)行。
Os_SetDelayedTasks()用于指定需要延遲哪些任務(wù)。如果一個(gè)任務(wù)在調(diào)用之前被延遲,但它不在新的延遲任務(wù)集中,那么如果它的優(yōu)先級(jí)高于調(diào)用方,那么它將在此調(diào)用返回之前執(zhí)行。
您必須只設(shè)置在調(diào)用核心上運(yùn)行的任務(wù)。
Os_AddDelayedTasks()用于向已有的延遲任務(wù)集中添加任務(wù)。多次添加任務(wù)是允許的,但沒有效果。必須只添加在調(diào)用核心上運(yùn)行的任務(wù)。
Os_RemoveDelayedTasks()用于從去袒護(hù)的任務(wù)集中移除任務(wù)。如果被刪除的任務(wù)的優(yōu)先級(jí)高于調(diào)用方,則它們將在此調(diào)用返回之前執(zhí)行。
注意,如果某個(gè)特定核心上的任務(wù)共享優(yōu)先級(jí),則必須指定共享優(yōu)先級(jí)的所有任務(wù)或不指定優(yōu)先級(jí)。當(dāng)啟用延遲任務(wù)時(shí),任務(wù)狀態(tài)模型變得有點(diǎn)復(fù)雜。下表試圖解釋可能的轉(zhuǎn)換。
2.13 空閑機(jī)制The Idle Mechanism
當(dāng)沒有任務(wù)或ISR要運(yùn)行時(shí),任何搶占式操作系統(tǒng)都必須有事可做。在AUTOSAR OS中,這是通過空閑機(jī)制實(shí)現(xiàn)的。在RTA-OS中,當(dāng)沒有任務(wù)或ISR要運(yùn)行時(shí),操作系統(tǒng)將處于繁忙等待循環(huán)中,什么也不做。
但是,可以通過聲明一個(gè)名為Os_Cbk_Idle的回調(diào)來提供您自己的空閑機(jī)制實(shí)現(xiàn),從而覆蓋默認(rèn)行為。
Os_Cbk_Idle的行為與任務(wù)相同,除了:
?無法激活
?不能終止
?它不能等待事件
?它不能被束縛
?不能使用內(nèi)部資源
Os_Cbk_Idle的優(yōu)先級(jí)比系統(tǒng)中的任何任務(wù)都低,因此它只在沒有準(zhǔn)備運(yùn)行的任務(wù)(或ISR)時(shí)運(yùn)行。
因此,空閑機(jī)制為您提供了一個(gè)幾乎完全不受系統(tǒng)開銷影響的“額外任務(wù)”。
例2.9顯示了Os_Cbk_Idle用于控制RTA的實(shí)現(xiàn)。
Os_Cbk_Idle在退出時(shí)返回一個(gè)布爾值,告訴RTA-OS是否再次調(diào)用Os_Cbk_Idle。當(dāng)返回TRUE時(shí),RTA-OS立即再次調(diào)用Os_Cbk_Idle。當(dāng)返回FALSE時(shí),RTA-OS停止調(diào)用Os_Cbk_Idle,并進(jìn)入繁忙等待循環(huán)的默認(rèn)行為。
#include
2.14 任務(wù)開始和結(jié)束的構(gòu)子函數(shù)Pre and Post Task Hooks
假設(shè)需要在每個(gè)任務(wù)開始之前和/或在每個(gè)任務(wù)結(jié)束之后執(zhí)行一些代碼,例如分析執(zhí)行的跟蹤。可以使用AUTOSAR OS提供的PreTask和PostTask鉤子來實(shí)現(xiàn)這一點(diǎn)。
當(dāng)任務(wù)進(jìn)入運(yùn)行狀態(tài)時(shí),RTA-OS會(huì)調(diào)用PreTask鉤子。
這意味著當(dāng)一個(gè)任務(wù)在搶占后恢復(fù)時(shí),PreTask鉤子也將被調(diào)用。
當(dāng)任務(wù)移出運(yùn)行狀態(tài)時(shí),RTA-OS會(huì)調(diào)用PostTask鉤子。
PostTask鉤子將在任務(wù)終止時(shí)調(diào)用,并且每次任務(wù)被搶占時(shí)調(diào)用。
圖2.19顯示了相對(duì)于任務(wù)搶占,PreTask和PostTask鉤子被調(diào)用的位置。
這兩個(gè)鉤子只有在配置時(shí)才被調(diào)用。圖2.20顯示了如何啟用鉤子。
圖2.19 PreTaskHook()和PostTaskHook()相對(duì)于任務(wù)搶占
圖2.20 Enabling the PreTaskHook() and PostTaskHook()
FUNC(void, OS_CALLOUT_CODE) PreTaskHook(void) { /* PreTask hook code. */ } FUNC(void, OS_CALLOUT_CODE) PostTaskHook(void) { /* PostTask hook code. */ }
Example 4.10: The PreTaskHook and PostTaskHook
例2.10展示了鉤子應(yīng)該如何出現(xiàn)在代碼中。
在任務(wù)進(jìn)入和退出時(shí)以及每次搶占/恢復(fù)時(shí)調(diào)用PreTask和PostTask鉤子。這意味著可以使用這些鉤子記錄應(yīng)用程序的執(zhí)行跟蹤。由于應(yīng)用程序中的所有任務(wù)都必須使用相同的PreTask和PostTask鉤子,因此有必要使用GetTaskID() API調(diào)用來確定在進(jìn)入鉤子例程時(shí)哪個(gè)任務(wù)已經(jīng)或?qū)⒁\(yùn)行。
RTA-OS定義了一組宏,這些宏僅在對(duì)應(yīng)的鉤子被啟用時(shí)才被定義。這些宏被稱為:
?OS_PRETASKHOOK
?OS_POSTTASKHOOK
#ifdef OS_PRETASKHOOK FUNC(void, OS_CALLOUT_CODE) PreTaskHook (void) { /* Your code */ } #endif /* OS_PRETASKHOOK */
Example 2.11: Conditional Compilation of PreTaskHook
這允許編寫代碼,其中可以有條件地編譯鉤子,如示例2.11所示。
2.15 通過搶占保存硬件寄存器Saving Hardware Registers across Preemption
RTA-OS在上下文切換時(shí)盡可能少地保存上下文—只保存操作系統(tǒng)正確操作的上下文。但是,可能會(huì)發(fā)現(xiàn)需要在運(yùn)行時(shí)保存和恢復(fù)附加的依賴于應(yīng)用程序的上下文。例如,可能有使用浮點(diǎn)寄存器的任務(wù),因此需要通過上下文切換保存微控制器的浮點(diǎn)上下文。
可以選擇使用PreTask和PostTask鉤子和應(yīng)用程序管理的堆棧手動(dòng)實(shí)現(xiàn)這一點(diǎn)。但是,很難在不改變操作系統(tǒng)配置的情況下優(yōu)化這種類型的實(shí)現(xiàn)??梢?
?始終保存每個(gè)交換機(jī)上的上下文到一個(gè)任務(wù),然后在每個(gè)交換機(jī)上恢復(fù)。這個(gè)模型意味著你可能會(huì)做不必要的保存和恢復(fù)(例如,當(dāng)切換到一個(gè)不使用它的任務(wù)時(shí),保存一個(gè)寄存器集);或
?離線計(jì)算所需的保存,然后編寫一個(gè)更復(fù)雜的鉤子對(duì),使用GetTaskID()/GetISRID()來計(jì)算是否需要保存/恢復(fù)。這個(gè)模型是脆弱的,因?yàn)閷?duì)配置的更改,例如添加新的任務(wù)/ isr或修改優(yōu)先級(jí),將意味著需要重新工作。為了避免這些問題,RTA-OS提供了一種簡單的通用機(jī)制,用于保存特定于用戶的上下文和操作系統(tǒng)上下文。RTA-OS能夠利用其優(yōu)先級(jí)空間的knowl edge來精確計(jì)算哪些任務(wù)需要在運(yùn)行時(shí)保存寄存器集,從而優(yōu)化掉不必要的保存,節(jié)省上下文切換所需的時(shí)間和堆棧。例如:
?如果你只有一個(gè)任務(wù)或二類ISR使用一個(gè)給定的寄存器集,那么不需要保存或恢復(fù)。
?如果多個(gè)任務(wù)使用相同的寄存器集,但不能同時(shí)執(zhí)行(因?yàn)樗鼈儾豢蓳屨?,共享?nèi)部資源或共享優(yōu)先級(jí)),那么RTA-OS不需要保存寄存器集。
圖2.21 Register saving in action
?上下文切換到使用寄存器集的最低優(yōu)先級(jí)任務(wù)不需要進(jìn)行保存,因?yàn)榭梢员WC沒有其他任務(wù)可以使用該集(因?yàn)槿绻邇?yōu)先級(jí)任務(wù)正在使用寄存器集,則最低優(yōu)先級(jí)任務(wù)不可能運(yùn)行)。
?類似地,從使用寄存器集的最高優(yōu)先級(jí)任務(wù)進(jìn)行上下文切換不需要進(jìn)行保存,因?yàn)闆]有更高優(yōu)先級(jí)的任務(wù)使用寄存器集,因此不會(huì)破壞上下文。
圖2.21顯示了由任務(wù)1、3和5共享的寄存器集??梢钥吹?,當(dāng)不需要保存時(shí)(當(dāng)切換到不使用寄存器集的任務(wù)時(shí)),就不會(huì)進(jìn)行上下文保存。
需要保存的每個(gè)寄存器集都需要在配置時(shí)聲明給RTA-OS。Rtaosgen使用聲明定義兩個(gè)回調(diào)函數(shù),必須提供它們來保存和恢復(fù)寄存器集。圖2.22顯示了三個(gè)寄存器集的定義。
使用寄存器集的每個(gè)任務(wù)都需要在運(yùn)行時(shí)聲明這一點(diǎn),以便rtaosgen可以計(jì)算需要保存的最大集數(shù)。圖2.23顯示了如何為任務(wù)執(zhí)行此操作。
RTA-OS不知道如何或在哪里保存和恢復(fù)寄存器集——它只知道需要保存多少次以及何時(shí)保存和重新存儲(chǔ)它們。對(duì)于定義的每個(gè)寄存器集,RTA-OS生成一個(gè)宏OS_REGSET_
圖2.22 寄存器集定義
圖23. 在一個(gè)任務(wù)中使用寄存器集
typedef volatile uint32 RegType; #define VOLATILEREGISTER (*(RegType*)(0xDEAFBEEF)) uint32 VolatileRegisterSaveArea[OS_REGSET_VolatileRegister_SIZE]; FUNC(void, OS_CALLOUT_CODE) Os_Cbk_RegSetSave_VolatileRegister(Os_RegSetDepthType Depth) { VolatileRegisterSaveArea[Depth] = VOLATILEREGISTER; } FUNC(void, OS_CALLOUT_CODE) Os_Cbk_RegSetRestore_VolatileRegister(Os_RegSetDepthType Depth) { VOLATILEREGISTER = VolatileRegisterSaveArea[Depth]; }
Example 2.12: Register Set Save And Restore
你還需要為保存和恢復(fù)操作提供回調(diào)函數(shù):
?Os_Cbk_RegSetSave_
?Os_Cbk_RegSetRestore_
兩個(gè)回調(diào)函數(shù)都傳遞了一個(gè)Depth值,該值指示要保存或恢復(fù)的寄存器集。
例2.12顯示了回調(diào)函數(shù)應(yīng)該如何出現(xiàn)在你的代碼中。
2.16 小結(jié)
?任務(wù)是一個(gè)并發(fā)活動(dòng)。
?有兩類任務(wù):基本任務(wù)和擴(kuò)展任務(wù)。
?任務(wù)可以共享優(yōu)先級(jí),但建議不要這樣做。
?根據(jù)優(yōu)先級(jí)安排任務(wù)。
?當(dāng)一個(gè)高優(yōu)先級(jí)的任務(wù)準(zhǔn)備好運(yùn)行時(shí),它將搶占低優(yōu)先級(jí)的任務(wù),但它不會(huì)搶占任何已配置為非搶占的任務(wù)。
?任務(wù)以就緒、運(yùn)行、掛起或等待狀態(tài)存在(但是,只有已擴(kuò)展的任務(wù)可以進(jìn)入等待狀態(tài))。
?如果一個(gè)任務(wù)終止,它必須調(diào)用TerminateTask()或ChainTask(TaskID)來終止。
?所有任務(wù)在其入口函數(shù)中終止的系統(tǒng)可以使用“快速終止”優(yōu)化來最小化堆棧使用和上下文切換時(shí)間。
?任務(wù)只能在處于掛起狀態(tài)時(shí)被激活,除非指定了多個(gè)激活。?PreTask和PostTask鉤子允許你在任務(wù)開始前和結(jié)束后執(zhí)行代碼。這可用于在運(yùn)行時(shí)分析應(yīng)用程序。
審核編輯 :李倩
-
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6742瀏覽量
123194 -
AUTOSAR
+關(guān)注
關(guān)注
10文章
350瀏覽量
21479 -
調(diào)度器
+關(guān)注
關(guān)注
0文章
98瀏覽量
5241
原文標(biāo)題:符合AUTOSAR標(biāo)準(zhǔn)的RTA-OS --Task詳解
文章出處:【微信號(hào):汽車電子嵌入式,微信公眾號(hào):汽車電子嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論