ELM327 OBD-II 心得 (9),驗屍報告3,CANBUS起碼要有兩個裝置!
給開發板做個家
亂成一團的設備也是Bug來源,我請收納專家(老婆)幫忙改善。收納真的是專業!
玩MCU還是要沾醬油(Data Sheet)
換STM32優點是環境單純,而且STM給了CAN驅動程式,沾醬油(Reference Manual)服用更美味,這份文件有1954頁。我想起十年前刻S3C2410 bootloader的往事,整份datasheet大概600頁我也幾乎讀遍,把peripheral driver全部寫一輪
開卷有益,我對CAN Bus又有一些新的了解,也修掉幾個Bug。底下文字我純粹留個紀錄,客官看看就好
其實關鍵的問題就是:汽車和我的書桌究竟哪裡不一樣,為什麼書桌上OK,汽車會死。HUD設計時,應該預期連上活的網路,上面有很多裝置在溝通,眾聲喧嘩;書桌上的網路很安靜。中間人攻擊發動時,我會有兩個CAN網路
中間人串起的兩個網路,如果是無條件轉發,兩個封包的負載完全一樣:從HUD發資料到CAR會多吃一發arbitration delay
STM32的開發環境
最後我想聊一下開發環境,底下是我用的工具和挑選的理由
亂成一團的設備也是Bug來源,我請收納專家(老婆)幫忙改善。收納真的是專業!
- 開發板的針腳插入泡棉當底座,底座再用熱熔膠貼在盒子裡
- 專家:網購的紙箱都是用熱熔膠固定,唯一答案
- 杜邦線用束帶固定在盒子邊緣
- 專家:這種紙不能用膠帶黏,束帶才是正解,還可以反覆調整
- 在盒子挖洞固定OBD-II頭(熱熔膠固定),以及走USB線
- MCU開發板,供電和燒錄用
- OBD-II供電,5V轉12V給設備用
- 樹莓派供電
- 這篇文章最後的結論:樹莓派妙用無窮!
玩MCU還是要沾醬油(Data Sheet)
換STM32優點是環境單純,而且STM給了CAN驅動程式,沾醬油(Reference Manual)服用更美味,這份文件有1954頁。我想起十年前刻S3C2410 bootloader的往事,整份datasheet大概600頁我也幾乎讀遍,把peripheral driver全部寫一輪
開卷有益,我對CAN Bus又有一些新的了解,也修掉幾個Bug。底下文字我純粹留個紀錄,客官看看就好
- STM32 boot code預設沒開CAN重傳,這個功能必須打開
- 封包從HUD轉發到汽車時,很有可能被忙碌的CAN BUS撞掉,需要重傳
- 如果沒開重傳,STM32發送失敗就會丟掉封包,於是HUD以為車子不理他
- STM的register命名很爛:NART,No Auto ReTransmission
- 我自己寫軟體很注意正向表列,0關閉,1打開,符合人類直覺才好debug
- 名字要正向表列才對,改成ENART(Enable Auto ReTransmission)
- STM32的CAN-TX很強,Mailbox能承受3個message排隊
- 直接發送封包即可,如果queue滿了軟體印條紀錄就好
- 拔掉畫蛇添的semaphore可以拔掉(沒寫他造成程式鎖死)
- STM32的CAN-RX也很強,有兩套FIFO,每套FIFO都能存3個message
- 基本上不大需要擔心buffer overflow
- STM32的CAN1/CAN2共享資源,需要透過CAN1幫CAN2設定Filter的起點和參數
- 他硬體就是這樣做,不知道就會卡很久
靈光一閃
其實關鍵的問題就是:汽車和我的書桌究竟哪裡不一樣,為什麼書桌上OK,汽車會死。HUD設計時,應該預期連上活的網路,上面有很多裝置在溝通,眾聲喧嘩;書桌上的網路很安靜。中間人攻擊發動時,我會有兩個CAN網路
- CAN1
- CAR or Pi-CAR
- RPi-MITM
- CAN2
- HUD
- RPi-MITM
設備接上汽車,封包會從CAN1不斷轉發到CAN2。如果HUD還沒上電,等於CAN2只剩RPi-MITM。他自顧自的發送封包,但是沒人理他。這時CAN控制器內部的
TEC (Transmit Error Count)會不斷累加,數到255就自己消音進入bus-off狀態,不再打Ack。我設定RPi等10ms會解開Bus-Off。這代表HUD加入時,如果RPi正在耍自閉(Bus-OFF),HUD也會沒反應
TEC (Transmit Error Count)會不斷累加,數到255就自己消音進入bus-off狀態,不再打Ack。我設定RPi等10ms會解開Bus-Off。這代表HUD加入時,如果RPi正在耍自閉(Bus-OFF),HUD也會沒反應
假如HUD加入網路瞬間,RPi-MITM把堆在TX-Queue的東西一股腦送出(我又把Queue弄得很深1024,清光需要0.2秒),變成HUD的查詢要等很久才發出,最後就time-out死掉。也許我可以把TX-Queue弄淺一點作實驗,不過還是會周期的進入Bus-off狀態,這樣解不漂亮
所以正確的解法是滿足HUD設計的場景:隨時都有兩個以上的CAN裝置
所以正確的解法是滿足HUD設計的場景:隨時都有兩個以上的CAN裝置
- CAN1
- CAR or Pi-CAR
- STM32-CAN1 (package forwarding)
- RPi-CAN0 (dummy client/ sniffer)
- CAN2
- HUD or VIDA-DICE
- STM32-CAN2 (package forwarding)
- SRPi-CAN1 (dummy client/ sniffer)
同時放上RPi和STM32,利用STM32轉發,HUD上電就是活的網路,理論上就能正常運作。RPi好用就在這裡:他可以滿足CAN網路的需要(起碼兩個元件),也可以當監聽設備,還可以輕鬆保存大量資料(高速CPU,很大的記憶體,GB等級的儲存空間)。我本來還在煩惱怎麼從STM32取數據出來(在考慮要不要搞USB或Ethernet),暫時可以省掉這個工夫
其實中間人的延遲比想像得再多一點
中間人串起的兩個網路,如果是無條件轉發,兩個封包的負載完全一樣:從HUD發資料到CAR會多吃一發arbitration delay
- HUD封包在CAN2發送時,先承受一次Arbitration delay
- 在CAN1發送到汽車時,還要再承受一次Arbitration delay
STM32的開發環境
最後我想聊一下開發環境,底下是我用的工具和挑選的理由
- STM32 CUBEMX
- STM提供的boot code generator,可以不用自己手刻,配置環境很方便
- 想玩USB也有資源
- Atollic True Studio
- 純粹當GCC編譯工具,不用折騰toolchain,同時避免用Keil ARM這類版權物
- 他的編輯器我用不慣,Code complete無法用
- Debugger透過gdb連線的體驗不大好,無法attach上裝置;不過他的OS awareness有FreeRTOS,可以看semaphore,Queue的狀態,改天可以試試看
- Sublime text 3
- 近年來我愛用的編輯器,Windows/Linux跨平台
- Convert ST-Link on-board into a J-Link
- 感謝SEGGER,可以把板子上的ST-Link變J-Link,我用得很開心
- 我對J-Link是真的很有感情的
- Segger OZone Debugger
- 專業,免費,而且還是跨平台(Windows/ MacOS/ Linux)的debugger
- 大部分的IDE都有Debugger,但是未必用得順手
- Keil ARM的debugger很好用,不過要錢,未必用得心安理得
- Attolic True Studio這類gdb-based debugger有時候真的難用
- SEGGER OZone有專人維護,而且好用,值得投資時間精通
- Amazon FreeRTOS
- 感謝Amazon買下FreeRTOS,以前要賣錢的文件現在可以以直接下載
- 這個年代,拉攏開發者就對了
- MCU寫一個while(1)搭配中斷是一種玩法,這個適合寫小程式
- MCU搭配Real Time Kernel是另一種風情,可以架構大型程式。如果要挑一個投資時間,有富爸爸Amazon撐腰的FreeRTOS絕對是上上之選,裡面已經有現成的TCP/IP stack(注意,這個以前要賣錢的),日後想玩IoT也可以
留言