如果使用過EFM32的CMSIS庫,那麼肯定也看到過EFM_ASSERT這個宏,幾乎無處不在。
1. 這個宏定義在哪裡,函數原型是什麼?
這個通過goto 函數定義,應該很容易找到EFM_ASSERT是一個空函數或則是assertEFM()函數。由另外一個宏定義來決定。
2.assertEFM()函數中的const char *file, int line這兩個參數是何作用?
通過這兩個參數,可以讓客戶知道是哪個檔案的,那一行的EFM_ASSERT造成的錯誤。
3. 為什麼需要EFM_ASSERT?
它能夠檢查括弧裡面的運算式是否成立,如果為false,程式會報告錯誤,並且終止執行,防止造成錯誤的結果。如果為true,則繼續執行。後續我們會舉例說明。
4. 什麼時候需要開啟這樣的功能?
ASSERT功能最大的好處是在前期進行軟體調試的時候,協助使用者找出一些潛在的bug。但是在後期Release時,一定記得要關掉。
5. 如何開始ASSERT以及關閉ASSERT功能?
通過在IDE中預定義DEBUG_EFM宏來開啟ASSERT功能。取消預定義,則關閉該功能。
以下,舉個具體的例子。目前有如下的一段代碼,開啟Assert功能之後,看看會發生什麼事情:
int main(void)
{
CHIP_Init();
CMU_ClockEnable(cmuClock_GPIO,true);
CMU_HFRCOBandSet(cmuHFRCOBand_1MHz);
//EFM32的GPIO口沒有第17pin,看能否檢測的出來
GPIO_PinModeSet(gpioPortD,17,gpioModePushPull,0);
while(1)
{
unsigned long ulDelay=500000;
while(ulDelay--);
GPIO_PinOutToggle(gpioPortD,7);
}
}
這是一段很簡單的LED閃爍的代碼,但是在GPIO_PinModeSet()函數中送錯了參數。下載這段代碼之後,全速運行,發現程式卡在了assert_EFM() 函數裡面:
然後開啟IAR -> View -> Locals視窗,就可以看到是那個檔案的第幾行的EFM_ASSERT檢測false造成的。這裡是c:\Assert test\emlib\src\em_gpio.c,第200行。
從這裡就知道是調用GPIO_PinModeSet()裡面的參數有問題。EFM32的GPIO口沒有第17pin的。問題就這樣就找出來了。
使用EFM_ASSERT注意事項:
1. 如果要看到File以及Line的內容,必須要設定代碼最佳化等級為None,否則這兩個參數直接就被最佳化掉了。
2. 後期一定要關掉此功能。
3.如果路徑名太長,則會顯示不全。把工程換個短點的路徑即可。後面都是...了,看不到啊。
最後還有一個小技巧:
其實還有一個更簡單的方法找到,是哪裡的EFM_ASSERT函數出錯造成的。
當程式卡在assertEFM之後,IAR -> View -> Call Stack, 在Call Stack視窗,你可以看到整個函數的調用關係。而且你還可以試試雙擊那些個函數,怎麼樣,跳過去了吧。這樣省事了了吧! 而且不怕最佳化等級,呵呵。
這個小技巧,算是給看完這篇文章的人一個小小的獎勵吧。
在keil中,進入dedug狀態之後,可以通過View -> Call Stack + locals來查詢到底是哪裡除了問題。通過如下視窗顯示的資訊,就能推斷出是main函數裡面,調用了GPIO_PinModeSet函數,如果main函數中調用了多次的GPIO_PinModeSet函數,則可以通過查詢GPIO_PinModeSet函數的參數來判斷具體的位置。這裡可以看到port參數是gpioPortD,pin參數是0x12,即18等資訊。
但是遺憾的是,不像IAR,雙擊函數就跳過去了。。