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