正文
計數器以tick為單位記錄操作系統中發生了多少“事情”。滴答是一個抽象的單位。
這是由你來決定你想要一個滴答的意思。
可以這樣定義tick:
?時間Time,例如毫秒,微秒,分鐘等,然后計數器告訴你已經過去了多少時間。
?旋轉Rotation,例如以度或分鐘為單位,在這種情況下,計數器會告訴你物體旋轉了多少。
?按鈕按下Button Presses,在這種情況下,計數器會告訴你按鈕被按了多少次。
?錯誤Errors,在這種情況下,計數器計算錯誤發生的頻率。
一個ISR(有時是一個任務)用于驅動一個計數器。驅動程序負責進行正確的RTA-OS API調用來“tick”計數器,或者告訴RTA-OS計數器已經“tick”到一個必需的值。
6.1配置計數器Configurting Counters
每個計數器都有4個強制性屬性:
Name 是計數器的名稱。RTA-OS使用與計數器具有相同名稱的標識符為每個計數器創建一個句柄。
Type 定義計數器模型。AUTOSAR提供兩種型號
軟件Software計數器是由操作系統內部維護的計數值。User需要提供一個計數器驅動程序,告訴RTA-OS將計數器增加一個tick。在6.2.1節中提供了進一步的細節。
硬件Hardware計數器是由外設維護的計數值。User需要提供一個計數器驅動程序,該驅動程序告訴操作系統何時已經過了請求的tick數。操作系統還將要求您的驅動程序支持支持RTA-OS用于在運行時管理外圍設備的回調例程的實現。章節6.2.2提供了進一步的細節。
當需要相對較低的分辨率(例如一毫秒或更高)時,軟件計數器就足夠了。當需要非常高的分辨率(例如在微秒范圍內),或者需要將RTA-OS中的任務調度精確地同步到外部源(例如TPU或全局(網絡)時間源)時,應該使用硬件計數器。
Maximum Value定義計數器的最大計數值。在達到最大允許值后,所有計數器在刻度上自動歸零。對于16位計數器將為65535(216?1),對于32位計數器將為4294967295(232?1)。這對應于AUTOSAR OS計數器屬性MAXALLOWEDVALUE。端口的最大可能計數器值由文件Os.h中TickType類型的大小決定。
集成指南:對于硬件計數器,必須確保最大匹配值+1等于外圍設備的模量。
Minimum Cycle最小周期定義在為Alarm或者schedule table偏移量設置周期值時允許的最短刻度數。在大多數情況下,希望它是1個刻度。但是,如果希望構建的系統在計數器上強制執行最小的警報間隔,那么可以選擇更大的值。這對應于AUTOSAR OS計數器屬性MINCYCLE。
Ticks per base是一個屬性,可用于定義計數器上每個刻度所需的基礎計數器驅動刻度的數量。可以為這個屬性賦任何值,因為RTA-OS不使用它。這對應于AUTOSAR操作系統屬性TICKSPERBASE。
還有一個附加的可選屬性:
Seconds Per Tick以秒為單位定義計數器滴答的持續時間。如果想要使用AUTOSAR OS提供的刻度/時間轉換功能,則應該定義此選項。進一步的細節在第6.5節中給出。
圖6.1 聲明一個計數器
6.2 計數器驅動Conuter Drivers
RTA-OS不控制任何硬件來提供計數器驅動程序。這使得RTA-OS非常容易與任何tick源集成,例如計時器滴答,錯誤計數,按鈕按壓,TPU外設等。這意味著需要為在RTA-OS中聲明的每個計數器提供驅動程序,并將其接口到操作系統。
驅動程序和計數器之間的接口取決于計數器的類型:
Software Counters由API調用遞增。
Hardware Counters該計數值保存在外部硬件外圍設備中。應用程序必須提供一個更復雜的驅動程序,該驅動程序告訴RTA-OS請求的滴答數已經過了。RTA-OS使用特殊的回調來設置請求的tick數,取消請求,獲取當前計數值并獲取計數器的狀態。
6.2.1 軟件計數器驅動Software Counter Drivers
對于每個軟件計數器,需要提供提供刻度的驅動程序。RTA-OS在StartOS()期間將所有軟件計數器初始化為零并向上計數。
軟件計數器驅動模型在AUTOSAR OS中標準化,如圖6.2所示。
圖6.2 Ticked Counter Driver Model
實現軟件計數器:
使用API調用IncrementCounter(CounterID)來增加RTA-OS中保存的計數器值。當向MAXALLOWEDVALUE中添加1時,軟件計數器會自動歸零。
可以從應用程序代碼中的大多數地方調用IncrementCounter(CounterID)。計數器最常見的用途之一是為RTA-OS提供基于Alarm或Schedule table激活任務的時間基礎。在這種情況下,需要提供一個周期性計時器中斷,在每次到期時調用IncrementCounter(CounterID)。
例6.1展示了毫秒中斷如何驅動一個名為TimeCounter的計數器。
#includeISR(HandleTimerInterrupt) { DismissTimerInterrupt(); IncrementCounter(TimeCounter); }
Example 6.1: Using a periodic interrupt to tick a software counter
軟件計數器的另一個常見用途是作為容錯系統的一部分,在超過錯誤閾值時需要采取某些操作。軟件計數器可用于記錄錯誤的數量,然后可以使用警報來觸發恢復操作(例如,激活錯誤恢復任務)。
例6.2展示了名為Critical的任務如何在名為ErrorCounter的計數器上記錄錯誤。
#includeTASK(Critical){ ... if (Error) { IncrementCounter(ErrorCounter); } ... TerminateTask(); }
Example 6.2: Using a periodic Task to tick a software counter
靜態計數器接口Static Counter Interface:
由于AUTOSAR API調用將計數器的名稱作為參數,這意味著RTA-OS必須在更新OS數據結構之前在內部取消對參數的引用。這也意味著編譯器需要在進入時將參數壓入堆棧。
然而,通常情況下,在構建時就知道將從何處計時哪個計數器。可能需要從中斷處理程序驅動計數器。
RTA-OS認識到這一點,并為配置文件中聲明的每個計數器生成一個專用的API調用Os_IncrementCounter_
集成指南:API調用Os_IncrementCounter_
例如,考慮一個包含兩個計數器的應用程序:一個名為TimeCounter,另一個名為AngularCounter。rtaosgen將生成例6.3中所示的兩個API調用。
為定時器和角中斷提供服務的中斷處理程序必須調用這些API調用。
例6.4展示了這些中斷處理程序。
#includeISR(HandleTimerInterrupt) { ServiceTimerInterrupt(); Os_IncrementCounter_TimeCounter(); } ISR(HandleAngularInterrupt) { ServiceAngularInterrupt(); Os_IncrementCounter_AngularCounter(); }
Example 6.4: Interrupt Handlers for Example 6.3
#includeISR(MillisecondInterrupt) { ServiceTimerInterrupt(); Os_IncrementCounter_Counter1(); Os_IncrementCounter_Counter2(); ... Os_IncrementCounter_CounterN(); }
Example 6.5: Making multiple calls to the static software counter interface
如果您有多個軟件計數器,您需要以相同的速率tick,可以在處理程序中進行多個Os_IncrementCounter_
對于聲明的每個計數器,都有一個Os_IncrementCounter_
6.2.2 硬件計數器驅動Hardware Counter Drivers
對于每個硬件計數器,User需要提供調用RTA-OS的硬件計數器驅動程序和RTA-OS使用的一組回調。與軟件計數器一樣,RTA-OS提供了一個定義良好的接口,用于將高級計數器驅動程序連接到操作系統。
集成指南:AUTOSAR OS標準沒有指定處理硬件計數器的標準API調用。如果要將應用程序從另一個操作系統移植到RTA-OS,則可能需要更改硬件計數器驅動程序API調用。
對于每個硬件計數器,RTA-OS知道該計數器驅動的下一個動作是什么,是使警報過期,還是處理調度表上的過期點,或者兩者兼而有之。RTA-OS還知道在發生這種情況之前需要經過多少滴答。這被稱為匹配值。
圖6.3 Advanced Counter Driver Model
當使用軟件計數器時,驅動程序會在每次計時結束時告訴RTA-OS。RTA-OS在內部對刻度進行計數,當達到匹配值時,采取操作。然后RTA-OS計算下一個匹配值并重復該過程。
相比之下,當使用硬件計數器時,RTA-OS通過回調函數告訴驅動程序何時需要進行下一個操作。外設計算請求的滴答數,并在正確的滴答數耗盡時生成中斷。在中斷處理程序中,可以調用Os_AdvanceCounter_CounterID() API來告訴RTA-OS處理CounterID上的下一個操作。RTA-OS這樣做,然后重復這個過程。
通常,User將使用中斷來驅動軟件和硬件計數器。對于軟件計數器,無論RTA-OS是否有任何事情要做,每個計數器滴答都會發生中斷。對于硬件計數器,只有當RTA-OS需要做某事時才會發生中斷。這意味著硬件計數器將中斷干擾減少到所需的絕對最小值。
Advancing Hardware Counters
User使用API調用Os_AdvanceCounter_
集成指南:User負責編寫調用Os_AdvanceCounter_
Os_AdvanceCounter_
Callback Functions
對于軟件計數器,RTA-OS在內部計算經過的滴答數。這意味著RTA-OS總是知道當前的計數器值,在下一次到期之前有多少個滴答等等。
對于硬件計數器,外設計算經過的滴答數。這意味著RTA-OS必須告訴硬件計數器它需要計數多少個節拍,并且必須詢問外設當前的計數值,到下一個到期的節拍數等。
這種交互是使用回調函數在RTA-OS和您想用作計數器驅動程序的任何類型的硬件外設之間進行接口的。回調函數的確切功能性取決于用作硬件計數器驅動程序的外設。
然而,通過一個簡短的概述,需要四個回調:
Os_Cbk_Set_
這個回調為下一個動作到期時發生的中斷設置狀態。回調函數被傳遞一個計數器的絕對值,在這個計數器上應該發生一個動作。對于計數器,這個回調在兩種不同的情況下使用:
1. 開始Starting
當Schedule Table或Alarm在計數器上啟動時,設置初始中斷源。
2. 重置Resetting
縮短到下一個計數器到期的時間。這是必要的,例如,當下一個中斷超過100個滴答時,做一個SetRelAlarm(WakeUp, 100)調用。
AlarmBaseType Info; GetAlarmBase(Alarm2, &Info); MaxValue = Info.maxallowedvalue; BaseTicks = Info.ticksperbase; MinCycle = Info.mincycle;
Example 6.6: Using GetAlarmBase() to read static counter attributes
Os_Cbk_State_
此回調返回計數器上的下一個操作是否掛起,以及(通常)在達到匹配值之前剩余的tick數。
Os_Cbk_Now_
此回調需要返回外部計數器的當前值。這用于GetCounterValue() API調用。
Os_Cbk_Cancel_
這個回調必須為計數器清除任何掛起的中斷,并確保中斷不能成為掛起,直到一個Os_Cbk_Set_
集成指南:硬件計數器可用于多核系統。RTA-OS將確保State, Set和Cancel回調只在擁有計數器的核心上被調用。這意味著User可以從擁有計數器的不同核心啟動alarm和ScheduleTables, RTA-OS將向計數器的核心發送消息,告訴它調用適當的回調。
6.3運行時獲取計數器屬性Accessing Counter Attributes at Run time
RTA-OS API調用GetAlarmBase()總是返回配置的計數器值。GetAlarmBase()的結構如例6.6所示。
配置的值也可以以符號常量的形式訪問,如下所示。
? OSMAXALLOWEDVALUE_
? OSTICKSPERBASE_
? OSMINCYCLE_
因此,上面的例6.6也可以寫成例6.7:
MaxValue = OSMAXALLOWEDVALUE_Alarm2; BaseTicks = OSTICKSPERBASE_Alarm2; MinCycle = OSMINCYCLE_Alarm2;
Example 6.7: Using macros to read static counter attributes
6.3.1 特殊的計數器名Special Counter Names
如果創建了一個名為SystemCounter的計數器,那么在AUTOSAR OS中可以通過省略末尾的_CounterID來使用簡短的宏形式訪問相關的計數器屬性:
OSMAXALLOWEDVALUE_SystemCounter ? OSMAXALLOWEDVALUE
OSTICKSPERBASE_SystemCounter ? OSTICKSPERBASE
OSMINCYCLE_SystemCounter ? OSMINCYCLE
RTA-OS為SystemCounter生成兩種形式的宏,User可以使用任何一種版本。SystemCounter還提供了一個額外的宏來獲取計數器滴答的持續時間(以納秒為單位),稱為OSTICKDURATION。
集成指導:生成一個有意義的OSTICKDURATION宏需要配置計數器屬性“Seconds Per Tick”。
6.4 讀取計數器值Reading Counter Values
應用程序需要能夠在運行時讀取計數器的當前值。例如,User可能想知道錯誤計數器記錄了多少錯誤,按鈕被按了多少次,或者經過了多少時間。
計數器的當前值可以在運行時通過調用GetCounterValue() API來讀取,如例6.8所示。
TickType HowMany; GetCounterValue(ButtonPresses,&HowMany);
Example 8.8: Using GetCounterValue()
當使用GetCounterValue()時,應該意識到:
?計數器從MAXALLOWEDVALUE到零,因此計算需要補償。Counters wrap around from MAXALLOWEDVALUE to zero, so the calculation needs to compensate for the wrap
?搶占可以在調用返回時發生,這意味著當您恢復時,' Now '的值將是舊的
?當使用硬件計數器時,當調用返回時,計數器驅動程序仍將遞增。即使沒有發生搶 占,立即執行的計算也將基于舊數據
如果需要執行一個簡單的計算來計算自上次讀取值以來計數器經過了多少次計時,那么可以通過使用GetElapsedCounterValue() API調用來避免這種潛在的競爭條件。該調用將先前讀取的計數器值作為輸入,并計算已經過的刻度,包括對計數器包裝的補償。計算發生在操作系統級別(即禁用中斷),因此不會受到搶占效應的影響。
示例6.9顯示了如何使用此特性來度量任務的端到端(響應)時間。
#includeTickType Start; ISR(CaptureTrigger){ /* Dismiss interrupt */ GetCounterValue(TimeCounter,&Start); ... ActivateTask(GenerateResponse); } TASK(GenerateResponse){ TickType Finish; CalculateValue(); WriteToDevice(); GetElapsedCounterValue(TimeCounter,&Start,&Finish); ... TerminateTask(); }
Example 6.9: Using GetElapsedCounterValue()
如果計數器正在計算時間刻度(如例6.9),那么這在AUTOSAR OS中被稱為“自由運行計時器free running timer”。這種類型的計數器沒有什么特別之處——它與任何其他類型的計數器相同——唯一的區別是計數器是由計時器滴答源驅動的。
自由運行計時器功能的預期用途是在運行時測量短、高準確度的持續時間。如果需要這樣做,那么可能需要使用硬件計數器來獲得所需的計數器分辨率。
6.5 Tick數轉換為時間Tick to Time Conversions
通常將計數器用作操作系統的時基參考。對于編寫的大多數應用程序,事件的相對定時將是由系統需求決定的實時值。很可能會根據實時值、納秒、毫秒等來考慮系統配置,而不是使用更抽象的tick(滴答)概念。
如果計數器配置參數“秒每滴答”已經配置,那么RTA操作系統生成宏供使用,以在滴答和實時單位之間轉換。
可移植性注意事項:AUTOSAR OS聲明Tick到時間的轉換僅適用于硬件計數器。但是,該特性通常對軟件和硬件計數器都有用,并且AUTOSAR XML配置語言支持對這兩種類型的計數器進行配置。
在RTA-OS中,這種異常通過為軟件和硬件計數器提供刻度到時間的轉換來解決。但是,應該注意,其他AUTOSAR OS實現不一定支持為軟件計數器提供這些宏。
提供了以下Tick轉換為時間的宏:
? OS_TICKS2NS_CounterID(ticks) converts ticks to nanoseconds
? OS_TICKS2US_CounterID(ticks) converts ticks to microseconds
? OS_TICKS2MS_CounterID(ticks) converts ticks to milliseconds
? OS_TICKS2SEC_CounterID(ticks) converts ticks to seconds
這些宏返回的值是PhysicalTimeType,而不是TickType,可能會使用這些宏的API調用使這些值,因此需要將它們轉換為適當的類型。
例6.10展示了如何在應用程序代碼中使用這些宏來使用靜態定義的“timeout”值來模擬超時。
#define TIMEOUT_MS 100 /* Set a timeout to be 100ms */ TickType TimeoutInTicks; TimeoutInTicks = (TickType)((PhysicalTimeType)TIMEOUT_MS/OS_TICKS2MS_TimeCounter(1)); SetRelAlarm(TimeoutAlarm, TimeoutInTicks, 0);
Example 6.10: Programming an alarm with time rather than ticks (1)
RTA-OS將盡可能使用整數乘法或除法生成這些宏。然而,對于某些滴答率,有必要在計算中使用浮點數,以保持準確性。當這些宏被傳遞給編譯時已知的固定值時,編譯器通常會自己執行計算并嵌入整型結果。如果傳遞的值是一個變量,那么編譯器將不得不在運行時生成使用浮點計算的代碼。如果這在應用程序中可能是一個問題,應該檢查文件Os_Cfg.h以檢查宏的代碼。
除了這些宏之外,RTA-OS還生成一個名為otickduration_
#define TIMEOUT_NS 100000000 /* Set a timeout to be 100ms */ TickType TimeoutInTicks; TimeoutInTicks = (TickType)(TIMEOUT_NS/OSTICKDURATION_TimeCounter); SetRelAlarm(TimeoutAlarm, TimeoutInTicks, 0);
Example 6.11: Programming an alarm with time rather than ticks (2)
可移植性注意事項:OSTICKDURATION_
6.6 小結
?計數器用于注冊一些tick源的計數。
?計數器可以是軟件計數器也可以是硬件計數器。User需要為配置的計數器類型提供私有驅動程序。
審核編輯:劉清
-
計數器
+關注
關注
32文章
2241瀏覽量
93981 -
定時器
+關注
關注
23文章
3218瀏覽量
113708 -
AUTOSAR
+關注
關注
10文章
339瀏覽量
21362 -
ISR
+關注
關注
0文章
38瀏覽量
14360
原文標題:符合AUTOSAR標準的RTAOS--Counters詳解
文章出處:【微信號:汽車電子嵌入式,微信公眾號:汽車電子嵌入式】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論