都是Semaphore惹得禍

NPCPU發包,CPU通過中斷的方式接收。HTFD High的中斷正常,可以調用ISR用來give相應的信號量,Main_TFDH可以take到信號量;HTFD Low的中斷也正常,也可正常give信號量,但是Main_TFDL卻不能take信號量。調試步驟如下:

1. 利用EZmdeHTFD Low隊列發包到CPU,終端顯示:

AHE_Isr --- Channel=0    cause reg bit 2 is set
                uqCauseReg=0x00000004    HTFD Low
                send semaphore to Main_TFDL

由此可見,中斷確實發生了,但是相應的中斷處理任務(Main_TFDL)並沒有執行。

 

2. 在終端上查看當前系統中的任務狀態:

-> i

NAME        ENTRY       TID    PRI   STATUS      PC       SP     ERRNO DELAY
---------- ------------   -------- ---     ----------    -------- --------   -------       -----
……           ……           ……    …     ……           ……    ……       ……       ……
TFDH_0     Main_TFDH_0   43e6ae0 145 PEND         a25f74 43e6960       0     0
TFDL_0     Main_TFDL_0   43e0860 150 PEND         a25f74 43e06d0       0     0
FPGA_FIFO_Dnp_load_FPGA 43af7d0 150 READY        23df90 43af6e8 3d0001     0
……           ……           ……    …     ……           ……    ……       ……       ……

value = 0 = 0x0

3.查看中斷處理任務Main_TFDL的函數調用堆棧:

-> tt 0x43e0860
989800 vxTaskEntry    +54 : Main_TFDL ()
823584 Main_TFDL      +74 : semTake ()
a26a50 semTake        +130: a25df8 ()
value = 0 = 0x0

 

終端處理任務也是正常的。無意間發現FPGA FIFO 溢出檢測任務的狀態似乎有點不正常,這個任務跟中斷處理任務一樣,也是需要take相應的信號量才能作相應處理,按理說它的狀態也應該是PEND纔對,但是此處卻是READY

 

4. 查看FPGA FIFO 溢出檢測任務的函數調用堆棧:

-> tt 0x43af7d0
989800 vxTaskEntry    +54 : np_load_FPGA_standby ()
828558 np_load_FPGA_standby+90 : FPGA_check_fifo_overflow ()
242788 FPGA_check_fifo_overflow+20 : BspNPCheckBoard ()
value = 0 = 0x0
-> Main_TFDL -- channel 0 HTFD Low interrupt happen!

HTFD Low Msg queue is empty

 

奇怪的事發生了,tt FPGA FIFO 溢出檢測任務後,剛剛沒有執行的Main_TFDL現在卻得到了執行。NP通過HTFD Low隊列向CPU發包,CPU產生中斷give信號量,但是Main_TFDL卻不能take,但只要一執行

        tt 0x43af7d0 (FPGA FIFO 溢出檢測任務)

Main_TFDL就會take到信號量。嘗試了好多次,都是這樣的結果。

 

5.在代碼中去掉FPGA檢測任務,重新編譯版本,啓動後,再從NPCPU發包。這次中斷果然正常了:

AHE_Isr --- Channel=0    cause reg bit 2 is set
                uqCauseReg=0x00000004    HTFD Low
                send semphomore to Main_TFDL

Main_TFDL -- channel 0 HTFD Low interrupt happen!

HTFD Low Msg queue is empty

從以上幾步診斷結果來看,問題應該出在FPGA FIFO 溢出檢測任務上,但是實在想不通FPGA檢測任務怎麼會影響到HTFD Low中斷處理任務!這兩個任務沒有共享全局變量,也沒有任何進程間通信。

查閱了VxWorks的相關資料,得知ready狀態表示任務除了等待CPU外不等待其它資源,執行i命令時此任務是ready狀態,那麼這個任務有可能平時一直處於無限循環中。

對比了一下創建FPGA FIFO 溢出檢測任務和創建HTFD Low中斷處理任務的語句,如下:

EZ_TSK_SPAWN( "FPGA_FIFO_DAEMON",
                          NORMAL_PRIORITY_TSK_DEF1/*BELOW_NORMAL_PR_TSK_DEF1*/,
                          ISR_TSK_STK_SIZE_DEF,
                          (EZ_FUNCPTR ) np_load_FPGA_standby,/*lint !e64 */
                           0 );
g_EZisrTaskId[i][1] = EZ_TSK_SPAWN(NP_EZIsrTFDL_Name[i],
                                           NORMAL_PRIORITY_TSK_DEF1,
                                           ISR_TSK_STK_SIZE_DEF,
                                           (EZ_FUNCPTR)NP_EZIsrTFDL_Entry[i],
                                           0);

發現這兩個任務處於同一優先級上(NORMAL_PRIORITY_TSK_DEF1)。會不會是FPGA_FIFO_DAEMON 任務中某個地方出錯導致了無限循環,而使得處於同一優先級上的HTFD Low中斷處理任務得不到執行呢?抱着這個猜想,我把FPGA_FIFO_DAEMON任務的優先級調低(BELOW_NORMAL_PR_TSK_DEF1),如果猜想正確的話,即使FPGA_FIFO_DAEMON任務一直佔着CPU進行無限循環,一旦發生HTFD Low中斷,高優先級的中斷處理任務還是會搶佔CPU從而得以執行的。

修改了FPGA_FIFO_DAEMON任務的優先級後,重編版本,下載運行後,果然驗證了剛纔的猜測。此時只要產生硬件HTFD Low中斷,HTFD Low的中斷處理任務便立刻被執行。

現在問題已經明朗,問題肯定出在FPGA_FIFO_DAEMON任務中。此任務的入口函數框架如下:

void np_load_FPGA_standby()
{
    ……
    while(TRUE)
    {
        /*每200ms對FPGA的狀態進行一次檢測*/
        EZ_SEM_TAKE(g_EZPhiId.EZFpgaFifoSem);
       
        /*檢查FPGA的FIFO是否溢出*/
        fpga_fifo_state = FPGA_check_fifo_overflow();

        if( fpga_fifo_state && bFPGALoadFlg )
        {
            ……
        }
        ……
    }    
}

按理說此任務不應該一直在循環呀,它需要獲得g_EZPhiId.EZFpgaFifoSem這個信號量纔可以循環一次,而這個信號量是由時鐘中斷定時give的。再次檢查了時鐘中斷處理函數,感覺並沒有地方出錯。請教單位的某老鳥,他問我此信號量有沒有初始化,一句話驚醒了夢中人!這個信號在以前的版本是中沒有的,是我後加入到v3.5中的,當時只在時鐘中斷函數中give了一下,在FPGA_FIFO_DAEMON任務中take了一下,還真忘了在NP_Sem_Create()中初始化此信號量。折騰了一天,原來問題出在這,還真有點讓人出乎意料。

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