正文
1. OS錯(cuò)誤處理介紹
1.1 錯(cuò)誤類型
OS的Error類型分為三類,Application Errors, Protection Errors, Kernel Errors, 每種Errors產(chǎn)生的原因及產(chǎn)生Error后OS執(zhí)行的動作都不相同,詳見下表:
Error Types | Feature |
Application Errors |
1.如果操作系統(tǒng)無法正確執(zhí)行應(yīng)用程序請求的操作系統(tǒng)提供的API服務(wù),則引發(fā)Application Erros。典型情況就是操作系統(tǒng)API使用錯(cuò)誤(例如對象ID無效)。 2.Application Error不會損壞操作系統(tǒng)內(nèi)部數(shù)據(jù)。 3.如果配置了Error Hook,則OS會調(diào)用ErrorHook(),ErrorHook()是一個(gè)Callout函數(shù),需要用戶自定義錯(cuò)誤處理機(jī)制。 4.不會造成OS調(diào)用Shutdown/terminate。應(yīng)用程序可以通過簡單地從ErrorHooks返回來繼續(xù)執(zhí)行。 |
Protection Errors |
1.如果應(yīng)用程序違反其配置的邊界則會觸發(fā)Protection Errors, 典型的就是配置了內(nèi)存保護(hù)或者時(shí)間保護(hù)后發(fā)生內(nèi)存非法訪問或超時(shí)。 2.Protection Errors不會損壞操作系統(tǒng)內(nèi)部數(shù)據(jù)。 3.在發(fā)生未處理的異常和中斷時(shí)會觸發(fā)Protection Error。 4.將導(dǎo)致ProtectionHook()的調(diào)用,在該調(diào)用中可以選擇引發(fā)Shutdown或Terminatehanding(ProtectionHook返回值將覺得OS接下來的執(zhí)行流,無論是否重新啟動)。 5.如果配置了Shutdownhook,則會調(diào)用ShutdownHook(). 6.如果配置了ProtectionHook,則會調(diào)用ProtectionHook(). |
Kernel Errors |
1.如果操作系統(tǒng)無法再確保其內(nèi)部數(shù)據(jù)的正確性,則引發(fā)Kernel Errors(例如,ProtectionHook()期間內(nèi)存訪問違規(guī))。 2.發(fā)生Kernel Errors后OS會關(guān)閉所有中斷且調(diào)用Os_PannicHook()通知應(yīng)用程序。 3. 最后操作系統(tǒng)進(jìn)入無限循環(huán)。 |
1.2 錯(cuò)誤碼
發(fā)生Application Errors后OS會調(diào)用ErrorHook(),ErrorHook()函數(shù)是callout函數(shù),函數(shù)原型:
(void) ErrorHook(StatusType Error);
參數(shù)Error標(biāo)識具體的錯(cuò)誤碼
發(fā)生Protection Errors后OS會調(diào)用ProtectionHook(), ProtectionHook函數(shù)是callout函數(shù),函數(shù)原型:
ProtectionReturnType ProtectionHook(StatusType Fatalerror);
參數(shù)Fatalerror標(biāo)識具體的錯(cuò)誤碼
返回值類型ProtectionReturnType是一個(gè)枚舉類型:
typedef enum ProtectionReturnType_e { PRO_IGNORE, PRO_TERMINATETASKISR, PRO_TERMINATEAPPL, PRO_TERMINATEAPPL_RESTART, PRO_SHUTDOWN, PRO_NOTCONFIGURED } ProtectionReturnType;
也就是,我們可以通過自定義ProtectionHook()的返回值來控制發(fā)送ProtectionHook后Os的執(zhí)行流。
每個(gè)廠商(Vector, Etas…)Os實(shí)現(xiàn)的Os_Types.h文件中都具體定義了每一種ErrorCode,這里以Vector的代碼實(shí)現(xiàn)為例說明每種Error Type包含的常見的Error Code:
ErrorTypes | 包含的Error Codes |
Application Errors |
E_OS_ACCESS: Illegal access E_OS_CALLEVEL:Invalid calling context. E_OS_ID:Invalid OS object ID. E_OS_LIMIT: Maximum task activations reached. E_OS_NOFUNC: OS object is currently not in use. E_OS_RESOURCE:Scheduling requested with occupied resource. E_OS_STATE: OS object is not in correct state to perform the requested operation. E_OS_VALUE:Given value is out of the configured range. E_OS_SERVICEID: Service cannot be called. |
Protection Errors |
E_OS_PROTECTION_MEMORY:A memory access violation occurred. E_OS_PROTECTION_EXCEPTION: A trap occurred. E_OS_SYS_PROTECTION_SYSCALL: An unhandled syscall occurred. E_OS_STACKFAULT: A stack fault detected via stack monitoring by the OS. E_OS_SYS_API_ERROR: Wrong API usage. |
1.3 Davinci中配置OsHooks
三個(gè)Error相關(guān)的Hook函數(shù)可以在Davinci中配置,如果配置后就需要用戶自定義實(shí)現(xiàn)。
2. 自定義錯(cuò)誤處理
通過第一節(jié),我們知道了Error的類型及其包含的具體的Error Code,同時(shí),如果我們配置Error發(fā)生后Hook函數(shù),那么在Error發(fā)生時(shí)我們就能被通知到。那么現(xiàn)在,我們在Error發(fā)生后應(yīng)該考慮如何存儲錯(cuò)誤相關(guān)的信息,同時(shí)能在事后通過存儲的Error相關(guān)信息定位和分析Error。
2.1 錯(cuò)誤信息存儲
背景知識1:RAMRetention。RAMretention是一種技術(shù),用于在斷電后保持隨機(jī)存取存儲器(RAM)中的數(shù)據(jù)。在計(jì)算機(jī)系統(tǒng)中,RAM是一種易失性存儲器,這意味著在斷電情況下,其中的數(shù)據(jù)會被清除。這對于一些應(yīng)用程序來說是不可接受的,因?yàn)樗鼈冃枰跀嚯姾笕匀荒軌虮3謹(jǐn)?shù)據(jù)。這就是RAMretention技術(shù)的用武之地。
背景知識2:斷電系統(tǒng)和深度休眠系統(tǒng)。ECU在設(shè)計(jì)時(shí)根據(jù)具體需求可以在硬件上添加SBC或無SBC。如果ECU有SBC,ECU就是一個(gè)斷電系統(tǒng)。那么ECU在系統(tǒng)下電(Shutdown)流程的最后一步會調(diào)用SBC的服務(wù)接口斷掉MCU的電,整個(gè)MCU在休眠中是處于斷電狀態(tài)的。在外部信號(Can Transceiver/Lin Transceiver的INH引腳,Dio喚醒引腳 )喚醒MCU時(shí),SBC重新給MCU供電,MCU重新冷啟動。
如果ECU無SBC,ECU就是一個(gè)深度休眠系統(tǒng)。那么ECU在系統(tǒng)下電(Shutdown)流程的最后一步會調(diào)用MCU的服務(wù)進(jìn)入到Deep Sleep深度休眠狀態(tài)(MCU陷入深度休眠狀態(tài),程序不在運(yùn)行,但是MCU還有電存在)。在外部信號(Can Transceiver/Lin Transceiver的INH引腳,Dio喚醒引腳 )通過中斷喚醒MCU,MCU被喚醒后,程序可以選擇軟件復(fù)位,整個(gè)軟件重新運(yùn)行,也可以選擇從上次停止的地方接著運(yùn)行。
Aurix芯片進(jìn)入深度休眠后后SCR會接管芯片控制,在進(jìn)入SCR前可以配置PMS模塊的PMSWCR0.STBYRAMSEL位域,選擇給哪快RAM進(jìn)行供電。只有休眠后改被供電的RAM才有RAMRetentions的功能。
問題1:為什么要考慮錯(cuò)誤信息的存儲了?
答:因?yàn)镋rror發(fā)生時(shí)如果時(shí)Protection Error的話,一般就會在OS調(diào)用ProtectionHook()后執(zhí)行Shutdown,在ShutdownHook()中一般執(zhí)行ECU復(fù)位了,如果我們不存儲Error發(fā)生時(shí)的上下文信息的話,一旦系統(tǒng)復(fù)位的話我們就無法再分析Error發(fā)生的原因了。
問題2:錯(cuò)誤信息存儲在那里了,是不是可以存儲在NvM?
答:錯(cuò)誤信息可以存儲在NvM中,但是因?yàn)镻rotectionHook()后一般馬上就要進(jìn)行MCU復(fù)位了,來不及調(diào)用異步的NvM接口來存儲錯(cuò)誤信息了,所以只能把錯(cuò)誤信息存儲到Retention RAM中。復(fù)位起來后,錯(cuò)誤信息處理SWC讀取Retention RAM中的異常信息,此時(shí)可選擇是否再次寫入到NvM當(dāng)中。
Note:
1.如果系統(tǒng)是斷電系統(tǒng),那么一定要注意OS ShutdownHook()中調(diào)用Mcu_PerformReset()進(jìn)行軟件復(fù)位而不是調(diào)用SBC的接口給MCU斷電,因?yàn)镸CU斷電后是冷啟動,Retention RAM中的數(shù)據(jù)也沒了。
2.如果系統(tǒng)是深度休眠系統(tǒng)且使用Aurix芯片的SCR功能,那么Retention RAM一定要配置在PMSWCR0.STBYRAMSEL配置供電的RAM塊中。
3.無論是深度休眠系統(tǒng)還是斷點(diǎn)系統(tǒng),MCU復(fù)位后在Main函數(shù)之前的Startup階段都不能把Retention RAM給清零了(需要修改啟動代碼和連接器腳本)。
2.2 關(guān)鍵上下文信息獲取
問題1:通過2.1小結(jié)我們知道錯(cuò)誤信息應(yīng)該存放在Retention RAM當(dāng)中,那么我們應(yīng)該存儲哪些異常時(shí)的上下文信息了?
答:我們通過一個(gè)表格來舉例給出答案。
Error Types | Error Contex |
Application Errors |
如果在使用Spinlock是發(fā)生Application Error,可以獲取以下信息: 1.通過Os_GetDetailedError()獲取服務(wù)ID及Error Code等信息。 2.通過OSError_GetSpinlock_SpinlockId()返回錯(cuò)誤的GetSpinlock調(diào)用的參數(shù)SpinlockId. 使用其他OS服務(wù),比如Alarm, Resource等發(fā)生錯(cuò)誤時(shí)同樣可以調(diào)用OsError_xxx_xxx()獲取相關(guān)錯(cuò)誤現(xiàn)場信息。 |
Protection Errors |
1.ProtectionHook()的參數(shù)Fataerror. 2.通過GetTaskID獲取Error發(fā)生時(shí)的正在處理的Task. 3.通過GetISRID()獲取當(dāng)前執(zhí)行ISR的標(biāo)識符。 4.通過Os_GetExceptionAddress()獲取引發(fā)最新異常的指令的地址。 5.讀取DEADD寄存器獲取發(fā)生trap時(shí)的地址信息。 6.通過Os_GetExceptionContext()獲取異常上下文信息,異常結(jié)構(gòu)體為:struct Os_ExceptionContextType_Tag; 通過結(jié)構(gòu)體成員Ra和ExceptionSource對應(yīng)的TIN和Class信息,可以輕松定位MPU保護(hù)產(chǎn)生的Error. |
Kernel Errors | 通過GetTaskID獲取Error發(fā)生時(shí)的正在處理的Task. |
/*!Setofhardwareregisterstobeabletoresumefromanexception.*/ structOs_ExceptionContextType_Tag { /*StoredAddressregistersofthethread(a2-a7,a12-a15)*/ uint32AddressRegisters[16]; /*StoredDataregistersofthethread(d0-d15)*/ uint32DataRegisters[16]; /*!Storedreturnaddressofthethread*/ uint32Ra; /*!StoredPswofthethread*/ uint32Psw; /*!StoredExceptionsource(Exceptionclassandtinnumber)ofthethread*/ uint32ExceptionSource; /*!StoredPcpn(PreviousCPUPrioritynumber)fromthePcxiofthethread*/ uint32Pcpn; /*!StoredPie(PreviousInterruptEnable)fromthePcxiofthethread*/ uint32Pie; /*!TheloweraddressoftheMPUregionforstack.*/ uint32MpuRegionForStackLow; /*!TheupperaddressoftheMPUregionforstack.*/ uint32MpuRegionForStackUpper; /*!TherawPCXIvaluefromtheuppercontext;maybeusedtolookupinCSAspriortotheexception*/ uint32RawPCXI; };
2.3 錯(cuò)誤定位
對于Application Error一般都是錯(cuò)誤使用OSAPI導(dǎo)致的,只要我們記錄好錯(cuò)誤發(fā)生時(shí)的ServiceID等就能輕松定位。
對于Kernel Error由于OS內(nèi)部數(shù)據(jù)可能被異常打亂了,數(shù)據(jù)不在可信,可獲取的上下文信息不多,這類錯(cuò)誤就只能根據(jù)具體硬件平臺和OS代碼積累經(jīng)驗(yàn)了(開發(fā)階段可以通過故障注入提前獲知Kernel Error產(chǎn)生后的表現(xiàn))。
實(shí)際項(xiàng)目中最可能出問題的就是Protection Error了,而這里面也以MPU保護(hù)Error為最常見。出現(xiàn)內(nèi)存保護(hù)Error后,通過Ra(A11程序返回寄存器)查找Map文件可以大概知道那塊代碼(指令所在的地址)發(fā)生異常;通過DEADD寄存器可以得知大概是訪問了哪塊Data數(shù)據(jù)(訪問的數(shù)據(jù)的地址)發(fā)生了異常,比如異常改寫了調(diào)用棧內(nèi)容。
3.總結(jié)
最后通過回答開頭的三個(gè)問題來結(jié)束本文。
問題1:有哪里常見的OS錯(cuò)誤 ?
答:大類有Application Errors, Protection Errors, Kernel Errors三種,每種大類包含的具體ErrorCode可以參考1.1章節(jié)。
問題2:如何進(jìn)行OS錯(cuò)誤處理?
答:通過Retention RAM來存儲OS錯(cuò)誤信息,通過OS給出的一系列API獲取Error發(fā)生時(shí)的上下文信息。
審核編輯:劉清
-
RAM
+關(guān)注
關(guān)注
8文章
1369瀏覽量
114813 -
SCR
+關(guān)注
關(guān)注
2文章
150瀏覽量
44237 -
AUTOSAR
+關(guān)注
關(guān)注
10文章
363瀏覽量
21639 -
SBC
+關(guān)注
關(guān)注
0文章
78瀏覽量
19215 -
易失性存儲器
+關(guān)注
關(guān)注
0文章
14瀏覽量
6736
原文標(biāo)題:AUTOSAR架構(gòu)下的OS錯(cuò)誤處理
文章出處:【微信號:汽車電子嵌入式,微信公眾號:汽車電子嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論