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