MCUXpresso Using of printf

另一篇參考文檔:https://community.nxp.com/docs/DOC-334074

MCUXpresso幫助文檔中的“Using of printf”

默認情況下,藉由semihost機制,printf()和puts()的輸出會顯示在debugger console上。
要想讓printf()這樣工作,就必須在鏈接過程中把一個"semihost"或“semihost-nf”變種庫鏈接到程序中。
注意:如果只要顯示固定字符串,則使用puts()即可,它比printf()節約很多代碼空間。

Redlib printf變種

Redlib提供如下兩種printf變種。在創建新工程時,MCUXpresso新工程嚮導會提供選項,允許你從這兩種中選擇其中一種。

字符 VS 字符串輸出
默認情況下,printf()和puts()會立即輸出生成的字符串,這樣,單獨一次semihost操作就可以把字符串輸出到debugger console。注意:這種printf()/ puts()使用malloc在堆中創建一個臨時緩衝區來生成字符串。
另一個版本是“按字符依次發送”,它不需要堆空間。這種版本需要在工程中宏定義"CR_PRINTF_CHAR"。如果你要把printf()重定向到UART(下面詳述),這種方法就特別有用,因爲在使用UART時沒必要創建一個緩衝區來儲存整個字符串,只要每次向UART輸出一個字符即可。

只打印整數 VS 打印全部類型數字(包括浮點數)
Redlib中的printf()比Newlib中的小的多。因此,如果很在意代碼尺寸,就儘量嘗試使用Redlib。另外,如果你的應用不打印浮點數,就可以選擇一個“僅整數”(不兼容浮點)變種的printf。這又能減少代碼尺寸。
要使能Redlib中的“僅整數”printf,須在工程中宏定義“CR_INTEGER_PRINTF”。在使用SDK新工程嚮導時,這是默認定義的。

NewlibNano printf變種

默認情況下,NewlibNano變種僅支持整數的printf和scanf,從而減少代碼尺寸。
如果確實需要支持浮點數,則需:
工程屬性——C/C++ Build——Settings——MCU Linker——Managed Linker Script,勾選“Enable printf / scanf float”。

Newlib printf變種

Newlib提供了一個“iprintf”函數來實現“僅整形”printf。

使用LPCOpen時的printf

使用SDK時的printf

MCUXpresso SDK代碼倉庫通過宏PRINTF提供它自己的printf功能。PRINTF宏在fsl_debug_console.h中定義,它既可以指向C庫中的printf函數,也可以指向SDK中的僞printf函數DbgConsole_Printf()。典型地,這【指向DbgConsole_Printf()】會通過一個UART(它可能連接到板上的調試probe,從而通過USB VCOM通道回傳給host)來發送。通過宏SDK_DEBUGCONSOLE來控制:
  如果SDK_DEBUGCONSOLE == 0
    PRINTF定向到C庫中的printf()
  如果SDK_DEBUGCONSOLE == 1
    PRINTF定向到SDK的DbgConsole_Printf()
SDK新工程嚮導,以及導入SDK樣例嚮導時,在Advanced頁面中,提供配置選項來控制SDK_DEBUGCONSOLE的值。

另外,如果PRINTF被定向到C庫printf(),並且也定義了SDK_DEBUGCONSOLE_UART,則printf依然定向到UART。同樣的,在SDK新工程嚮導以及導入SDK樣例嚮導的Advanced頁面中,提供了配置選項來控制這一點。

重定向printf/scanf

默認情況下,藉由semihost機制,printf()把文本輸出到debug console上。
有時這種輸出機制不符合你的應用需求,你希望通過一個通信通道(UART,或者Cortex-M3/M4上的ITM SWO Trace)來輸出。這時,你可以重定向底層庫的某些部分來達到目的。
下面的“如何使用ITM Printf”展示了一個例子。
注意:重定向這些函數時,一般在鏈接時要選擇C庫的“nohost”變種,而非“semihost”變種。

Redlib
要重定向Redlib的printf(),需要你自己來完善__sys_write()函數:
int __sys_write(int iFileHandle, char *pcBuffer, int iLength)
成功時返回0,失敗時返回未發送的字節數。

類似地,如果要重定向scanf(),需要你自己來完善__sys_readc():
int __sys_readc(void)
函數返回讀到的字符。

注意:這2個函數直接有效地映射到底層的“semihost”操作。【啥意思?沒懂】

Newlib / NewlibNano
要重定向printf(),需要你自己來完善_write()函數:
int _write(int iFileHandle, char *pcBuffer, int iLength)
成功時返回0,失敗時返回未發送的字節數。

要重定向scanf(),需要你自己來完善_read():
int read(int iFileHandle, char *pcBuffer, int iLength)
函數返回讀到的字符數,讀到的字符保存在pcBuffer裏。
更多Newlib系統調用信息,參見https://sourceware.org/newlib/libc.html#Syscalls

如何使用ITM Printf

ITM Printf是一種通過debug probe訪問應用IO的機制,不使用semihosting。

ITM概覽

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章