diff --git a/hw/bsp/lpc51/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/lpc51/FreeRTOSConfig/FreeRTOSConfig.h
new file mode 100644
index 000000000..e6604d360
--- /dev/null
+++ b/hw/bsp/lpc51/FreeRTOSConfig/FreeRTOSConfig.h
@@ -0,0 +1,169 @@
+/*
+ * FreeRTOS Kernel V10.0.0
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software. If you wish to use our Amazon
+ * FreeRTOS name, please do so in a fair use way that does not cause confusion.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+// skip if included from IAR assembler
+#ifndef __IASMARM__
+  #include "fsl_device_registers.h"
+#endif
+
+/* Cortex M23/M33 port configuration. */
+#define configENABLE_MPU                        0
+#if defined(__ARM_FP) && __ARM_FP >= 4
+  #define configENABLE_FPU                      1
+#else
+  #define configENABLE_FPU                      0
+#endif
+#define configENABLE_TRUSTZONE                  0
+#define configMINIMAL_SECURE_STACK_SIZE         (1024)
+
+#define configUSE_PREEMPTION                    1
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+#define configCPU_CLOCK_HZ                      SystemCoreClock
+#define configTICK_RATE_HZ                      ( 1000 )
+#define configMAX_PRIORITIES                    ( 5 )
+#define configMINIMAL_STACK_SIZE                ( 128 )
+#define configTOTAL_HEAP_SIZE                   ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
+#define configMAX_TASK_NAME_LEN                 16
+#define configUSE_16_BIT_TICKS                  0
+#define configIDLE_SHOULD_YIELD                 1
+#define configUSE_MUTEXES                       1
+#define configUSE_RECURSIVE_MUTEXES             1
+#define configUSE_COUNTING_SEMAPHORES           1
+#define configQUEUE_REGISTRY_SIZE               2
+#define configUSE_QUEUE_SETS                    0
+#define configUSE_TIME_SLICING                  0
+#define configUSE_NEWLIB_REENTRANT              0
+#define configENABLE_BACKWARD_COMPATIBILITY     1
+#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP   0
+
+#define configSUPPORT_STATIC_ALLOCATION         1
+#define configSUPPORT_DYNAMIC_ALLOCATION        0
+
+/* Hook function related definitions. */
+#define configUSE_IDLE_HOOK                    0
+#define configUSE_TICK_HOOK                    0
+#define configUSE_MALLOC_FAILED_HOOK           0 // cause nested extern warning
+#define configCHECK_FOR_STACK_OVERFLOW         2
+
+/* Run time and task stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS          0
+#define configRECORD_STACK_HIGH_ADDRESS        1
+#define configUSE_TRACE_FACILITY               1 // legacy trace
+#define configUSE_STATS_FORMATTING_FUNCTIONS   0
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES                  0
+#define configMAX_CO_ROUTINE_PRIORITIES        2
+
+/* Software timer related definitions. */
+#define configUSE_TIMERS                       1
+#define configTIMER_TASK_PRIORITY              (configMAX_PRIORITIES-2)
+#define configTIMER_QUEUE_LENGTH               32
+#define configTIMER_TASK_STACK_DEPTH           configMINIMAL_STACK_SIZE
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet               0
+#define INCLUDE_uxTaskPriorityGet              0
+#define INCLUDE_vTaskDelete                    0
+#define INCLUDE_vTaskSuspend                   1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
+#define INCLUDE_xResumeFromISR                 0
+#define INCLUDE_vTaskDelayUntil                1
+#define INCLUDE_vTaskDelay                     1
+#define INCLUDE_xTaskGetSchedulerState         0
+#define INCLUDE_xTaskGetCurrentTaskHandle      1
+#define INCLUDE_uxTaskGetStackHighWaterMark    0
+#define INCLUDE_xTaskGetIdleTaskHandle         0
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
+#define INCLUDE_pcTaskGetTaskName              0
+#define INCLUDE_eTaskGetState                  0
+#define INCLUDE_xEventGroupSetBitFromISR       0
+#define INCLUDE_xTimerPendFunctionCall         0
+
+/* Define to trap errors during development. */
+// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7
+#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
+  #define configASSERT(_exp) \
+    do {\
+      if ( !(_exp) ) { \
+        volatile uint32_t* ARM_CM_DHCSR =  ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \
+        if ( (*ARM_CM_DHCSR) & 1UL ) {  /* Only halt mcu if debugger is attached */ \
+          taskDISABLE_INTERRUPTS(); \
+           __asm("BKPT #0\n"); \
+        }\
+      }\
+    } while(0)
+#else
+  #define configASSERT( x )
+#endif
+
+/* FreeRTOS hooks to NVIC vectors */
+#define xPortPendSVHandler    PendSV_Handler
+#define xPortSysTickHandler   SysTick_Handler
+#define vPortSVCHandler       SVC_Handler
+
+//--------------------------------------------------------------------+
+// Interrupt nesting behavior configuration.
+//--------------------------------------------------------------------+
+
+// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header
+#define configPRIO_BITS       2
+
+/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			  ((1<<configPRIO_BITS) - 1)
+
+/* The highest interrupt priority that can be used by any interrupt service
+routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	2
+
+/* Interrupt priorities used by the kernel port layer itself.  These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY 		          ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	        ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
+#endif /* __FREERTOS_CONFIG__H */
diff --git a/hw/bsp/lpc51/boards/lpcxpresso51u68/board.cmake b/hw/bsp/lpc51/boards/lpcxpresso51u68/board.cmake
new file mode 100644
index 000000000..1f549bf50
--- /dev/null
+++ b/hw/bsp/lpc51/boards/lpcxpresso51u68/board.cmake
@@ -0,0 +1,13 @@
+set(MCU_VARIANT LPC51U68)
+
+set(JLINK_DEVICE LPC51U68)
+set(PYOCD_TARGET LPC51U68)
+
+function(update_board TARGET)
+  target_compile_definitions(${TARGET} PUBLIC
+    CPU_LPC51U68JBD64
+    )
+  target_link_libraries(${TARGET} PUBLIC
+    ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/libpower.a
+    )
+endfunction()
diff --git a/hw/bsp/lpc51/boards/lpcxpresso51u68/board.h b/hw/bsp/lpc51/boards/lpcxpresso51u68/board.h
new file mode 100644
index 000000000..0a3b37fda
--- /dev/null
+++ b/hw/bsp/lpc51/boards/lpcxpresso51u68/board.h
@@ -0,0 +1,57 @@
+#ifndef BOARD_H
+#define BOARD_H
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM
+//--------------------------------------------------------------------+
+#define LED_PORT      0
+#define LED_PIN       29
+#define LED_STATE_ON  0
+
+// WAKE button
+#define BUTTON_PORT   0
+#define BUTTON_PIN    24
+
+// IOCON pin mux
+#define IOCON_PIO_DIGITAL_EN          0x80u   /*!< Enables digital function */
+#define IOCON_PIO_FUNC1               0x01u   /*!< Selects pin function 1 */
+#define IOCON_PIO_FUNC7               0x07u   /*!< Selects pin function 7 */
+#define IOCON_PIO_INPFILT_OFF       0x0100u   /*!< Input filter disabled */
+#define IOCON_PIO_INV_DI              0x00u   /*!< Input function is not inverted */
+#define IOCON_PIO_MODE_INACT          0x00u   /*!< No addition pin function */
+#define IOCON_PIO_OPENDRAIN_DI        0x00u   /*!< Open drain is disabled */
+#define IOCON_PIO_SLEW_STANDARD       0x00u   /*!< Standard mode, output slew rate control is enabled */
+
+/****************************************************************
+name: BOARD_BootClockFROHF96M
+outputs:
+- {id: SYSTICK_clock.outFreq, value: 96 MHz}
+- {id: System_clock.outFreq, value: 96 MHz}
+settings:
+- {id: SYSCON.MAINCLKSELA.sel, value: SYSCON.fro_hf}
+sources:
+- {id: SYSCON.fro_hf.outFreq, value: 96 MHz}
+******************************************************************/
+static inline void BootClockFROHF96M(void) {
+  /*!< Set up the clock sources */
+  /*!< Set up FRO */
+  POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on  */
+  CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without
+                                             accidentally being below the voltage for current speed */
+  POWER_SetVoltageForFreq(96000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
+  CLOCK_SetFLASHAccessCyclesForFreq(96000000U); /*!< Set FLASH wait states for core */
+
+  CLOCK_SetupFROClocking(96000000U); /*!< Set up high frequency FRO output to selected frequency */
+
+  /*!< Set up dividers */
+  CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false);     /*!< Set AHBCLKDIV divider to value 1 */
+  CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 0U, true);  /*!< Reset SYSTICKCLKDIV divider counter and halt it */
+  CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U, false); /*!< Set SYSTICKCLKDIV divider to value 1 */
+
+  /*!< Set up clock selectors - Attach clocks to the peripheries */
+  CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */
+  /*!< Set SystemCoreClock variable. */
+  SystemCoreClock = 96000000U;
+}
+
+#endif
diff --git a/hw/bsp/lpc51/boards/lpcxpresso51u68/lpcxpresso51u68.c b/hw/bsp/lpc51/boards/lpcxpresso51u68/lpcxpresso51u68.c
deleted file mode 100644
index 579c9c9ed..000000000
--- a/hw/bsp/lpc51/boards/lpcxpresso51u68/lpcxpresso51u68.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2018, hathach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "bsp/board_api.h"
-#include "fsl_device_registers.h"
-#include "fsl_gpio.h"
-#include "fsl_power.h"
-#include "fsl_iocon.h"
-
-//--------------------------------------------------------------------+
-// Forward USB interrupt events to TinyUSB IRQ Handler
-//--------------------------------------------------------------------+
-void USB0_IRQHandler(void)
-{
-  tud_int_handler(0);
-}
-
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM
-//--------------------------------------------------------------------+
-#define LED_PORT      0
-#define LED_PIN       29
-#define LED_STATE_ON  0
-
-// WAKE button
-#define BUTTON_PORT   0
-#define BUTTON_PIN    24
-
-// IOCON pin mux
-#define IOCON_PIO_DIGITAL_EN          0x80u   /*!< Enables digital function */
-#define IOCON_PIO_FUNC1               0x01u   /*!< Selects pin function 1 */
-#define IOCON_PIO_FUNC7               0x07u   /*!< Selects pin function 7 */
-#define IOCON_PIO_INPFILT_OFF       0x0100u   /*!< Input filter disabled */
-#define IOCON_PIO_INV_DI              0x00u   /*!< Input function is not inverted */
-#define IOCON_PIO_MODE_INACT          0x00u   /*!< No addition pin function */
-#define IOCON_PIO_OPENDRAIN_DI        0x00u   /*!< Open drain is disabled */
-#define IOCON_PIO_SLEW_STANDARD       0x00u   /*!< Standard mode, output slew rate control is enabled */
-
-/****************************************************************
-name: BOARD_BootClockFROHF96M
-outputs:
-- {id: SYSTICK_clock.outFreq, value: 96 MHz}
-- {id: System_clock.outFreq, value: 96 MHz}
-settings:
-- {id: SYSCON.MAINCLKSELA.sel, value: SYSCON.fro_hf}
-sources:
-- {id: SYSCON.fro_hf.outFreq, value: 96 MHz}
-******************************************************************/
-void BootClockFROHF96M(void)
-{
-  /*!< Set up the clock sources */
-  /*!< Set up FRO */
-  POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on  */
-  CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without
-                                             accidentally being below the voltage for current speed */
-  POWER_SetVoltageForFreq(96000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
-  CLOCK_SetFLASHAccessCyclesForFreq(96000000U); /*!< Set FLASH wait states for core */
-
-  CLOCK_SetupFROClocking(96000000U); /*!< Set up high frequency FRO output to selected frequency */
-
-  /*!< Set up dividers */
-  CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false);     /*!< Set AHBCLKDIV divider to value 1 */
-  CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 0U, true);  /*!< Reset SYSTICKCLKDIV divider counter and halt it */
-  CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U, false); /*!< Set SYSTICKCLKDIV divider to value 1 */
-
-  /*!< Set up clock selectors - Attach clocks to the peripheries */
-  CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */
-  /*!< Set SystemCoreClock variable. */
-  SystemCoreClock = 96000000U;
-}
-
-void board_init(void)
-{
-  // Enable IOCON clock
-  CLOCK_EnableClock(kCLOCK_Iocon);
-
-  // Enable GPIO0 clock
-  CLOCK_EnableClock(kCLOCK_Gpio0);
-
-  // Init 96 MHz clock
-  BootClockFROHF96M();
-
-#if CFG_TUSB_OS == OPT_OS_NONE
-  // 1ms tick timer
-  SysTick_Config(SystemCoreClock / 1000);
-#elif CFG_TUSB_OS == OPT_OS_FREERTOS
-  // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
-  NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
-#endif
-
-  GPIO_PortInit(GPIO, LED_PORT);
-  GPIO_PortInit(GPIO, BUTTON_PORT);
-
-  // LED
-  gpio_pin_config_t const led_config = { kGPIO_DigitalOutput, 0};
-  GPIO_PinInit(GPIO, LED_PORT, LED_PIN, &led_config);
-  board_led_write(true);
-
-  // Button
-  gpio_pin_config_t const button_config = { kGPIO_DigitalInput, 0};
-  GPIO_PinInit(GPIO, BUTTON_PORT, BUTTON_PIN, &button_config);
-
-  // USB
-  const uint32_t port1_pin6_config = (
-    IOCON_PIO_FUNC7       | /* Pin is configured as USB0_VBUS */
-    IOCON_PIO_MODE_INACT  | /* No addition pin function */
-    IOCON_PIO_INV_DI      | /* Input function is not inverted */
-    IOCON_PIO_DIGITAL_EN  | /* Enables digital function */
-    IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
-    IOCON_PIO_OPENDRAIN_DI  /* Open drain is disabled */
-  );
-  IOCON_PinMuxSet(IOCON, 1, 6, port1_pin6_config); /* PORT1 PIN6 (coords: 26) is configured as USB0_VBUS */
-
-  POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*Turn on USB Phy */
-  CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); /* enable USB IP clock */
-}
-
-//--------------------------------------------------------------------+
-// Board porting API
-//--------------------------------------------------------------------+
-
-void board_led_write(bool state)
-{
-  GPIO_PinWrite(GPIO, LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
-}
-
-uint32_t board_button_read(void)
-{
-  // active low
-  return 1-GPIO_PinRead(GPIO, BUTTON_PORT, BUTTON_PIN);
-}
-
-int board_uart_read(uint8_t* buf, int len)
-{
-  (void) buf; (void) len;
-  return 0;
-}
-
-int board_uart_write(void const * buf, int len)
-{
-  (void) buf; (void) len;
-  return 0;
-}
-
-#if CFG_TUSB_OS == OPT_OS_NONE
-volatile uint32_t system_ticks = 0;
-void SysTick_Handler(void)
-{
-  system_ticks++;
-}
-
-uint32_t board_millis(void)
-{
-  return system_ticks;
-}
-#endif
diff --git a/hw/bsp/lpc51/family.c b/hw/bsp/lpc51/family.c
new file mode 100644
index 000000000..a0667a741
--- /dev/null
+++ b/hw/bsp/lpc51/family.c
@@ -0,0 +1,141 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018, hathach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "fsl_device_registers.h"
+#include "fsl_gpio.h"
+#include "fsl_power.h"
+#include "fsl_iocon.h"
+
+#include "bsp/board_api.h"
+#include "board.h"
+
+//--------------------------------------------------------------------+
+// Forward USB interrupt events to TinyUSB IRQ Handler
+//--------------------------------------------------------------------+
+void USB0_IRQHandler(void) {
+  tud_int_handler(0);
+}
+
+void board_init(void) {
+  // Enable IOCON clock
+  CLOCK_EnableClock(kCLOCK_Iocon);
+
+  // Enable GPIO0 clock
+  CLOCK_EnableClock(kCLOCK_Gpio0);
+
+  // Init 96 MHz clock
+  BootClockFROHF96M();
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+  // 1ms tick timer
+  SysTick_Config(SystemCoreClock / 1000);
+#elif CFG_TUSB_OS == OPT_OS_FREERTOS
+  // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
+  NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
+#endif
+
+  GPIO_PortInit(GPIO, LED_PORT);
+  GPIO_PortInit(GPIO, BUTTON_PORT);
+
+  // LED
+  gpio_pin_config_t const led_config = {kGPIO_DigitalOutput, 0};
+  GPIO_PinInit(GPIO, LED_PORT, LED_PIN, &led_config);
+  board_led_write(true);
+
+  // Button
+  gpio_pin_config_t const button_config = {kGPIO_DigitalInput, 0};
+  GPIO_PinInit(GPIO, BUTTON_PORT, BUTTON_PIN, &button_config);
+
+  // USB
+  const uint32_t port1_pin6_config = (
+      IOCON_PIO_FUNC7       | /* Pin is configured as USB0_VBUS */
+      IOCON_PIO_MODE_INACT  | /* No addition pin function */
+      IOCON_PIO_INV_DI      | /* Input function is not inverted */
+      IOCON_PIO_DIGITAL_EN  | /* Enables digital function */
+      IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
+      IOCON_PIO_OPENDRAIN_DI  /* Open drain is disabled */
+  );
+  IOCON_PinMuxSet(IOCON, 1, 6, port1_pin6_config); /* PORT1 PIN6 (coords: 26) is configured as USB0_VBUS */
+
+  POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*Turn on USB Phy */
+  CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); /* enable USB IP clock */
+}
+
+//--------------------------------------------------------------------+
+// Board porting API
+//--------------------------------------------------------------------+
+
+void board_led_write(bool state) {
+  GPIO_PinWrite(GPIO, LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON));
+}
+
+uint32_t board_button_read(void) {
+  // active low
+  return 1 - GPIO_PinRead(GPIO, BUTTON_PORT, BUTTON_PIN);
+}
+
+int board_uart_read(uint8_t* buf, int len) {
+  (void) buf;
+  (void) len;
+  return 0;
+}
+
+int board_uart_write(void const* buf, int len) {
+  (void) buf;
+  (void) len;
+  return 0;
+}
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+volatile uint32_t system_ticks = 0;
+
+void SysTick_Handler(void) {
+  system_ticks++;
+}
+
+uint32_t board_millis(void) {
+  return system_ticks;
+}
+#endif
+
+#ifndef __ICCARM__
+// Implement _start() since we use linker flag '-nostartfiles'.
+// Requires defined __STARTUP_CLEAR_BSS,
+extern int main(void);
+
+TU_ATTR_UNUSED void _start(void) {
+  // called by startup code
+  main();
+  while (1) {}
+}
+
+#ifdef __clang__
+void	_exit (int __status) {
+  while (1) {}
+}
+#endif
+
+#endif
diff --git a/hw/bsp/lpc51/family.cmake b/hw/bsp/lpc51/family.cmake
new file mode 100644
index 000000000..dd0ef6d1b
--- /dev/null
+++ b/hw/bsp/lpc51/family.cmake
@@ -0,0 +1,123 @@
+include_guard()
+
+set(SDK_DIR ${TOP}/hw/mcu/nxp/mcux-sdk)
+set(CMSIS_DIR ${TOP}/lib/CMSIS_5)
+
+# include board specific
+include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
+
+# toolchain set up
+set(CMAKE_SYSTEM_PROCESSOR cortex-m0plus CACHE INTERNAL "System Processor")
+set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
+
+set(FAMILY_MCUS LPC51 CACHE INTERNAL "")
+
+#------------------------------------
+# BOARD_TARGET
+#------------------------------------
+# only need to be built ONCE for all examples
+function(add_board_target BOARD_TARGET)
+  if (TARGET ${BOARD_TARGET})
+    return()
+  endif()
+
+  if (NOT DEFINED LD_FILE_GNU)
+    set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}_flash.ld)
+  endif ()
+  set(LD_FILE_Clang ${LD_FILE_GNU})
+
+  if (NOT DEFINED STARTUP_FILE_GNU)
+    set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S)
+  endif ()
+  set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
+
+  add_library(${BOARD_TARGET} STATIC
+    ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
+    # driver
+    ${SDK_DIR}/drivers/common/fsl_common_arm.c
+    ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c
+    ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c
+    ${SDK_DIR}/drivers/flexcomm/fsl_usart.c
+    # mcu
+    ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_VARIANT}.c
+    ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c
+    ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_power.c
+    ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c
+    )
+  target_include_directories(${BOARD_TARGET} PUBLIC
+    ${TOP}/lib/sct_neopixel
+    # driver
+    ${SDK_DIR}/drivers/common
+    ${SDK_DIR}/drivers/flexcomm
+    ${SDK_DIR}/drivers/lpc_iocon
+    ${SDK_DIR}/drivers/lpc_gpio
+    ${SDK_DIR}/drivers/lpuart
+    # mcu
+    ${SDK_DIR}/devices/${MCU_VARIANT}
+    ${SDK_DIR}/devices/${MCU_VARIANT}/drivers
+    ${CMSIS_DIR}/CMSIS/Core/Include
+    )
+  target_compile_definitions(${BOARD_TARGET} PUBLIC
+    CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\)
+    __STARTUP_CLEAR_BSS
+    )
+
+  update_board(${BOARD_TARGET})
+
+  if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+    target_link_options(${BOARD_TARGET} PUBLIC
+      "LINKER:--script=${LD_FILE_GNU}"
+      --specs=nosys.specs --specs=nano.specs
+      -nostartfiles
+      )
+  elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
+    target_link_options(${BOARD_TARGET} PUBLIC
+      "LINKER:--script=${LD_FILE_Clang}"
+      )
+  elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
+    target_link_options(${BOARD_TARGET} PUBLIC
+      "LINKER:--config=${LD_FILE_IAR}"
+      )
+  endif ()
+endfunction()
+
+
+#------------------------------------
+# Functions
+#------------------------------------
+function(family_configure_example TARGET RTOS)
+  family_configure_common(${TARGET} ${RTOS})
+
+  # Board target
+  add_board_target(board_${BOARD})
+
+  #---------- Port Specific ----------
+  # These files are built for each example since it depends on example's tusb_config.h
+  target_sources(${TARGET} PUBLIC
+    # BSP
+    ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
+    ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
+    )
+
+  target_include_directories(${TARGET} PUBLIC
+    # family, hw, board
+    ${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+    ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
+    ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
+    )
+
+  # Add TinyUSB target and port source
+  family_add_tinyusb(${TARGET} OPT_MCU_LPC51 ${RTOS})
+  target_sources(${TARGET}-tinyusb PUBLIC
+    ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
+    )
+  target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD})
+
+  # Link dependencies
+  target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb)
+
+  # Flashing
+  family_flash_jlink(${TARGET})
+  #family_flash_nxplink(${TARGET})
+  #family_flash_pyocd(${TARGET})
+endfunction()
diff --git a/hw/bsp/lpc51/family.mk b/hw/bsp/lpc51/family.mk
index c8ee29dbc..b41b5438e 100644
--- a/hw/bsp/lpc51/family.mk
+++ b/hw/bsp/lpc51/family.mk
@@ -1,19 +1,21 @@
 SDK_DIR = hw/mcu/nxp/mcux-sdk
-DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5
 
-MCU_DIR = $(SDK_DIR)/devices/$(MCU)
 include $(TOP)/$(BOARD_PATH)/board.mk
+MCU_DIR = $(SDK_DIR)/devices/$(MCU)
 CPU_CORE ?= cortex-m0plus
 
 CFLAGS += \
   -flto \
+  -D__STARTUP_CLEAR_BSS \
   -DCFG_TUSB_MCU=OPT_MCU_LPC51UXX \
   -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))'
 
 # mcu driver cause following warnings
 CFLAGS += -Wno-error=unused-parameter
 
-LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
+LDFLAGS_GCC += \
+  -nostartfiles \
+  --specs=nosys.specs --specs=nano.specs \
 
 # All source paths should be relative to the top level.
 LD_FILE = $(MCU_DIR)/gcc/$(MCU)_flash.ld
@@ -29,7 +31,8 @@ SRC_C += \
 	$(SDK_DIR)/drivers/flexcomm/fsl_usart.c
 
 INC += \
-	$(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
+  $(TOP)/$(BOARD_PATH) \
+  $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
 	$(TOP)/$(MCU_DIR) \
 	$(TOP)/$(MCU_DIR)/drivers \
 	$(TOP)/$(SDK_DIR)/drivers/common \
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 3ead20ee7..8d5527936 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -55,7 +55,8 @@
 #define OPT_MCU_LPC18XX             6 ///< NXP LPC18xx
 #define OPT_MCU_LPC40XX             7 ///< NXP LPC40xx
 #define OPT_MCU_LPC43XX             8 ///< NXP LPC43xx
-#define OPT_MCU_LPC51UXX            9 ///< NXP LPC51U6x
+#define OPT_MCU_LPC51               9 ///< NXP LPC51
+#define OPT_MCU_LPC51UXX            OPT_MCU_LPC51 ///< NXP LPC51
 #define OPT_MCU_LPC54              10 ///< NXP LPC54
 #define OPT_MCU_LPC55              11 ///< NXP LPC55
 // legacy naming