1. 程式人生 > >ARM cortex-M核心晶片的軟體定時器功能異常問題解決

ARM cortex-M核心晶片的軟體定時器功能異常問題解決

      最近一個專案中的使用了軟體定時器功能,程式執行在前後臺的系統中,使用軟體定時器建立任務處理應用。硬體上外接一個水流感測器,水流感測器輸出的是一個方波訊號,水流越快,訊號的頻率越高。CPU採用的是STM32L051的晶片,使用外部中斷接收這個方波訊號,中斷內記錄中斷時間,以此來計算出來方波的頻率,換算出來水流的速度。中斷程式中使用了一個軟體的定時器來判斷這個方波訊號沒有了時,觸發定時器超時來設定方波頻率為零。

       在測試過程中發現,測量水流感測器的方波頻率正常,但是有另外一個定時器任務在水流感測器工作時異外的被刪除了。首先查看了程式的堆疊, 發現堆疊夠用,不是堆疊小導致的程式修改了定時器的資料結構造成的。

/*水流感測器超時定時器控制代碼*/
HTMR  g_water_flow_tmr = NULL;

int main(void)
{
    /*時鐘初始化*/
    
    /*GPIO初始化, 此函式中設定的水流感測器的外部管腳中斷*/
    HAL_GPIO_Init()

    /*軟體定時器全域性變數初始化*/
    tmr_data_init();

    /*建立定時器*/
    tmr_creat(1000, TMR_LOOP, sersor_read, 0)

}
/*水流感測器中斷處理程式*/
void Water_flow_Interrupt(void)
{
    /*記錄方波訊號的時間,計算方波訊號的頻率*/
    ...
    
    tmr_delete(g_water_flow_tmr);

    g_water_flow_tmr = tmr_creat(1000, TMR_ONE, water_flow_timeout, 0);
    

}

     經過除錯發現,有水流時第一次進入水流感測器中斷處理程式中g_water_flow_tmr = 0x100, 這個控制代碼正是另外一個異外刪除的定時器的控制代碼,中斷程式中首先刪除超時定時器tmr_delete(),這裡導致了那隻定時器被意外刪除了。原因定位到是水流感測器的中斷程式引起的。但是g_water_flow_tmr為什麼是0x100,而不是預設初始化的NULL呢?經過不斷模擬除錯,在初始化GPIO時HAL_GPIO_Init()函式中初化外部中斷,開啟外部中斷後,CPU會在實際IO口未發現中斷時產生一次中斷(假中斷),中斷程式中執行tmr_creat()函式,g_water_flow_tmr被賦值為0x100,而主程式在繼續執行定時器初始化後,建立的這個定時器被消除了,後面的程式中再執行定時器建立任務時返回的控制代碼也是0x100,這時再有水流流動時,中斷程式就會刪除了0x100這個控制代碼的定時器。

       解決辦法:定時器初始化程式前移到GPIO初始化之前就可以了。

     經驗總結:所有純內部資料結構的初始化(如軟體定時器初始化),儘量放在初始化的最前面。同時一定要注意cortex-M3,cortex-M0這些核心的晶片在使能中斷時都會產生一次假中斷(CHIP BUG),對你設計的程式邏輯產生的影響。