另一篇参考文档: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概览
略