01不安全的CAN總線
1、如何保證ECU接收到的數(shù)據(jù)是合法的?
比如ECU1接收ECU2發(fā)出的一幀0x100報文,協(xié)議層是不會區(qū)分是ECU1發(fā)的,還是非法接入OBD的CAN盒發(fā)的?如果ECU1接收到非ECU2發(fā)出的0x100報文豈不是很危險?
2、ECU如何知道另一個節(jié)點(diǎn)掛死
比如ECU1還是接收ECU2發(fā)出的一幀0x100報文,但是由于某些神秘原因(程序跑飛了)導(dǎo)致ECU2掛死或者掉線,那ECU1如何知道此時的接收到0x100無效?
CAN通訊是一種廣播形式的通訊方式,自然協(xié)議層是無法做到數(shù)據(jù)合法性的校驗,這部分工作需要應(yīng)用層來完成。由此就出現(xiàn)了RollingCounter與Checksum。這兩個東西好像也是功能安全的一部分,本期只是介紹這兩個東西的原理,不對功能安全做過多討論。
一個規(guī)范的CAN矩陣協(xié)議,每一幀報文都會要求有這個兩個信號。如上圖,從bit52到bit55是RollingCounter,取值范圍0~15,ECU沒發(fā)一次自動累加,滿15就歸零。從bit56到bit63(byte8)都是Checksum,取值范圍0x00~0xFF,用來表示該條報文的校驗值。
對于判斷發(fā)送報文ECU有沒有掛死很簡單,只要在接收端對RollingCounter進(jìn)行判斷,幾個周期內(nèi)協(xié)議棧上的buff沒有得到更新則就能判斷為節(jié)點(diǎn)異常。
對于報文合法性的判斷則就要負(fù)責(zé)得多,且會有各種花樣
車企制定的通訊協(xié)議時,除了制定矩陣信號外,會規(guī)定Checksum的計算方法,比如這個是采用多項式的CRC校驗算法。
并且規(guī)定出需要校驗的數(shù)據(jù),有的是對矩陣的前7個byte進(jìn)行校驗,有的則要增加報文ID作為校驗計算的輸入,各種花樣都有。
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * CRC8校驗子程序0x1D(x8+x4+x3+x2+1) * * * * * * * * * * * * * * 參數(shù)1,uint8_t *data:需要計算的數(shù)據(jù) * * * * * * * * * * * * * 參數(shù)1,uint16_t len:需要計算的數(shù)據(jù)字節(jié)長度 * * * * * * * * * * 返回值,uint8_t crc8:計算出的CRC值 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ uint8_t crc_8find(uint8_t *data, uint16_t len) { uint8_tcrc8=0x00; while( len-- ) { crc8 = crc_table[crc8 ^ *data]; data++; } return crc8; }
甚至貼心的給出校驗計算的偽代碼,這函數(shù)寫法C、C++應(yīng)該都可以直接運(yùn)行的。理解下上面的代碼!
當(dāng)ECU2發(fā)出0x100之前,會對RollingCounter累加,并且通過計算包含RollingCounter的前七個字節(jié)的CRC值,填充到數(shù)據(jù)域的第8個字節(jié);
ECU1接收到0x100的時候使用同樣的校驗算法,計算數(shù)據(jù)域的前7個字節(jié),并且與第8個字節(jié)發(fā)送源計算的CRC值進(jìn)行比較。如果兩者相同,則數(shù)據(jù)合法。
02CANOE仿真
接下來在CANOE的CAPL進(jìn)行RollingCounter與Checksum的模擬
創(chuàng)建兩個ECU節(jié)點(diǎn),ECU1為發(fā)送節(jié)點(diǎn),ECU2為接收節(jié)點(diǎn)。ECU2會對ECU1的節(jié)點(diǎn)做Checksum,如果非法數(shù)據(jù)會在log窗口中打印出來。ECU1會而這個IG是用來模擬非法的數(shù)據(jù)發(fā)送。
int GetCrcChecksum (int crc_position ,message *data) { byte checksum; byte bitIndex; byte byteIndex; byte tdata; checksum = 0x00; for (byteIndex = DBLookup(data).dlc; byteIndex >= 1; byteIndex--) { if(byteIndex-1 != crc_position) { tdata = data.byte(byteIndex-1); } else { tdata = 0; } checksum ^= tdata; for (bitIndex = 0; bitIndex < 8; bitIndex++) { if ((checksum & 0x80) != 0) { checksum = (checksum << 1) ^ 0x1D; // cb_CRC_POLY: 0x1D } else { checksum = (checksum << 1); } } } checksum &= 0xFF; return (checksum); }
CAPL計算Checksum的函數(shù),在ECU1與ECU2里都存在
on timer Timer1 { Req.rollingCounter_0x100=LiveCount; Req.checksum_0x100=GetCrcChecksum(7,Req); output(Req); setTimer(Timer1,20); LiveCount=LiveCount+1; if(LiveCount==16) { LiveCount=0; }
ECU1的定時器函數(shù),發(fā)送前調(diào)用GetCrcChecksum函數(shù)生成Checksum
on message RCTest1 { if(this.checksum_0x100==GetCrcChecksum(7,this)) { Rep=this; }else { write("Invaild Message"); } }
ECU2接收事件中重新計算Checksum跟發(fā)送報文里的Checksum進(jìn)行比較,不同則拋出錯誤
按F2,開始仿真,可以監(jiān)控到ECU1發(fā)送出來的rollingCounter與Checksum
在Write窗口中打印ECU2接收到的數(shù)據(jù)
在IG節(jié)點(diǎn)設(shè)置一個非法的報文,rollingcounter與Checksum都設(shè)置0
對非法數(shù)據(jù)進(jìn)行拋出。
來源:古德曼汽車工業(yè)
審核編輯:湯梓紅
-
CAN總線
+關(guān)注
關(guān)注
145文章
1908瀏覽量
130501 -
仿真
+關(guān)注
關(guān)注
50文章
3995瀏覽量
133223 -
ecu
+關(guān)注
關(guān)注
14文章
865瀏覽量
54331 -
通訊協(xié)議
+關(guān)注
關(guān)注
10文章
265瀏覽量
20294
原文標(biāo)題:CAN總線報文數(shù)據(jù)一致性校驗
文章出處:【微信號:談思實驗室,微信公眾號:談思實驗室】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論