在嵌入式開發人員看來,在Arm Cortex-M微控制器上調試最糟糕、最煩人的故障之一是硬故障。如果你幸運的話,在你犯了一些非常明顯的錯誤之后,這個硬錯誤就會出現,你可以很快地撤銷它。在這篇文章中,我們將詳細介紹用來確定原因和糾正硬故障的過程。
不精確的錯誤
當發生硬故障時,嵌入式開發人員別無選擇,只能深入微控制器,檢查故障寄存器。深入研究的第一個寄存器是可配置故障狀態寄存器(CFSR)。CFSR由三個故障寄存器組成:
l MemManage故障狀態
l 總線故障狀態
l 使用故障狀態
這些寄存器一起可以幫助我們開始理解為什么會有故障。
不幸的是,存儲在這些寄存器中的值并不總是決定性的或有用的,這取決于硬故障。例如,檢查CFSR寄存器的值時,它被設置為0x400。下面的圖1詳細說明了CFSR中各個位的含義。值0x400是一個不精確的錯誤!
不精確錯誤是一種異步錯誤,是由于優先級問題、禁用錯誤、內存訪問問題等而導致的總線錯誤。不精確故障的問題是,嵌入式開發人員不能相信其他故障寄存器包含任何關于故障原因的直接或有價值的信息!沒錯,在這一點上,你是在還原代碼或猜測和隨機嘗試不同的創可貼來嘗試和修復問題。
從不精確到精確的誤差
值得慶幸的是,當你遇到一個不精確的錯誤導致你的硬故障時,并沒有失去一切。不精確的錯誤可能是由于CPU使用內部緩沖區來緩存指令造成的。如果緩沖區被禁用,執行的每條指令都將線性執行。結果將是不精確的錯誤變成精確的錯誤,并且所有其它故障寄存器可以幫助識別故障。
禁用緩沖器的步驟非常簡單。開發人員可以通過設置ACTLR寄存器中的DISDEFWBUF來禁用寫緩沖器。執行此操作的代碼如下所示:
SCN SCB-> ACTLR | = SCN SCB _ ACTLR _ DISDEFWBUF _ Msk;
除了禁用寫緩沖器之外,確保在SHCSR寄存器中啟用使用、總線和存儲器故障也是一個好主意。嵌入式開發人員使用以下C代碼片段可以啟用這些故障:
// Enable Usage-/Bus-/Mem Faults
SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk
| SCB_SHCSR_BUSFAULTENA_Msk
| SCB_SHCSR_MEMFAULTENA_Msk;
編譯代碼,然后重新運行代碼。希望不精確的錯誤現在是一個精確的錯誤,它使我們能夠更深入地挖掘硬故障的原因。
調試精確錯誤
現在我們有了精確的誤差,我們可以檢查CFSR寄存器中的其他位。在這種情況下,唯一設置的另一位是BFARVALID位。BFARVALID位告訴我們,存儲在BFAR寄存器中的總線地址是一個有效地址,并且可以告訴我們是什么導致了我們的故障。最初,僅通過BFARVALID位置位,我們就可以推斷出總線故障導致了硬故障。
本例中,BFAR寄存器(總線故障地址寄存器)保存的值為0x100000。有意思!當總線試圖訪問地址0x100000時,為什么處理器會出錯?對微控制器存儲器映射的快速調查顯示,存儲器地址0x100000并不存在!在這種情況下,閃存從0x0到0x100000。處理器應該在拋出錯誤,但是為什么編譯器在內存空間之外生成指令?
結論
如果你沒有使用正確的流程,排除微控制器上的硬故障可能會很困難。在這篇文章中,我們看到開發人員可以使用CFSR寄存器來識別他們的硬故障的原因。在更復雜的情況下,嵌入式開發人員可能需要禁用CPU寫緩沖區來將不精確的錯誤變為精確的錯誤。一旦做到這一點,識別問題的時間就會大大縮短。希望這能幫助你快速解決你或你的團隊將來可能遇到的任何困難。