Content originally posted in LPCWare by robert.palmer on Wed Jun 20 13:26:47 MST 2012
Hi all.
I'll post an example at some point, but wanted to at least post a "how to" as soon as possible since I was able to effectively get this working. I've included a couple of extra pieces to handle:
- using a UART port instead of the debug console
- dealing with both newer and older versions of the LPCXpresso IDE
First off, IGNORE the comments on putchar/outbyte, and the commented section that contains "main.c" - they're from the original code and do NOT apply to the NXP modified code. NXP took the approach of providing a function pointer parameter to the printf function. This function pointer should be a function that takes a char, prints it and then returns an int (see the typedef in small_printf.h)
Second, printf is NOT defined anywhere, YOU must define it in your code and reference it to the func_printf_nofloat() or fund_printf_float() (depending on whether you want float support or not)
Also, if you DO want float support, you must define LIB_FLOAT_PRINTF, I would recommend doing this in the compiler settings (project/properties/C/C++ Build/Settings/MCU C Compiler/Symbols)
The code relies on the linker to strip unused code. Both float and non-float appear to be compiled, but because only one of them is referenced (through the define in small_printf.h), the other will not get linked in.
So here's what I did:
define USE_SMALL_PRINTF to enable small printf
define USE_UART_DEBUG_PORT to use a UART instead of the debug console
This chunk is from Red Code and provides a way to handle older and newer versions of the LPCXpresso IDE
WRITEFUNC and READFUNC will be the names you use later in the code. This should go in the same header file as the code chunk below.
//------------------------------------------
// support for semihosting
// Include stdio.h to pull in __REDLIB_INTERFACE_VERSION__
#include <stdio.h>
#if (__REDLIB_INTERFACE_VERSION__ >= 20000)
// We are using new Redlib_v2 semihosting interface
#define WRITEFUNC __sys_write
#define READFUNC __sys_readc
#else
// We are using original Redlib semihosting interface
#define WRITEFUNC __write
#define READFUNC __readc
#endif
This is the main piece for using lib_small_printf_m0. It should go in a header file, to be included by any code that will use printf. This code chunk allow you to choose between sending the printf to the debug console (you must select a semihost library) or to the UART.
//--------------------------------------------
// support for lib_small_printf_m0
// must define a char output function and redefine printf
#if defined(USE_SMALL_PRINTF)
#include <small_printf.h>
int _debuguart_putchar(char c);
int _debugconsole_putchar(char c);
int _debug_buf_printf(char *format, ...);
#if defined(USE_UART_DEBUG_PORT)
#define printf(S,...) func_printf(_debuguart_putchar, S, ##__VA_ARGS__)
#else
#define printf(S,...) _debug_buf_printf(S, ##__VA_ARGS__)
#endif
#endif
Now in a C file, include the following code:
#if defined(USE_SMALL_PRINTF)
extern int WRITEFUNC(int zero, char *s, int len);
#if defined(USE_UART_DEBUG_PORT)
int _debuguart_putchar(char c)
{
// your favorite flavor of function that will send a char to the UART of your choice
return UARTPutChar(DEBUG_UART_PORT, c);
}
#else
// This version of _putchar generates output on the debug console
// ONE CHAR AT A TIME - VERY SLOW!
int _debugconsole_putchar(char c)
{
return WRITEFUNC(0, &c, 1);
}
#endif
#endif
As you can see from the comment, this is VERY slow. A modified version that buffers the chars, then writes them all to the output can be done using the following:
Put this in your 'C' file
// This version generates output on the debug console, one BUFFER at a time
char debug_printf_buf[128];
int _debug_buf_printf(char *format, ...)
{
va_list args;
va_start( args, format );
nsprintf_write_init((char *) debug_printf_buf, sizeof(debug_printf_buf));
printf_format( nsprintf_write, format, args );
return WRITEFUNC(0, debug_printf_buf, sizeof(debug_printf_buf));
}
and change your '.h' file to redefine printf as:
#define printf(S,...) _debug_buf_printf(S, ##__VA_ARGS__)
This only allows an output string of 128 chars, but that should be enough in most cases. This is noticeably faster, but still not as fast as code red's printf to the console. The advantage is that this is only a little over 1K whereas code red's printf add about 12k
Hope this helps some of you. At some point, I'll post a complete example.