AnsweredAssumed Answered

Using printf()

Question asked by LPCware Support on Mar 31, 2016

Printf and semihosting

 

By default, the output from printf() (and puts()) will be displayed in the debugger console via the semihosting mechanism. This provides a very easy way of getting basic status information out from your application running on your target.

 

For printf() to work like this, you must ensure that you are linking with a "semihost" library variant.

 

Redlib printf variants

 

Redlib provides the following two variants of printf. Some of the LPCXpresso project wizards provide options to select which of these to use when you create a new project.

 

Character vs String output

 

By default printf() and puts() functions will output the generated string at once, so that a single semihosted operation can output the string to the console of the debugger. Note that these versions of printf() /puts() make use of malloc() to provide a temporary buffer on the heap in order to generate the string to be displayed.

 

It is possible to switch to using "character-by-character" versions of these functions (which do not require additional heap space) by specifying the build define "CR_PRINTF_CHAR" (which should be set at the project level). This can be useful, for example, if you are retargeting printf() to write out over a UART (as detailed below)- as in this case it is pointless creating a temporary buffer to store the whole string, only to then print it out over the UART one character at a time.

 

"Integer only" vs "full" printf (including floating point)

 

The printf() routine incorporated into Redlib is much smaller than that in Newlib. Thus if code size is an issue, then always try to use Redlib if possible In addition if your application does not pass floating point numbers to printf, you can also select a "integer only" (non-floating point compatible) variant of printf. This will reduce code size further.

 

To enable the "integer only" printf from Redlib, define the symbol "CR_INTEGER_PRINTF" (at the project level).

 

Note that if you only require the display of fixed strings, then using puts() rather than printf() will noticeably reduce the code size of your application.

 

Printf when using LPCOpen

 

If you are building your application against LPCOpen, you may find that printf output does not get displayed in the LPCXpresso debug console by default. This is due to many LPCOpen board library projects by default redirecting printf to a UART output.

 

If you want to direct printf output to the debug console instead, then you will need to modify your projects so that:

 

  1. Your main application project is linked against the "semihost" variant of the C library, and

  2. You disable the LPCOpen board library's redirection of printf output by either:

    • locating the source file board.c within the LPCOpen board library and comment out the line: #include "retarget.h, or

    • locating the file board.h and enable the line: #define DEBUG_SEMIHOSTING

 

Retargeting printf/scanf

 

By default, the printf function outputs text to the debug console using the "semihosting" mechanism.

 

In some circumstances, this output mechanism may not be suitable for your application. Instead, you may want printf to output via an alternative communication channel such as a UART or - on Cortex-M3/M4 - the ITM channel of SWO Trace. In such cases you can retarget the appropriate portion of the bottom level of the library.

 

The FAQ "How to use ITM Printf" provides an example of how this can be done.

 

Note that when retargeting these functions, you can typically link against the "nohost" variant of the C Library, rather than the "semihost" one.

 

Redlib

 

To retarget Redlib's printf(), you need to provide your own implementations of the function __sys_write():

int __sys_write(int iFileHandle, char *pcBuffer, int iLength)
Function returns number of unwritten bytes if error, otherwise 0 for success

Similarly if you want to retarget scanf(), you need to provide your own implementations of the function __sys_readc():

int __sys_readc(void)
Function returns character read

Note that these two functions effectively map directly onto the underlying "semihosting" operations.

 

Newlib

 

To retarget printf(), you will need to provide your own implementation of the Newlib system function _write():

int _write(int iFileHandle, char *pcBuffer, int iLength)
Function returns number of unwritten bytes if error, otherwise 0 for success

To retarget scanf, you will need to provide your own implementation of the Newlib system function _read():

int _read(int iFileHandle, char *pcBuffer, int iLength) 
Function returns number of characters read, stored in pcBuffer

 

More information on the Newlib system calls can be found at:

 

http://sourceware.org/newlib/libc.html#Syscalls

Outcomes