問題現(xiàn)象
客戶使用 STM32H750VBT6,通過 QSPI 外擴(kuò)了一個(gè) 4M 的 NOR FLASH,采用memory map 模式。當(dāng)程序跳轉(zhuǎn)運(yùn)行到外設(shè) FLASH 后,大約兩個(gè)小時(shí)后程序死機(jī)??蛻羰褂玫?IDE 是 KEIL,此問題可以固定重現(xiàn)。 在 KEIL 調(diào)試模式下重現(xiàn)問題時(shí),通過多次觀察發(fā)現(xiàn),程序死的位置總體上會(huì)停在兩個(gè)位置,并不是同一個(gè)位置。一個(gè)是 TIM15函數(shù)的入口;另一個(gè)是進(jìn)入中斷函數(shù)后的一個(gè)賦值語(yǔ)句。
問題分析及測(cè)試
通過拜訪客戶,觀察到死機(jī)位置處于即將進(jìn)入 TIM15 中斷入口處,但還未進(jìn)入之時(shí)。查看客戶的原理圖,發(fā)現(xiàn)兩個(gè) VCAP 并未從外部相連,于是要求客戶直接從外部將此兩個(gè)引腳飛線短連。 但是,后來經(jīng)測(cè)試問題仍然重現(xiàn)。
又觀察到 PC13 連接為 GPIO 輸出引腳,用于驅(qū)動(dòng)一外部組件。 考慮到備份域相關(guān)的一些引腳其驅(qū)動(dòng)能力相對(duì)弱一些,于是讓客戶將 PC13 引腳斷開后再測(cè)試,結(jié)果問題仍然重現(xiàn)。
上面是一些硬件相關(guān)的懷疑點(diǎn),經(jīng)測(cè)試結(jié)果來看,與此問題無關(guān)。 看來主要可能還是軟件方面的問題。
在軟件上確定客戶已經(jīng)打開了 IO 補(bǔ)償功能,但 IO 速度設(shè)置的是 HIGH,于是讓客戶修改成 “VERY_HIGH”,經(jīng)測(cè)試問題仍然存在。
由于之前發(fā)生過一個(gè)從低功耗喚醒后死機(jī)的問題,是與 Cache 相關(guān)的問題,于是要測(cè)試下將 CACHE 關(guān)閉的情況。 這次經(jīng)測(cè)試客戶反饋問題沒現(xiàn)重現(xiàn) ! 但客戶同時(shí)也反饋,之前的代碼也存在稍微修改一處代碼,問題就不再重現(xiàn)的現(xiàn)象,沒有找到具體規(guī)律。 這次代碼修改也沒排除這種可能性。
為了讓關(guān)閉 Cache 的方法更具效力,于是讓客戶在調(diào)試模式下通過手動(dòng)關(guān)閉 CACHE的方式,代碼仍然保持為原先可以重現(xiàn)問題的代碼。
后記
有些人可能會(huì)問,NOR FLASH 的最后一個(gè)字節(jié) CPU 真的會(huì)去訪問嗎 ? 客戶的程序占滿了整個(gè) FLASH 空間了嗎 ? 若那個(gè)地址沒有代碼那還會(huì)不會(huì)有這個(gè)問題。
其實(shí)勘誤手冊(cè) 2.4.4 節(jié)也提到了,不管 FSIZE 定義的空間最后的一個(gè)字節(jié)內(nèi)容是什么,均會(huì)有此問題。 那么 CPU 為什么會(huì)去訪問此地址呢 ? 其實(shí)這是 M7 內(nèi)核的指令預(yù)取和分支預(yù)測(cè)的特性導(dǎo)致的。