DEM診斷事件管理之二——report
Report
圖1: dependencies of the Diagnostic Event Manager to other software modules
report也就是SWC或者BSW給DEM報診斷事件的狀態。它由兩個部分組成,一個是診斷事件(diagnostic event),一個是濾波(debounce)。可以把應用層或者BSW監控(monitor)某個組件component叫做一個診斷事件(diagnostic event),DEM會給每個診斷事件分配一個獨一無二的識別碼(EventId),來區分不同的事件。如應用層週期監控(monitor)KL30電電壓(component)是否過壓叫做一個診斷事件。在這個診斷事件中檢測電壓是否超過正常值的上限,再通過
Std_ReturnType FiM_GetFunctionPermission(
FiM_FunctionIdType FID,
boolean* Permission )
判斷是否該功能被抑制(即診斷KL30電壓過壓的功能[1]),如果沒有被抑制且電壓超過有效範圍最大值,這時SWC調用
Dem_SetEventStatus(EventID, DEM_EVENT_STATUS_PREFAILED)[2]
接口把診斷事件及診斷事件狀態報給DEM;如果沒有被抑制且電壓沒有超過有效範圍最大值,這時SWC調用
Dem_SetEventStatus(EventID, DEM_EVENT_STATUS_PREPASSED)
接口把診斷事件及狀態報給DEM;如果被抑制了,SWC也應當給DEM提示當前的功能無法執行,DEM會在內部對debounce的一些數據進行處理,如把debounce的counter復位。僞代碼如下:
注[1]:電壓監控事件怎麼還能被抑制呢?因爲這種診斷功能(function)都會與其他的事件相關聯,存在其他的功能失效導致該功能會被抑制,所以在執行前都需要調用FiM_GetFunctionPermission( FID, &Permission )獲得執行的權利。可以防止由一個其他功能引起的另外一個功能異常的誤報,如母線電壓過低時,會導致抑制電機輸出扭矩輸出功能,診斷扭矩輸出的功能也會被抑制。FIM功能多用於SWC,也可用於BSW。
注[2]:對於診斷事件發生故障時可以持續的給DEM發送DEM_EVENT_STATUS_PREFAILED狀態,DEM內部debounce時,debounce counter不會重新計數;同樣當每一次診斷事件結果passed時,可以持續的給DEM發送DEM_EVENT_STATUS_PREPASSED狀態,DEM內部debounce時,debounce counter不會重新計數。具體詳見下面的debounce章節。
void DiagOverVolt(void)
{
res = ChkOverVolt()
if(E_OK == Fim_GetFunctionPermission(diag_volt_fid, &permission))
{
if(*permission == TRUE)
{
if(res == True)
{
Dem_SetEventStatus(diag_volt_event_id, DEM_EVENT_STATUS_PREFAILED);
}
else
{
Dem_SetEventStatus(diag_volt_event_id, DEM_EVENT_STATUS_PREPASSED);
}
}
else
{
Dem_SetEventStatus(diag_volt_event_id, 0xff);//0xff means inhibition
}
}
else
{…}
}
診斷事件分類:
診斷事件分爲兩種,一種是在SWC應用層的診斷事件,這種事件在report時使用的診斷接口爲:
Std_ReturnType Dem_SetEventStatus(
Dem_EventIdType EventId,
Dem_EventStatusType EventStatus
)
還有一種診斷事件是在BSW中的診斷事件,這種事件在report時使用的診斷接口爲:
void Dem_ReportErrorStatus(
Dem_EventIdType EventId,
Dem_EventStatusType EventStatus
)
如NVM的寫入錯誤、讀取錯誤、校驗錯誤等,這些不需要debounce,可以直接判定是failed還是passed,直接調用Dem_ReportErrorStatus(NvmReadErrId, DEM_EVENT_STATUS_FAILED)。
Debounce
SWC的debounce邏輯:
當SWC通過Dem_SetEventStatus(EventId, EventStatus)把事件狀態報給DEM後,剩下的工作全權由DEM處理。SWC是周期函數,一般在檢測某個故障是否發生時,不會因爲一個週期檢測到失效,就判定該故障發生,而是故障發生持續一定的時間。而診斷事件狀態從failed到passed也不是立即變化,也需要消抖(debounce)一定次數或時間。這也就是爲什麼需要debounce的原因。
消抖算法有基於時間的和基於次數的,兩者可以統一於基於次數,因爲對於診斷事件都是一個週期行的任務,消抖時間可以等於任務執行週期乘以次數,所以可以用消抖次數代替消抖時間。
debounce的幾個參數
items |
description |
details |
step-size/ DemDebounceCounterIncrementStepSize/DemDebounceCounterDecrementStepSize |
步長 |
每次debounce counter增加或者減少的長度 |
debounce counter |
消抖計數器 |
sint16類型的 |
DemDebounceCounterFailedThreshold |
|
使得診斷事件狀態爲failed的debounce counter的閾值 |
DemDebounceCounterPassedThreshold |
|
使得診斷事件狀態爲passed的debounce counter的閾值 |
DemDebounceCounterJumpDownValue |
|
當debounce counter大於該值時,如果這時診斷事件的EventStatus是prefailed,那麼debounce counter會被初始化爲該值。這個機制是在DemDebounceCounterJumpDown爲true的條件下使能。 |
DemDebounceCounterJumpUp |
|
當debounce counter小於該值時,如果診斷事件的EventStatus是prepassed,那麼debounce counter會被複位爲該值。這個機制是在DemDebounceCounterJumpUp爲true的條件下使能。 |
可以從下圖中(原圖來自AUTOSAR_SWS_DiagnosticEventManager Figure 7.30)可以清晰地看出debounce counter的意義。
圖2:Example of counter based debouncing
IncreatementStepSize和DecreasementStepSize長度可以不同,DFCmax和FDCmin也不用互爲相反數,根據不同需求確定這些參數。
但是在實際應用中,我們更希望failed狀態能夠更快速地可靠地報出來,而從failed恢復正常到passed的狀態是足夠可靠,所以當EventStatus爲prefailed變爲prepassed時,讓debounce counter自然地從當前的數值往下減少,不使用DemDebounceCounterJumpDown機制;DemDebounceCounterJumpUpValue設置爲0,這樣即使當前debounce counter小於0,即爲prepassed的狀態,當EventStatus變爲prefailed時,debounce counter重新從0計數,然後再以IncrementStepSize向上增長;即使會中途出現prepassed狀態,也不影響。如下圖:
圖3:實際應用中的debounce 方式
從兩圖中可以發現每次report的EventStatus都是Prefailed或者Prepassed,而不是Failed或者Passed,因爲對於需要debounce的故障而言,每次SWC對component的監控結果爲failed或者passed,都是瞬態的,即使這個故障發生時間很長,SWC依然可以report這個故障的狀態爲prefailed,因爲在DEM的denounce模塊,該故障的debounce counter早已超過FDCmax,故障狀態早已是failed了。在autosar文檔規定,當debounce counter大於等於DFCmax時,即使SWC繼續report EventStatus爲prefailed,debounce counter也不會繼續增加,而是保持DFCmax,這樣SWC和debounce counter兩者都相得益彰,SWC也不用進行什麼時候報prefailed什麼時候報failed的邏輯。
debounce方式分類
對於不同的診斷事件,debounce counter範圍可以是(-128~127),也可以是(-32768~32767),也可以不進行debounce,可以根據不同的需要,合理的使用debounce方式和FDCmax和FDCmin。
debounce對UDS DTC狀態的影響
UDS的8個故障狀態位爲別爲:
bit0 |
testFailed |
bit1 |
testFailedThisOperationCycle |
bit2 |
pendingDTC |
bit3 |
confirmedDTC |
bit4 |
testNotCompleteSinceLastClear |
bit5 |
testFailedSinceLastClear |
bit6 |
testNotCompleteThisOperationCycle |
bit7 |
warningIndicatorRequested |
依據AutoSAR描述,當event report的EventStatuse爲passed或者failed或者bounce counter到達debounce counter的閾值時,UDS Status的bit0(TestFailed)、bit1(TestFailedThisOperationCycle)和bit6(TestNotCompletedThisOperationCycle)會發生變化,根據ISO14229-1_2013規定,bit4(testNotCompletedSinceLastClear)由“1”變爲“0”的條件是“DTC測試的結果爲passed或者failed”;bit5(testFailedSinceLastClear)由“1”變爲“0”的條件是“從上一次診斷信息被清除之後的DTC測試結果爲failed”。
bit0 testFailed
translation |
condition |
0 -> 1 |
test Failed |
1 -> 0 |
test passed | 14 (FF FF FF) | reset |
bit1: testFailedThisOperationCycle
translation |
condition |
0 -> 1 |
test Failed |
1 -> 0 |
14 (FF FF FF) | operation cycle end -> start(KL15 off to on) |
bit2: pendingDTC
pending狀態位的置位放在primary memory中處理,詳見DEM之Event memory。
bit3: confirmedDTC
confirmedDTC狀態位的置位放在primary memory中處理,詳見DEM之Event memory。
bit4: testNotCompletedSinceLastClear
translation |
condition |
0 -> 1 |
test Failed |
1 -> 0 |
14 (FF FF FF) |
bit5: testFailedSinceLastClear
translation |
condition |
0 -> 1 |
test Failed |
1 -> 0 |
14 (FF FF FF) | replaced by other event in EventMemory | aged |
bit6: testNotCompletedThisOperationCycle
translation |
condition |
0 -> 1 |
test Failed |
1 -> 0 |
14 (FF FF FF) | operation cycle end -> start(KL15 off to on) | aged |
bit7 warningIndicatorRequested:
pending狀態位的置位放在primary memory中處理,詳見DEM之Event memory。
綜上可知,在經過了debounce或者no debounce濾波之後的結果爲failed時,bit4和bit6會被清零,bit5應當被置一;在經過debounce的或者no debounce濾波之後的結果爲passed時,bit4和bit6會被清零。
而bit2(pendingDTC)、bit3(confirmedDTC)和bit7(warningIndicatorRequested)是需要在Fault memory中其他的條件去判斷(具體的可以在Fault Memory章節和UDS Status大總結中看到),所以這3個位和debounce影響的4個UDS狀態位是異步置位。由於診斷事件report故障及狀態是獨立於DEM模塊,所以爲了保存debounce之後的故障狀態,可以給每個故障再給配一個變量記錄debounce的狀態。僞代碼如下:
#define DEM_DEB_MASK_FAILED 0x01
#define DEB_DEB_MASK_FAILED_CYCLE 0x02
#define DEB_DEB_MASK_FAILED_NOT_COMPLETED_CLR 0x10
#define DEB_DEB_MASK_FAILED_NOT_COMPLETED_CYCLE 0x40
struct Dem_Deb_Cnf_Struct
{
uint16* Deb_DecSize;
uint16* Deb_IncSize;
uint16* Deb_MaxSize;
};
struct Dem_Deb_Info
{
uint8 status;
uint16 deb_ctr;
};
uint16 Dem_Deb_Dec[]={1,2,3,4};//for prepassed
uint16 Dem_Deb_Inc[]={1,2,3,4};//for prefailed
uint16 Dem_Deb_Max[]={10,8,9,8};
struct Dem_Deb_Cnf_Struct Dem_Deb_Cnf_Ptr;
void Dem_Deb_Init(void)
{
Dem_Deb_Cnf_Ptr->Deb_DecSize = Dem_Deb_Dec;
Dem_Deb_Cnf_Ptr->Deb_IncSize = Dem_Deb_Inc;
Dem_Deb_Cnf_Ptr->Deb_MaxSize = Dem_Deb_Max;
}
uint16 Dem_Deb_Prepass(Dem_Deb_Info* dem_deb_info_ptr, Dem_EventIdType EventId)
{
uint16 something;
tmp_deb_ctr=dem_deb_info_ptr->deb_ctr;
tmp_minux_max = (-1)*Dem_Deb_Cnf_Ptr->Deb_MaxSize[EventId];
if(tmp_deb_ctr<=tmp_minux_max)
{
Dem_Deb_Pass(dem_deb_info_ptr, EventId);
}
else
{
if(tmp_deb_ctr<=0)
{
tmp_deb_ctr -= Dem_Deb_Cnf_Ptr->Deb_IncSize;
}
else
{
tmp_deb_ctr -= Dem_Deb_Cnf_Ptr->Dem_Deb_Dec;
if(tmp_deb_ctr <= tmp_minux_max)
{
Dem_Deb_Pass(dem_deb_info_ptr, EventId);
}
}
}
dem_deb_info_ptr->deb_ctr = tmp_deb_ctr;
return something;
}
uint16 Dem_Deb_Pass(Dem_Deb_Info* dem_deb_info_ptr,, Dem_EventIdType EventId)
{
dem_deb_info_ptr->status &= (uint8)~DEM_DEB_MASK_FAILED;
dem_deb_info_ptr->status &= (uint8)~DEB_DEB_MASK_FAILED_NOT_COMPLETED_CLR;
dem_deb_info_ptr->status &= (uint8)(~DEB_DEB_MASK_FAILED_NOT_COMPLETED_CYCLE);
}
更多內容,可關注公衆號“激活未來”。