無論我們的調(diào)試工具變得多么復(fù)雜,老舊的printf語句總會有一席之地。printf往往是高效的,并且會極大地影響系統(tǒng)的實時性能。對于使用Arm Cortex?-M3或更高版本的嵌入式開發(fā)人員,可以將printf重新映射到Instrumentation Trace Macrocell (ITM),這不僅可以使用printf,還可以顯著提高其效率并消除任何實時性能損失。讓我們來看看如何使用ITM。
在我們深入細(xì)節(jié)之前,重要的是要注意ITM比通過UART或其他外圍設(shè)備使用我們的普通printf更快、更高效。ITM速度更快有幾個原因,例如:
它旨在通過硬件傳輸printf樣式的消息
它使用專用引腳SWO來傳輸消息
波特率基于內(nèi)部時鐘頻率,可以使其非常快
它有多個刺激端口,可以輕松分離數(shù)據(jù)和跟蹤消息
基本上,開發(fā)人員只需將一個字符放入ITM緩沖區(qū),硬件添加時間戳和相關(guān)數(shù)據(jù)并自行傳輸,無需任何額外的軟件交互。消息通過微控制器上的串行線輸出 (SWO)引腳直接傳輸?shù)秸{(diào)試器。然后調(diào)試器可以在IDE控制臺中記錄和顯示消息。
ITM包含32個獨立的激勵端口,可用于將不同的消息傳輸?shù)介_發(fā)環(huán)境,例如調(diào)試、數(shù)據(jù)和跟蹤信息。通常,端口0用于printf消息,而端口31用于RTOS事件消息。除此之外,端口1到30可用于嵌入式開發(fā)人員想要傳輸?shù)娜魏胃郊有畔ⅰ_@可能包括狀態(tài)機狀態(tài)、傳感器讀數(shù)或任何其他有助于調(diào)試系統(tǒng)的信息。每個激勵端口還可以在同一ITM消息中傳輸多達(dá)10個字節(jié)。
使用ITM傳輸 printf 消息很簡單 Arm在ITM的Arm CMSIS標(biāo)準(zhǔn)中包含了三個不同的輔助函數(shù)。這些包括:
ITM_SendChar
ITM_ReceiveChar
ITM_CheckChar
通過這些API,開發(fā)人員可以發(fā)送、接收和檢查單個字符。默認(rèn)情況下,這些API假定端口0刺激端口,這意味著如果要使用另一個端口或多個端口,開發(fā)人員將需要自己編寫這些函數(shù)。使用API很簡單。要傳輸一個字符,開發(fā)人員可以簡單地編寫:
ITM_SendChar(Character);
如果我們想傳輸單個字符,這很有幫助,但如果我們想重定向printf語句,我們需要對printf的工作方式進(jìn)行一些更改。修改將取決于所使用的開發(fā)環(huán)境和編譯器。對于使用GCC的基于Eclipse的IDE,嵌入式開發(fā)人員可以修改write函數(shù)而不是更改printf。包含printf 的nanolib庫使用具有以下原型的write函數(shù)將printf重定向到開發(fā)人員可能想要使用的任何源:
int _write(int file, char *ptr, int len);
默認(rèn)情況下通常不實現(xiàn)此功能。 正如您從原型中看到的那樣,所需要做的就是利用指向字符緩沖區(qū)的指針并使用定義緩沖區(qū)中字符數(shù)的長度。有了這些信息,開發(fā)人員可以創(chuàng)建一個使用ITM的寫入函數(shù),如下所示:
對于正在尋找一種快速有效的方法來使用printf語句的開發(fā)人員來說,ITM是一個非常寶貴的工具。 我們已經(jīng)大致了解了ITM以及一些在軟件中啟動和運行它的技巧。請注意,為了成功接收消息,嵌入式開發(fā)人員需要啟用所使用的ITM激勵端口,并且可能需要修改調(diào)試配置以用于串行線查看(SWV)以及微控制器時鐘速率。 除此之外,享受快速確定性的printf消息!