問題描述:
系統調試過程中發現硬件中斷經常得不到及時響應,根據現象推斷中斷會被延遲達150us以上。 問題分析: 中斷信號是連到CPLD的,DSP的GPIO6也與CPLD相連。用CPLD的任一個輸出腳IOX做為中斷延遲指示。中斷沿來了之后將IOX置為高電平,DSP進入中斷服務函數馬上給GPIO6一個翻轉,CPLD檢查到來自GPIO6的翻轉后將IOX清為低電平。這樣,通過觀察IOX上的信號正脈沖寬度就可以看到從中斷發生到中斷得到響應所用的時間了。而且通過脈寬觸發模式就可以設置大于150us的正脈沖觸發,這樣就能捕捉到異常情形了。通過測試發現,一般延遲只有400ns左右,但任務負載一重就會出現寬度超過150us的正脈沖,也就是中斷被延遲了150us以上才得到響應。 下圖為觀察到的IOX管腳上的波形:
開始以為是有其他中斷打斷而占用CPU。但經過實驗驗證發現這種延遲并非受中斷影響,而是和任務有關。 最終確認這種延時和某個任務中的memset()函數調用有關――這個函數對片外SDRAM中的384×100個字節進行清0操作。將這個函數注釋掉就可以明顯減小中斷延遲發生的頻率。 memset(buffer,0,lenth); 由于片內空間不足,buffer位于片外SDRAM,lenth為384×100。 于是先懷疑這個函數可能對中斷機制做了什么禁止操作,便用自己寫的for循環代替memset函數進行清0操作,看是不是會解決這個問題。后來卻發現延遲反而更長了。于是將for循環多進行幾遍,編程使for循環重復9次。 for(j=0;j<9;j++){ dst=buffer; for (len=0;len<38400;len++){ *dst++ = 0; } } 從示波器可以看到連續9個中斷響應異常:
上面的波形即可看出,中斷發生是200us周期的,超過200us的中斷延遲會致使一次中斷丟失。這幾個異常中斷響應之間(脈沖下降沿間隔)都是300us.,于是推斷一次內循環大致耗時300us。 更改次數為5,則可以見到連續5個中斷響應都被延遲300us左右。如果按133M寫速率的話,這個時間剛好是38400/133M=288us。于是懷疑為for循環內中斷一直不能得到響應。 在for循環內設置斷點觀察。發現for循環運行中,GIE有效,IER內的中斷使能有效,IFR中斷對應位也正常置1,但程序不會跳轉到中斷服務程序。直到內層的for循環結束后,才會跳轉到中斷服務程序,外層的for循環是可以打斷的。因為自身的IER仍有效,所以判斷沒有進入HWI_enter調試程序,不是DSP/BIOS的問題。應當是DSP芯片循環賦值硬件機制和中斷配合的問題。 上面的賦值語句是按字節賦值,DSP處理時每循環一次2個時鐘周期,每循環一次寫3個字節(多邏輯單元并行操作)。也許正是這種多邏輯單元并行處理機制導致的CPU不能即時響應中斷。 后來在TI的一篇文檔中找到了答案。TMS320C64x/C64x+ DSP CPU and Instruction Set Reference Guide(SPRU732H)。第534頁列出了中斷得到CPU響應需具備的條件。 · IFm is set during CPU cycle 6. (This determination is made in CPU cycle 4 by the interrupt logic.) · There is not a higher priority IFm bit set in IFR. · The corresponding bit in IER is set (IEm = 1). · GIE = 1 · NMIE = 1 · The five previous execute packets (n through n + 4) do not contain a branch (even if the branch is not taken). 其中第6條即標明,CPU響應中斷前5個執行包內,不能有跳轉指令。(execute packets指同一周期內可并行執行的指令集合——最多一周期可執行8條指令。)因為循環賦值的for循環內只有五六條匯編指令,往往在二到三個周期內即可完成一次循環,然后CPU無法中斷而繼續下一次循環。直到循環結束才開始響應中斷。而從內層的for循環到下一次循環之間則剛好多于5個執行包,所以外層的for循環可以被中斷 解決方法: 可以使用DMA操作,用DAT_fill()函數代替memset()函數。 可以將較長的for循環分解為多層for循環,以減小最內層for循環執行時間,減小對中斷的影響。內層循環結束后可以適當做一點簡單的運算來提供5周期的“空隙”。 可以用64位操作或32位操作替換8位操作,可減小賦值所需的總時間。 可以用編譯器的“-mi”編譯項來讓編譯器自動處理(后面需帶參數,具體意義和用法可參見TI的SPRU198G文檔“TMS320C6000 Programmer’s Guide”的“interrupts”一節,356頁)。 注:64x和64x+都是這樣的。
|