How do I port LPCOpen to a new board?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How do I port LPCOpen to a new board?

4,468 Views
lpcware-support
Senior Contributor I

You've just created a brand new development board and now you want to run some LPCOpen code on it to see how it works. May be you want to quickly test some of the exiting LPCOpen examples and projects on your new board without making a lot of changes to the LPCOpen code? This FAQ will help with explaing the steps needed to port LPCOpen to your board.

Porting LPCopen to your board is completely optional. You don't have to port LPCOpen at all unless you want to use the common LPCopen system initialization approach or want to use the LPCOpen examples with a minimum of changes. You could setup the startup code to use LPCopen

LPCOpen is meant to be easy to port to new platforms. when porting LPCOpen to a new platform, you typically only need to provide a board layer for your board. If using existing LPCopen examples, you may also - but not always - need to alter pin muxing settings for specific examples.

Before reading this FAQ, you should understand how LPCOpen applications perform system initialization. See this FAQ entry for details on LPCOpen application startup.

What is needed for an LPCOpen port?

To port LPCOpen to a new platform, you will need to develop board layer code. This layer provides the system bringup for the board - pin muxing, system clocking, and external memory setup. At a minimum, it also provides abstracted board level functions for LED control, DEBUG input/output (via UART), and button state monitoring.

If you want to use LPCopen examples without making a lot of modifications, you may also need to tweak muxed pin settings at the project level. For projects that require these settings to be setup for a new platform, the project will usually give a warning or error indicating the needed setup at build time.

LPCOpen projects are setup to use the board layer code as a board library, with a dedicated board project to build the board library. LPCOpen applications use the board library file to link against instead of the board layer functions directly.

LPCOpen board layer

The LPCopen board layer needs to be ported to use LPCOpen. The board layer consists of 3 files - board.h, board.c, and board_sysinit.c. There may also be one or more project files for IAR and Keil for building the board layer code into a library.

Board layer code is located in the LPCopen tree at software/lpc_core/lpc_board/<CHIP>/<BOARD>. For Keil and IAR releases. For the LPCXpresso release, it is located in the board library project area in the workspace.

Porting the board layer requires writing the following functions:

  • Functions in board_sysinit.c
    • void Board_SystemInit(void);
    • void Board_SetupMuxing(void);
    • void Board_SetupClocking(void);
    • void Board_SetupExtMemory(void); (Optional - not all devices support external memory)
  • Functions in board.c
    • void Board_Init(void);
    • void Board_Debug_Init(void);
    • void Board_UARTPutChar(char ch);
    • int Board_UARTGetChar(void);
    • void Board_UARTPutSTR(char *str);
    • void Board_LED_Set(uint8_t LEDNumber, bool State);
    • bool Board_LED_Test(uint8_t LEDNumber);
    • void Board_LED_Toggle(uint8_t LEDNumber);

Board_SystemInit() in board_sysinit.c

The Board_SystemInit() function in board_sysinit.c file is used to initialize the platform's pin muxing, clocking, and external memory to an initial state prior to calling main(). Board_SystemInit() may call Chip layer functions or other board layer functions for setup. The version provided in most LPCOpen distributions usually calls Board_SetupMuxing(), Board_SetupClocking(), and Board_SetupExtMemory() if needed.

/**
 * @brief    Setup and initialize hardware prior to call to main()
 * @return    None
 * @note    Board_SystemInit() is called prior to the application and sets up system
 * clocking, memory, and any resources needed prior to the application
 * starting.
 */
void Board_SystemInit(void);

Board_SetupMuxing() in board_sysinit.c

The Board_SetupMuxing() function simply sets up the board pin functions to their default states. If you don't need this function and would prefer to setup pin muxing as needed, you can stub this function. Using this centralized version over individual calls as needed can save code space as the pin mux table is packed and processed as an array. See the existing board layer functions for how to write this function.

/**
 * @brief    Setup pin multiplexer per board schematics
 * @return    None
 * @note    Board_SetupMuxing() should be called from SystemInit() prior to application
 * main() is called. So that the PINs are set in proper state.
 */
void Board_SetupMuxing(void);

Board_SetupClocking() in board_sysinit.c

The Board_SetupClocking() function sets up system level clocking. This may vary per board, with some boards using an external oscillator or crystal, and others using the internal RC oscillator. Some boards use this function to call the chip layer function for setting up board clocking. This function should enable any power domains needed for clocking, enable the crystal if needed, setup the main PLL, and setup the CPU clock source from the main PLL.

/**
 * @brief    Setup system clocking 
 * @return    None
 * @note    This sets up board clocking.
 */
void Board_SetupClocking(void);

Board_SetupExtMemory() in board_sysinit.c

The Board_SetupExtMemory() function is used to setup external memory. Most platforms don't need this function and it can be safely stubbed.

/**
 * @brief    Setup external system memory
 * @return    None
 * @note    This function is typically called after pin mux setup and clock setup and
 * sets up any external memory needed by the system (DRAM, SRAM, etc.). Not all
 * boards need this function.
 */
void Board_SetupExtMemory(void);

Board_Init() in board.c

All LPCopen applications call Board_Init() almost directly after the entry to main(). Board_Init() provides any board level initialization that isn't performed as part of Board_SystemInit(). This includes UART setup and LED/GPIO setup.

/**
 * @brief    Set up and initialize all required blocks and functions related to the board hardware.
 * @return    None
 */
void Board_Init(void);

Board_Debug_Init() in board.c

The Board_Debug_Init() function sets up the DEBUG UARTfor input and output of debug data. This function is usually called as part of Board_Init(). See this FAQ for more information on the DEBUG UART.

/**
 * @brief    Initializes board UART for output, required for printf redirection
 * @return    None
 */
void Board_Debug_Init(void);

Board_UARTPutChar() in board.c

The Board_UARTPutChar() function sends a single byte of data on the DEBUG UART. Note the default implementation for most LPCOpen board layer code will block until the UART can take the byte to send.

/**
 * @brief    Sends a single character on the UART, required for printf redirection
 * @param    ch    : character to send
 * @return    None
 */
void Board_UARTPutChar(char ch);

Board_UARTGetChar() in board.c

The Board_UARTGetChar() function gets a single byte of data on the DEBUG UART. If a byte doesn't exist, EOF is returned.

/**
 * @brief    Get a single character from the UART, required for scanf input
 * @return    EOF if not character was received, or character value
 */
int Board_UARTGetChar(void);

Board_UARTPutSTR() in board.c

The Board_UARTPutSTR() function sends a NULL terminated string on the DEBUG UART. Note the default implementation for most LPCOpen board layer code will block until the UART can send the entire string.

/**
 * @brief    Prints a string to the UART
 * @param    str    : Terminated string to output
 * @return    None
 */
void Board_UARTPutSTR(char *str);

Board_LED_Set() in board.c

The Board_LED_Set() function sets the state of an LED. LEDs are mapped starting at index 0 and the function handles mapping the on/off state and index to the correct GPIO state (high or low) for on or off and the correct GPIO port and pin mapping.

/**
 * @brief    Sets the state of a board LED to on or off
 * @param    LEDNumber    : LED number to set state for
 * @param    State        : true for on, false for off
 * @return    None
 */
void Board_LED_Set(uint8_t LEDNumber, bool State);

Board_LED_Test() in board.c

The Board_LED_Test() function returns the on/off state of an LED. LEDs are mapped starting at index 0 and the function handles mapping the on/off state and index to the correct GPIO state (high or low) for on or off and the correct GPIO port and pin mapping.

/**
 * @brief    Returns the current state of a board LED
 * @param    LEDNumber    : LED number to set state for
 * @return    true if the LED is on, otherwise false
 */
bool Board_LED_Test(uint8_t LEDNumber);

Board_LED_Toggle() in board.c

The Board_LED_Toggle() function toggles the on/off state of an LED. LEDs are mapped starting at index 0 and the function handles mapping the on/off state and index to the correct GPIO state (high or low) for on or off and the correct GPIO port and pin mapping.

/**
 * @brief    Toggles the current state of a board LED
 * @param    LEDNumber    : LED number to change state for
 * @return    None
 */
void Board_LED_Toggle(uint8_t LEDNumber);

What about board.h?

The board.h file provide in the board layer provides an include to the chip.h file, the DEBUG definitions, a board name definition value, and an include to the board_api.h file.

The chip.h file is included because most LPCOpen applications only need to include board.h. The DEBUG definitions are used for DEBUG input/routing. The optional board name definition is used with LPCOpen exampples that have specific pin muxing setup or use requirements.

/** Define DEBUG_ENABLE to enable IO via the DEBUGSTR, DEBUGOUT, and
    DEBUGIN macros. If not defined, DEBUG* functions will be optimized
    out of the code at build time.
 */
#define DEBUG_ENABLE

/** Define DEBUG_SEMIHOSTING along with DEBUG_ENABLE to enable IO support
    via semihosting. You may need to use a C library that supports
    semihosting with this option.
 */
// #define DEBUG_SEMIHOSTING

/** Board UART used for debug output and input using the DEBUG* macros. This
    is also the port used for Board_UARTPutChar, Board_UARTGetChar, and
    Board_UARTPutSTR functions.
 */
#define DEBUG_UART LPC_USART0

/**
 * @}
 */

/* Board name */
#define BOARD_MY_NEW_BOARD

LPCOpen applications

If you are using the unmodified LPCOpen applications with your new board, you may need to tweak the pin muxing settings or pin use settings with an application. For example, for an ADC example, the example may be setup to use ADC3 as the default input. If your board also uses ADC2, you'll need to tweak the example to use your mapped pin. Most LPCOpen examples that use board specific pins will generate and build time warning or error if the example needs to be setup for the board. This build time message is based on the board name definition in the board.h file.

Labels (1)
0 Replies