CAN總線錯誤分析方法

    我們先簡單總結一下CAN的錯誤處理與故障界定:

    1.CAN控制器記錄發生在發送/接收過程中,總線數據出現錯誤的總數(位錯誤,CRC錯誤等)。

    2.CAN控制器根據總線出錯數量由低到高,依次處於主動錯誤狀態,被動錯誤狀態,以及總線關閉狀態。

    3.位於主動錯誤的節點,在檢測到錯誤時,可以發送主動錯誤標誌(6位顯性位),告知總線上所有節點發生了總線的錯誤,之後進行正常的收發操作。保證如果總線CAN_H與CAN_L出現短路等會影響整個總線通訊的問題時,各個控制器會迅速反應。

       當隨着發送/接收錯誤總數的增加,節點將位於被動錯誤狀態,當檢測到總線發生錯誤的時候,將等待總線出現被動錯誤幀(連續6位隱性位),之後纔可正常進行收發操作。保證如果總線因爲線長或者節點數增大,遠處的節點干擾嚴重,則干擾嚴重的節點將不會影響其餘節點的正常通信。

        如果發送錯誤總數達到了255,則進入bus-off狀態,處於這種狀態的節點將會與總線隔離,直到檢測到128 次出現11 個連續“隱性”位後,纔可以恢復錯誤主動狀態,錯誤計數器 也清零。

1.Linux SocketCAN

    Linux 4.17.0-RC6 內核網絡部分增加了SocketCAN,用於Linux的CAN協議的一種實現。以前的嵌入式開發板的CAN驅動是以基於字符串設備的驅動註冊到內核中,新的內核使用Berkeley套接字API,Linux網絡堆棧並將CAN設備驅動程序作爲網絡接口來實現。CAN套接字API的設計與TCP / IP協議儘可能相似,以便熟悉網絡編程的程序員輕鬆使用CAN套接字進行CAN通信。具體詳細的特性介紹詳見https://www.kernel.org/doc/html/latest/networking/can.html。其中章節“Network Problem Notifications中介紹了一種CAN總線錯誤的記錄機制,SocketCAN將所有總線上的錯誤包裝成一個“錯誤幀”,注意這塊的“錯誤幀”不是CAN總線上實際跑的錯誤幀,而是驅動部分將控制器或者總線上的檢測的錯誤,包裝成一個CAN幀,上報給基於網絡層之上的用戶程序。

    我們在linux4.9內核E:\linux-4.9\linux-4.9\drivers\net\can目錄下的Makefile中看到內核支持了包括SJA1000,以及賽靈思的開發板的CAN驅動支持,我們比較關心的CAN錯誤的定義呢,在E:\linux-4.9\linux-4.9\include\uapi\linux\can中定義了所有CAN總線可能上報給用戶層的錯誤信息具體的關係圖如下:

    

三個能展開的三級目錄分別如下:

   

     這其中我們舉個例子來說明這個僞造的錯誤幀是如何產生的,以AT91的驅動爲例,下面的描述均來自內核源碼。首先在設備的Open函數處註冊了中斷處理函數at91_irq,函數在發生終端時候,判斷中斷類型爲錯誤中斷,調用at91_irq_err處理設備錯誤信息,細分中斷源來定義當前新狀態爲bus-off、報警、主動錯誤狀態還是被動錯誤狀態,如果狀態發生了變化,則調用at91_irq_err_state形成錯誤幀進行上報。假如這個時候如果原狀態爲主動錯誤,而新的狀態爲RX/TX錯誤計數達到報警狀態,則會更新設備當前狀態,並向上層監聽端口的用戶程序發送一個表示控制器錯誤-->RX/TX錯誤計數達到報警狀態的錯誤幀。用戶程序就可以知道CAN總線發生了這樣的錯誤,並檢查干擾源。

2.STM32F10x bxCAN

    工業現場的總線上一般有兩種設備,一種爲普通的can節點設備,他們在整條總線上按需分佈,反饋一些即時的信息(傳感器信息或者摁鍵等),另一種設備一般一根CAN總線上就一臺這樣的設備,它負責將CAN總線上的數據轉發到以太網接口,WIFI,或者zigbee等通信接口,或者它本身帶有屏幕,顯示各個節點上報的信息並進行統一的控制。這種類似‘網關’的設備一般會上嵌入式實時操作系統,或者linux內核裁剪一下拿QT做做界面,或者直接就安卓了。

    反觀線上多數的設備,一般爲了壓低成本等原因,會採用STM32來進行開發,而總線上的狀態,往往是這些處於總線遠端的設備能更好的體現,並且出問題的設備也大概率會是這些設備,但是這些設備往往沒有實時操作系統,業務開發起來比較緩慢且不易多人維護,導致往往對於異常的處理不足,關注實現往往大於功能實現的效率以及質量。而其更沒有Linux比較完善的官方驅動支持,如上文一樣可以給用戶程序主動報一些總線上的錯誤。所以,基於STM32開發CAN的時候,更應該借鑑Linux的驅動實現方式,對總線上的錯誤進行記錄,方便查詢。

    我們首先來分析一下STM32 bxCAN的錯誤中斷源:

    

    由上圖可知,ERRIE爲錯誤中斷的總使能位,EWGIE爲錯誤警告中斷使能,當接收/發送的錯誤數到達報警標準之後觸發此中斷,EPVIE爲錯誤被動中斷使能,當接收/發送的錯誤數到達被動錯誤標準時觸發此中斷,BOFIE爲離線中斷使能,接收/發送的錯誤數到達離線標準時觸發此錯誤,LECIE爲上次錯誤號中斷使能,當接收/發送出現錯誤的時候,且與上次錯誤不同,觸發此中斷,錯誤號根據手冊能表示一下錯誤:000: No Error,001: Stuff Error,010: Form Error,011: Acknowledgment Error,100: Bit recessive Error,101: Bit dominant Error,110: CRC Error,111: Set by software。

    在發送過程,bxCan有三個發送mailbox,STM32的庫函數CAN_Transmit負責將數據放到mailbox中並觸發發送(若沒有空閒的mailbox則返回錯誤),由手冊可知,可根據TME來判斷mailbox是否可能,庫函數CAN_TransmitStatus封裝好能夠直接獲得當前mailbox的狀態,這裏建議對CAN控制器的CAN_NART配置爲DISABLE,使能報文重傳功能,這樣報文如果發送失敗,將在SCHEDULED和TRANSMIT兩個狀態切換,直到發送完畢,纔會釋放郵箱。除非你的應用需要報文發送的準確時間點進行記錄,並且你的應用實時性要求也不高,能夠騰出時間去處理報文重傳(如果你把CAN控制器的報文重傳功能去掉了,那你必然要自己實現)。從這個流程中可以看出,我們可以將發送溢出(郵箱佔滿),以及發送仲裁丟失作爲控制器的錯誤記錄下來。

    在接收過程中,就有接收溢出的中斷可供記錄接收溢出錯誤。

    綜上所述,STM32F10x bxCAN提供的寄存器能夠滿足類似Linux的除了收發器其餘的所有錯誤記錄,通過庫函數能夠很方便的將CAN控制器的狀態變化以及總線上的錯誤記錄下來,從而可以分析現場CAN總線的狀態。

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章