招聘網(wǎng)站開(kāi)發(fā)不受限制的搜索瀏覽器
項(xiàng)目場(chǎng)景:
USB Audio芯片,代碼放到qspi flash中,執(zhí)行代碼時(shí),客戶(hù)會(huì)偶爾保存一些參數(shù),即FPGA驗(yàn)證過(guò)程中,每隔10ms向flash info區(qū)燒寫(xiě)4個(gè)byte(取指過(guò)程一直存在,且時(shí)隙軟件不可控),同時(shí)芯片同時(shí)打開(kāi)錄音功能,以及DAC播放功能、以及打開(kāi)系統(tǒng)中其他中斷模塊(程序會(huì)被頻繁打斷)。
問(wèn)題描述
?首次問(wèn)題為:通過(guò)電腦端點(diǎn)擊錄音和播放切換按鈕,發(fā)現(xiàn)偶爾會(huì)卡死,概率性的問(wèn)題,運(yùn)氣好幾十次會(huì)復(fù)現(xiàn),運(yùn)氣不好幾百次才卡死。
原因分析:
==》
首先,軟件根據(jù)卡死時(shí)的pc dump出來(lái)所有通用寄存器,分析出來(lái)卡死的具體位置,并將現(xiàn)場(chǎng)打印出來(lái),通過(guò)對(duì)比現(xiàn)場(chǎng)與dump的指令,發(fā)現(xiàn)卡死時(shí)從flash取到的幾個(gè)指令錯(cuò)誤,導(dǎo)致CPU跑飛了。
==》
根據(jù)此現(xiàn)象,做進(jìn)一步分析:通過(guò)示波器測(cè)量了DCO的頻率,發(fā)現(xiàn)調(diào)節(jié)DCO頻率時(shí)導(dǎo)致FPGA主頻超頻,這種情況下我們基本上認(rèn)為取指錯(cuò)誤是超頻導(dǎo)致的。后來(lái)也發(fā)現(xiàn)每次軟件進(jìn)入調(diào)節(jié)DCO函數(shù)時(shí)就會(huì)死掉,那么基本上認(rèn)為就是這個(gè)原因了。因此,我們把調(diào)節(jié)DCO控制字關(guān)閉掉,簡(jiǎn)化測(cè)試環(huán)境,始終讓DCO工作在一個(gè)穩(wěn)定的時(shí)鐘頻率下再次進(jìn)行壓力測(cè)試。
==》
進(jìn)一步做壓力測(cè)試:發(fā)現(xiàn)還是偶爾會(huì)卡死,只是概率更低了,基本上都是幾百次才死一次。同樣根據(jù)現(xiàn)場(chǎng)與dump進(jìn)行指令比對(duì),發(fā)現(xiàn)卡死的時(shí)候還是有取指錯(cuò)誤。那么我們把cache關(guān)掉,再次取flash發(fā)生錯(cuò)誤的這個(gè)地址,這次取的是正確的指令。這說(shuō)明前面有一次取指錯(cuò)誤被cache住了,而且可以排除cache的問(wèn)題,因?yàn)閱尾秸{(diào)試再次取錯(cuò)誤地址時(shí)指令是正確的。
==》
進(jìn)一步分析:現(xiàn)在基本上確定是flash這邊的問(wèn)題,那么根據(jù)case,我們發(fā)現(xiàn)這個(gè)時(shí)候?qū)?yīng)著xip讀flash且同時(shí)進(jìn)行program操作,即對(duì)于flash來(lái)說(shuō),會(huì)有suspend和resume操作。把問(wèn)題集中到這個(gè)點(diǎn)上進(jìn)一步分析:
==》
從多次復(fù)現(xiàn)的現(xiàn)象上看,基本上死的時(shí)刻都發(fā)生在開(kāi)始program時(shí)刻,即cs_n拉高,然后大概50us的時(shí)候CPU來(lái)了xip 讀操作。然后我們結(jié)合datasheet給的suspend時(shí)間以及軟件單測(cè)program 4個(gè)byte的時(shí)候進(jìn)行分析,發(fā)現(xiàn)可能是因?yàn)閒lash內(nèi)部還沒(méi)有真正接收suspend掛起命令,就來(lái)了xip 讀操作了導(dǎo)致的。
==》
因此,我們查看datasheet,發(fā)現(xiàn)里面有要求,再發(fā)起suspend命令前,一定要輪詢(xún)flash的狀態(tài)寄存器busy以及suspend bit,然后滿(mǎn)足特定條件時(shí)才能發(fā)起suspend命令(0x75),而我們的硬件qspi controller設(shè)計(jì)并沒(méi)有完全按照這個(gè)要求來(lái),而是選擇了一個(gè)等待時(shí)間的方式,認(rèn)為cs_n拉高后,滿(mǎn)足datasheet給的時(shí)間后,一定會(huì)出現(xiàn)busy/suspend滿(mǎn)足要求,但是實(shí)際芯片測(cè)試不一定是這樣的,按照IP vendor給的建議,最后是直接輪詢(xún)內(nèi)部的狀態(tài)寄存器。
==》
考慮到目前我們的芯片已經(jīng)tap out,硬件暫時(shí)沒(méi)有改的機(jī)會(huì),目前通過(guò)軟件來(lái)繞:
軟件在發(fā)起program后,關(guān)閉中斷70us,這個(gè)關(guān)中斷時(shí)間保證了此期間沒(méi)有xip 讀操作,即這個(gè)時(shí)間差不多program也完成了4個(gè)byte的燒寫(xiě),因此就不會(huì)真正出現(xiàn)suspend的操作了。后來(lái)我們用這種方式繼續(xù)進(jìn)行壓力測(cè)試,發(fā)現(xiàn)了跑著跑著usb的in包數(shù)據(jù)突然沒(méi)有了,初步懷疑是關(guān)這70us的中斷導(dǎo)致CPU丟了usb的中斷,導(dǎo)致軟件沒(méi)有及時(shí)填tx fifo,導(dǎo)致斷音。因此,我們把場(chǎng)景降到FS模式,這樣1ms處理一次usb 中斷,理論上來(lái)說(shuō)發(fā)生斷音的概率幾乎沒(méi)有,但是事實(shí)上還是有,因此我們分析可能并不是關(guān)中斷導(dǎo)致的斷音。
==》
進(jìn)一步分析:
因?yàn)橹伴_(kāi)的usb FIFO為雙buffer,乒乓填數(shù)據(jù),現(xiàn)在為了簡(jiǎn)化case,改成單buffer結(jié)構(gòu),這樣故障概率會(huì)加大,另外軟件把a(bǔ)hb的頻率降低,排除timing問(wèn)題。根據(jù)此配置繼續(xù)debug發(fā)現(xiàn)仍然有問(wèn)題。
==》
進(jìn)一步分析:通過(guò)FPGA抓取一些內(nèi)部信號(hào)分析,考慮到FPGA資源有限,關(guān)鍵點(diǎn)需要找到適合的trigger,我們先將問(wèn)題定位到中斷上,因此先抓一下原始中斷、CPU中斷口,中斷使能分析一下。這個(gè)時(shí)候我們發(fā)現(xiàn)確實(shí)原始中斷沒(méi)有起來(lái),因此,我們懷疑可能是host端沒(méi)有發(fā)送數(shù)據(jù)請(qǐng)求,因此我們更進(jìn)一步簡(jiǎn)化驗(yàn)證平臺(tái)的環(huán)境,想到了目前芯片接到hub,由hub接到CPU的USB口,因此,我們把hub拿掉,直接將芯片接到電腦的USB口,再去試試。
這樣我們壓力測(cè)試了一天一夜,沒(méi)有發(fā)現(xiàn)問(wèn)題,說(shuō)明之前導(dǎo)致的問(wèn)題就是因?yàn)閔ub上可能接的東西太多了,導(dǎo)致傳輸不穩(wěn)定導(dǎo)致的。
==》
為了double check,我們?cè)赗TL級(jí)別修改了一些qspi控制器,完全完整datasheet要求,在發(fā)suspend及resume之前,先去讀busy和suspend狀態(tài)寄存器。再次進(jìn)行壓力測(cè)試,沒(méi)有發(fā)現(xiàn)問(wèn)題。
說(shuō)明以上問(wèn)題就是因?yàn)樵O(shè)計(jì)不魯棒導(dǎo)致的。
解決方案:
1. 目前針對(duì)已經(jīng)tap out的芯片,我們利用軟件繞的方式來(lái)規(guī)避這個(gè)問(wèn)題。
2. 針對(duì)后續(xù)項(xiàng)目,將采樣fix bug后的controller設(shè)計(jì)