之前的文章在講到調(diào)試的時候,一般都是大家熟悉的調(diào)試方法:通過打斷點,讓程序運行到某一個地方停下來,查看某些變量、寄存器等的狀態(tài);單步運行,看程序的執(zhí)行、跳轉(zhuǎn)是否跟預期一致;比較高級的是設置軟斷點,比如在讀寫某一個變量,或是某一變量值到達某種狀態(tài)時停下。這些方法有一個共同的特征,就是程序要停下來,讓我們觀察各種信息。
有沒有一種方法,程序在持續(xù)的運行,某些變量的值能夠持續(xù)的輸出給我們,甚至是通過圖表的形式給我們觀察,甚至是后期保存下來。這樣在某些情況下是更直觀的、更有效的一種調(diào)試方法。
這種方法當然是存在的,比如通常會利用單片機的某一個串口向外發(fā)送數(shù)據(jù),再通過上位機串口調(diào)試軟件接收并顯示。除此之外,還有另一種方法,通過STM32系列單片機的SWV(Serial Wire Viewer)實時跟蹤技術來實現(xiàn)。
接下來我們通過一個簡單的例子,看看在CubeIDE下怎么通過單片機的SWV功能結合CubeIDE的ITM(Instrumentation Trace Macrocell)功能實現(xiàn)參數(shù)的實時跟蹤。需要說明的是,下面關于SWV實時跟蹤的功能介紹來源于CubeIDE的用戶手冊,覺得自己英文水平還行的可以直接去看手冊,更權威。
1. 端口配置
我們還是基于正點原子的F767開發(fā)板,在CubeMX里新建一個工程,具體設置見下圖。默認的Debug模式為JTAG,這里我們改為Trace Asynchronous Sw,調(diào)試模式改為SWD。這個時候PB3就會被使能,它的一個復用功能是SWO(Serial Wire Output),這個引腳配合SWD輸出實時跟蹤數(shù)據(jù),也即實現(xiàn)了SWV功能。
2. 調(diào)試配置
用CubeIDE打開生成的工程,點擊菜單Run->Debug Configurations,新建一個調(diào)試配置文件,在調(diào)試器標簽頁里,接口選SWD,使能SWV,Core Clock處填內(nèi)核實際運行頻率,這里是216 MHz。
接下來,連接開發(fā)板,進入調(diào)試模式。點擊菜單Window->Show View->SWV->SWV Trace Log,會在窗口下方打開SWV Trace Log標簽,如下圖。點擊Configure Trace圖標進行配置。
在配置窗口里我們使能PC Sampling,對內(nèi)核PC(Program Counter)值進行采樣,分辨率16384 Cycles/sample的含義是每次采樣間隔16384個時鐘周期。這個值是默認的,考慮到SWO端口異步工作頻率為2 MHz,這個分辨率不能太小,否則數(shù)據(jù)量太大會造成堵塞。Timestamps必須被使能,好知道有事件發(fā)生了。后邊的預分頻值同樣與SWO數(shù)據(jù)量大小有關。
點擊SWV Trace Log標簽頁右方的Start Trace圖標,見下圖,并啟動調(diào)試,則會看到SWV Trace Log標簽頁會持續(xù)輸出PC Sample數(shù)據(jù)。
當然,除了輸出PC Sample數(shù)據(jù)之外,還可以配置輸出Configure Trace窗口里的各種事件發(fā)生的情況,也可以輸出某些變量值,甚至是把輸出的變量以圖表的形式輸出。具體配置方法可參考用戶手冊去研究。
3. 代碼利用printf重定向輸出消息
我們知道printf是C語言標準庫的函數(shù),可以向屏幕打印字符串,嵌入式里一般被重定向到串口。在利用SWV進行調(diào)試時,我們可以把printf重定向到ITM的0通道,調(diào)試時,用戶代碼可以利用printf向外發(fā)送易讀的消息。
首先,Configure Trace里勾選0通道,見下圖。然后點擊CubeIDE菜單Window->Show View->SWV->SWV ITM Data Console,窗口下方會出現(xiàn)SWV ITM Data Console標簽頁,可以顯示ITM各通道輸出的信息。
接下來修改代碼,打開工程文件夾->Src->syscall.c文件,這個源文件里的函數(shù)配合C庫實現(xiàn)系統(tǒng)調(diào)用。找到_write函數(shù),完成printf到ITM的重定向。修改如下:
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
//__io_putchar(*ptr++);
ITM_SendChar(*ptr++);
}
return len;
}
當然,把注釋掉的那一行修改成串口發(fā)送的話,就能把printf重定向到串口。
在main.c的while循環(huán)里添加如下代碼:
while (1)
{
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
printf("LED0 is offn");
HAL_Delay(500);
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
printf("LED0 is onn");
printf("%dn",counter++);
}
重新編譯,進入調(diào)試模式,則可以在SWV ITM Data Console標簽頁里看到如下打印信息。
4. 小結
基于STM32Cube生態(tài)的SWV實時跟蹤調(diào)試方法就介紹到這里。需要說明的是,此方法在硬件上需要留出SWD接口和SWO引腳,正點原子STM32F767核心板上的SWD接口沒有引出SWO引腳,所以連接核心板的SWD無法用到SWV功能,需要通過ST-Link連接底板上的20針JTAG接口實現(xiàn)。
-
寄存器
+關注
關注
31文章
5363瀏覽量
121021 -
STM32
+關注
關注
2271文章
10923瀏覽量
357257 -
C語言
+關注
關注
180文章
7614瀏覽量
137522 -
STM32單片機
+關注
關注
59文章
549瀏覽量
58788 -
SWD
+關注
關注
1文章
57瀏覽量
11891
發(fā)布評論請先 登錄
相關推薦
評論