LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Porting a new platform to LPCOpen

Introduction
This guide explains how to add a new Board layer into LPCOpen and configure the drivers and tools for that platform. The general porting procedure is as follows:

  • Create a new board directory in the ./software/lpc_core/lpc_board/board_{chip} are for your board
  • Create sys_config.h file used to configure platform code
  • Add board code for debug, LED, clocks setup, memory setup, etc.

There are many reference platforms that currently exist in LPCOpen for getting started. These platforms provide reference code that can be easily ported to a new platform.

The LPCOpen projects have an include path that points to a specific board layer directory for it's project target. If you want to use existing LPCOpen projects on your board without any modifications, it is recommended to use an existing board layer directory name for your new platform or you will need to modify the board layer include path for the projects you plan on using.

For this guide, we'll create a new Board layer using an (non-existant) example board called 'greenboard'. Greenboard will have a LPC4076 device with a 16-bit DRAM device and uses a 13MHz crystal. Greenboard also supports Ethernet using an RMII configuration, uses a lot of general purpose inputs and outputs for monitoring and controlling signals, and has a RS232 connector attached to UART1.

Create new directory and initial files
Start by creating a new directory in the LPC17xx/40xx board area for the board. The new directory will be named after the board and located in the LPC17xx/40xx board area at

  • "<LPCOPEN_PATH>\software\lpc_core\lpc_boards\boards_17xx_40xx\greenboard".

A minimum of 3 files are needed in the new directory. These files are:

  • sys_config.h (Platform configuration file)
  • board.h (Board layer include file)
  • Board and system source code (board.c) (Board layer initialization code and APIs)

Current LPCOpen board layers may have more than these 3 files. Most LPCOpen Board layer code separates the code for SystemInit() and board APIs into 2 separate source code files and uses a local board specific header file that's include by board.h.

sys_config.h file
The sys_config.h file is used by the compiler to perform build-time optimization of all source code. Definitions and values setup in this file are used to setup drivers to your board's configuration and may vary per device. You can get hints of settings for this file from other board layer code or a list of posible settings for this file at Adding platform definitions using sys_config.h.

For Greenboard, we need to add the following defines:

  • CHIP_LPC407X_8X // LPC40xx device family for LPC4076
  • USE_RMII // Uses RMII interface for Ethernet
  • CRYSTAL_MAIN_FREQ_IN=13000000 // 13MHz main crystal frequency
  • CRYSTAL_32K_FREQ_IN=32768 // 32KHz RTC frequency
  • DEBUG_ENABLE // Enable Debug support
  • DEBUG_UART=LPC_UART1 // Debug UART is UART1
#ifndef __SYS_CONFIG_H_
#define __SYS_CONFIG_H_

/* CORE_M4 needs to be setup as a compiler definition for the LPC4076 and
   should not be included in sys_config.h */

#define CHIP_LPC407X_8X
#define USE_RMII
#define CRYSTAL_MAIN_FREQ_IN (13000000)
#define CRYSTAL_32K_FREQ_IN (32768)
#define DEBUG_ENABLE
#define DEBUG_UART LPC_UART3

#endif /* __SYS_CONFIG_H_ */

board.h file
The board.h file includes optional function definitions for setting up peripheral interfaces when using the various LPCOpen examples. These functions are usually in the format:
Board_<PERIPHERAL>_Init(pointer to peripheral block);

The board.h file usually includes chip.h, board_api.h (which contains the function definitions for standard board API functions), and any other board specific files.

Since I want to use some of the LPCOpen examples on Greenboard, some Board layer functions have been added to support them for UART, I2C, and SSP. The lpc_phy.h file is included here to support the simple PHY driver for the Ethernet interface.

#ifndef __GREENBOARD_H_
#define __GREENBOARD_H_

#include "chip.h"
#include "board_api.h"
#include "lpc_phy.h"

#ifdef __cplusplus
extern "C" {
#endif

/* These board layer functions are called from the LPCOpen examples and
   configure the board for the selected interface (like pinmuxing) */
void Board_UART_Init(LPC_USART_T *pUART);
void Board_SSP_Init(LPC_SSP_T *pSSP);
void Board_I2C_Init(I2C_ID_T id);

void Board_ENET_GetMacADDR(uint8_t *mcaddr);

#endif /* __GREENBOARD_H_ */

board.c file
The board.c file includes the following recommended functions, as defined by the board_api.h (BOARD: Common board functions) file. Most LPCOpen examples use these functions.

The board.c file also includes the following optional functions. These functions sould only be needed if you use an example that uses them.

board.c file - SystemInit() function
LPCOpen startup code - code that gets called directly when the chip is reset - calls the SystemInit() first prior to starting the application. This initializes most platform resources prior to the application using them. SystemInit() performs the following:

  • Sets up system clocking - PLLs, clock sources, CPU clock rate, etc.
  • Sets up board pin muxing
  • Sets up memory, FLASH timing,
  • Other device specific tasks (FPU initialization, VTOR setup, etc.)

The full implementation of SystemInit() varies per platform and is beyond the scope of this guide. Other LPCOpen SystemInit() functions for similar board will probably work with some modifications. On a new platform, this function can be initially stubbed out, but must setup the proper VTOR pointer (replicate this code from another platform). In current LPCOpen platforms, SystemInit() is broken up into separate clock, pin muxing, and memory setup functions to make things more readable. SystemInit() is called before the data segments have been initialized, so any code in SystemInit() must take care to avoid using un-initialized data segments. LPCOpen SystemInit() functions only used the stack.

On the Greenboard platform, SystemInit() would setup the PLL to 120MHz and switch the CPU core clock to run from the PLL. DRAM would be initialized with clock at 60MHz. All the pins in the LPC4076 would be placed into the correct pin mux configuration prior to exist.

board.c file - SystemCoreClockUpdate() function and SystemCoreClock The SystemCoreClockUpdate() function updates the SystemCoreClock variable with the current COPU clock speed. This function should be called in Board_Init() or whenever a CPU clock rate change is made.

/*!< System Clock Frequency (Core Clock) */
uint32_t SystemCoreClock;

/* Update system core clock rate, should be called if the system has
   a clock rate change */
void SystemCoreClockUpdate(void)
{
 /* CPU core speed */
 SystemCoreClock = Chip_Clock_GetSystemClockRate();
}

board.c file - Board_Debug_Init() function
The Board_Debug_Init() function sets up the Debug I/O used with the DEBUGOUT, DEBUGSTR and DEBUGIN macros. In most cases, this function is setup using the DEBUG_ENABLE and DEBUG_UART definitions.

void Board_Debug_Init(void)
{
#if defined(DEBUG_ENABLE)
 /* UART already correctly muxed in SystemInit() */

 /* Setup UART for 115.2K8N1 */
 Chip_UART_Init(DEBUG_UART);
 Chip_UART_SetBaud(DEBUG_UART, 115200);
 Chip_UART_ConfigData(DEBUG_UART, UART_DATABIT_8, UART_PARITY_NONE, UART_STOPBIT_1);

 /* Enable UART Transmit */
 Chip_UART_TxCmd(DEBUG_UART, ENABLE);
#endif
}

board.c file - Board_UARTPutChar(), Board_UARTGetChar(), and Board_UARTPutSTR() functions
The Board_UART*() functions are used to send a character or string, or get a byte form the Debug I/O channel. When DEBUG_ENABLE is defined, these functions are mapped to the DEBUGOUT, DEBUGSTR and DEBUGIN macros. If not using DEBUG_ENABLE, these functions do not need to be defined.

/* Sends a character on the UART */
void Board_UARTPutChar(char ch)
{
#if defined(DEBUG_ENABLE)
 while (Chip_UART_SendByte(DEBUG_UART, (uint8_t) ch) == ERROR) {}
#endif
}

/* Gets a character from the UART, returns EOF if no character is ready */
int Board_UARTGetChar(void)
{
#if defined(DEBUG_ENABLE)
 uint8_t data;

 if (Chip_UART_ReceiveByte(DEBUG_UART, &data) == SUCCESS) {
  return (int) data;
 }
#endif
 return EOF;
}

/* Outputs a string on the debug UART */
void Board_UARTPutSTR(char *str)
{
#if defined(DEBUG_ENABLE)
 while (*str != '\0') {
  Board_UARTPutChar(*str++);
 }
#endif
}

board.c file - Board_LED_Set() and Board_LED_Test() functions
The Board_LED*() functions are used to set or test an LED state.

Board_LED_Toggle() function is defined in board.h and uses both the Board_LED_Set() and Board_LED_Test() functions and doesn't need a board layer functions.

/* Sets the state of a board LED to on or off */
void Board_LED_Set(uint8_t LEDNumber, bool On)
{
 /* There is only one LED */
 if (LEDNumber == 0) {
  Chip_GPIO_WritePortBit(LPC_GPIO, LED0_GPIO_PORT_NUM, LED0_GPIO_BIT_NUM, On);
 }
}

/* Returns the current state of a board LED */
bool Board_LED_Test(uint8_t LEDNumber)
{
 return Chip_GPIO_ReadPortBit(LPC_GPIO, LED0_GPIO_PORT_NUM, LED0_GPIO_BIT_NUM);
}

board.c file - Board_Init() function
The Board_Init() function is used to initialize the board once the application starts and after SystemInit() has completed. In LPCOpen examples, this is usually the first function called.

At a minimum, Board_Init() should call DEBUGINIT() to set up the Debug I/O and SystemCoreClockUpdate() to setup the SystemCoreClock variable. Any special board setup should also be done here, such as setting GPIO pin direction, or setting up other common board code.

/* Set up and initialize all required blocks and functions related to the
   board hardware */
void Board_Init(void)
{
 /* Sets up DEBUG UART */
 DEBUGINIT();

 /* Updates SystemCoreClock global var with current clock speed */
 SystemCoreClockUpdate();

 /* Initializes GPIO */
 Chip_GPIO_Init(LPC_GPIO);
 Chip_IOCON_Init(LPC_IOCON);

 /* Initialize LEDs */
 Board_LED_Init();
}

Other required board files
If yuor platform uses DEBUG_ENABLE, you need to include the retarget.c file from the 'board_common' directory in your image.

The Greenboard platform uses DEBUG_ENABLE and will require the retarget.c file.

Common board files
The 'board_common' directory has some common board code that works across multiple platforms.

The Greenboard Ethernet interface requires an external PHY. If the PHY on the Greenboard matches one of the simple PHY drivers in 'board_common', it can be included in the image to quickly get PHY support.