AnsweredAssumed Answered

LPCOpen debug input/output support

Question asked by LPCware Support on Apr 22, 2016
Latest reply on Apr 22, 2016 by LPCware Support

LPCOpen supports simple debug input/output support as part of the standard board layer API. These functions can be used to provide simple debug message output and input via a UART or device.  The functions are abstracted in the board layer and can be reimplemented to another device if needed. Default implementations included with LPCopen use available UARTs for a board if they exist, but can also be routed via semihosting to the debuggers console if it's available. If a UART capability doesn't exist on the board, debug support is usually disabled for that board.

 

It is recommended to use the DEBUG* implementations for debug input and output instead of printf or other custom implementations as the functions can easily be removed from an image by simply building the board layer code and example code with DEBUG_ENABLE undefined.

 

DEBUG function implementations

 

Inlcuded as part of the common board API in the 'lpcopen/software/lpc_core/\lpc_board/board_common' area, the board_api.h file includes the default DEBUG* implementation and functions used by all LPCOpen boards. If you want to replace the functions for your platform, you can change this file to use your own implementations. The selected implementation of the DEBUG* functions depend on the enabled states of the DEBUG_ENABLE and DEBUG_SEMIHOSTING definitions.

 

The LPCOpen DEBUG* functions defined in the board_api.h file are DEBUGINIT(), DEBUGOUT(), DEBUGSTR(), and DEBUGIN(). These are defined as macro definitions that select a specific implementation based on whether DEBUG_ENABLE and DEBUG_SEMIHOSTING are defined.

 

The code used for this is shown below. This code may change over time, see the board_api.h file for the latest implementation.

/* The DEBUG* functions are selected based on system configuration.
   Code that uses the DEBUG* functions will have their I/O routed to
   the UART, semihosting, or nowhere. */
#if defined(DEBUG_ENABLE)
#if defined(DEBUG_SEMIHOSTING)
#define DEBUGINIT()
#define DEBUGOUT(...) printf(__VA_ARGS__)
#define DEBUGSTR(str) printf(str)
#define DEBUGIN() (int) EOF

#else
#define DEBUGINIT() Board_Debug_Init()
#define DEBUGOUT(...) printf(__VA_ARGS__)
#define DEBUGSTR(str) Board_UARTPutSTR(str)
#define DEBUGIN() Board_UARTGetChar()
#endif /* defined(DEBUG_SEMIHOSTING) */

#else
#define DEBUGINIT()
#define DEBUGOUT(...)
#define DEBUGSTR(str)
#define DEBUGIN() (int) EOF
#endif /* defined(DEBUG_ENABLE) */

DEBUG_ENABLE and DEBUG_SEMIHOSTING definitions

 

Define or undefine the DEBUG_ENABLE and DEBUG_SEMIHOSTING definitions to disable DEBUG* functions complete or enable debugging via a device (UART) or via semihosting.

 

When both DEBUG_ENABLE and DEBUG_SEMIHOSTING are undefined, DEBUG* functions will be built out of the code and make a much smaller image.

 

When DEBUG_ENABLE is defined and DEBUG_SEMIHOSTING is undefined, DEBUG* functions will be setup for the default device. For supported LPCOpen boards, this is usually a UART. The default UART implementations of DEBUGOUT() and DEBUGSTR() functions are blocking and will affect code timing.

 

When both DEBUG_ENABLE and DEBUG_SEMIHOSTING are defined, DEBUG* functions will be setup for semihosting. This capability varies per toolchain. Semiihosting is usually blocking and will affect code timing.

 

You can change these settings in the board.h file for your LPCOpen release. You will need to rebuild the board library and example code after making the change.

Additional information on setting up semihosting

 

If you setup the DEBUG* support for semihosting, you may need to also configure the toolchain to support semihosting. See the topic(s) below for more information on toolchain specific semihosting setup support.

LPCXPresso semihosting library support

DEBUGINIT()

 

The DEBUGINIT() function definition sets up the debug input and output device(s). This needs to be called prior to calling any other DEBUG* functions. If DEBUG_ENABLE is not defined, this function will do nothing. If DEBUG_ENABLE is defined, but DEBUG_SEMIHOSTING is not defined, then the default LPCOpen implementation will attempt to use a UART for debug input and output. For most LPCOpen platforms, these functions are already setup to the available UART interface for the board. You can change the functions to another implementation if needed.

 

For all LPCOpen release, the DEBUGINIT() function is called automatically when you called Board_Init(). If you don't use a board layer in your example, but use these functions, you will need to call DEBUGINIT() in your code.

DEBUGOUT()

 

The DEBUGOUT() function provides formatted output to the debug output device. This maps to the printf() function whenever DEBUG_ENABLE is defined. The formatted string must be null terminated.

DEBUGSTR()

 

The DEBUGSTR() function simply outputs a raw string to the debug output device when DEBUG_ENABLE is defined. If DEBUG_SEMIHOSTING is defined, this maps to the printf() function. If DEBUG_SEMIHOSTING is not defined, then the raw string data is routed out top the output device directly. When not using semihosting, using this implementation over DEBUGOUT() can save memory since the formatting library isn't needed. The string or data must be null terminated.

DEBUGIN()

 

The DEBUGIN() function is used to poll the debug input device for a character. This function never blocks and will always return a single character value or EOF. If DEBUG_ENABLE is not defined, or both DEBUG_ENABLE and DEBUG_SEMIHOSTING are defined, then this function will return EOF. If DEBUG_ENABLE is defined and DEBUG_SEMIHOSTING is not defined, then the function will return a singel byte read from the device if it exists or EOF if no data exists.

Outcomes