Initial support for lpc55s69

pull/714/head
Thomas Cook 2026-02-26 15:59:56 -05:00 committed by Daniele Lacamera
parent f123c4ff7e
commit 2af2e795cb
8 changed files with 577 additions and 1 deletions

36
arch.mk
View File

@ -1183,6 +1183,42 @@ ifeq ($(TARGET),lpc)
endif
endif
ifeq ($(TARGET),lpc55s69)
ifneq ($(TZEN),1)
LSCRIPT_IN=hal/$(TARGET)-ns.ld
endif
CFLAGS+=\
-I$(MCUXPRESSO_PROJECT_TEMPLATE) \
-I$(MCUXPRESSO_DRIVERS) \
-I$(MCUXPRESSO_DRIVERS)/drivers \
-I$(MCUXPRESSO_DRIVERS)/../periph \
-I$(MCUXPRESSO)/drivers \
-I$(MCUXPRESSO)/drivers/common \
-I$(MCUXPRESSO)/drivers/flexcomm \
-I$(MCUXPRESSO)/drivers/flexcomm/usart \
-I$(MCUXPRESSO)/drivers/iap1 \
-I$(MCUXPRESSO)/drivers/lpc_gpio \
-I$(MCUXPRESSO)/drivers/lpc_iocon \
-I$(MCUXPRESSO_CMSIS)/Include \
-I$(MCUXPRESSO_CMSIS)/Core/Include
CFLAGS+=-DCPU_$(MCUXPRESSO_CPU)
CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33 -U__ARM_FEATURE_DSP
LDFLAGS+=-mcpu=cortex-m33
OBJS+=\
$(MCUXPRESSO_PROJECT_TEMPLATE)/clock_config.o \
$(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \
$(MCUXPRESSO_DRIVERS)/drivers/fsl_power.o \
$(MCUXPRESSO)/drivers/common/fsl_common_arm.o \
$(MCUXPRESSO)/drivers/iap1/fsl_iap.o \
$(MCUXPRESSO)/drivers/lpc_gpio/fsl_gpio.o
ifeq ($(DEBUG_UART),1)
OBJS+=\
$(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o \
$(MCUXPRESSO)/drivers/flexcomm/fsl_flexcomm.o \
$(MCUXPRESSO)/drivers/flexcomm/usart/fsl_usart.o
endif
endif
ifeq ($(TARGET),psoc6)
CORTEX_M0=1
OBJS+=\

View File

@ -0,0 +1,40 @@
ARCH?=ARM
TZEN?=0
TARGET?=lpc55s69
SIGN?=ECC384
HASH?=SHA384
MCUXSDK?=1
MCUXPRESSO?=$(PWD)/../NXP/mcuxpresso-sdk/mcuxsdk
MCUXPRESSO_CMSIS?=$(PWD)/../NXP/CMSIS_5/CMSIS
MCUXPRESSO_CPU?=LPC55S69JBD100_cm33_core0
MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/LPC/LPC5500/LPC55S69
MCUXPRESSO_PROJECT_TEMPLATE?=$(MCUXPRESSO)/examples/_boards/lpcxpresso55s69/project_template
DEBUG?=0
DEBUG_UART?=1
VTOR?=1
CORTEX_M0?=0
CORTEX_M33?=1
NO_ASM?=0
NO_MPU=1
EXT_FLASH?=0
SPI_FLASH?=0
ALLOW_DOWNGRADE?=0
NVM_FLASH_WRITEONCE?=1
NO_ARM_ASM=1
WOLFBOOT_VERSION?=0
V?=0
SPMATH?=1
RAM_CODE?=1
DUALBANK_SWAP?=0
PKA?=1
FLASH_MULTI_SECTOR_ERASE?=1
# 512-byte pages erasable/writeable
WOLFBOOT_SECTOR_SIZE?=0x200
# Default configuration
# 32KB boot, 48KB partitions, 512 swap
WOLFBOOT_PARTITION_SIZE?=0xB000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xA000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x15000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x20000

View File

@ -21,6 +21,7 @@ This README describes configuration of supported targets.
* [NXP iMX-RT](#nxp-imx-rt)
* [NXP Kinetis](#nxp-kinetis)
* [NXP LPC54xxx](#nxp-lpc54xxx)
* [NXP LPC55S69](#lpc55s69)
* [NXP LS1028A](#nxp-ls1028a)
* [NXP MCXA153](#nxp-mcxa153)
* [NXP MCXW716](#nxp-mcxw716)
@ -1948,7 +1949,7 @@ Example configurations for this target are provided in:
1. Download `aarch64-none-elf-` toolchain.
2. Copy the example `nxp-ls1028a.cofig` file to root directory and rename to `.config`
2. Copy the example `nxp-ls1028a.config` file to root directory and rename to `.config`
3. Build keytools and wolfboot

55
hal/lpc55s69-ns.ld 100644
View File

@ -0,0 +1,55 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = @WOLFBOOT_PARTITION_BOOT_ADDRESS@
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
}
SECTIONS
{
.text :
{
_start_text = .;
KEEP(*(.isr_vector))
. = 0x200;
*(.keystore*)
*(.text*)
*(.rodata*)
*(.init*)
*(.fini*)
. = ALIGN(4);
_end_text = .;
} > FLASH
.edidx :
{
. = ALIGN(4);
*(.ARM.exidx*)
} > FLASH
_stored_data = .;
.data : AT (_stored_data)
{
_start_data = .;
KEEP(*(.data*))
. = ALIGN(4);
KEEP(*(.ramcode))
. = ALIGN(4);
_end_data = .;
} > RAM
.bss (NOLOAD) :
{
_start_bss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_end_bss = .;
__bss_end__ = .;
_end = .;
} > RAM
. = ALIGN(4);
}
END_STACK = ORIGIN(RAM) + LENGTH(RAM);

258
hal/lpc55s69.c 100644
View File

@ -0,0 +1,258 @@
/* lpc55s69.c
*
* Copyright (C) 2025 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdint.h>
#include <string.h>
#include <target.h>
#include "fsl_common.h"
#include "image.h"
#include "clock_config.h"
#include "fsl_clock.h"
#include "fsl_iap.h"
#include "fsl_iocon.h"
#include "fsl_reset.h"
#include "fsl_usart.h"
#include "loader.h"
#ifdef TZEN
#include "hal/armv8m_tz.h"
#endif
static flash_config_t pflash;
static const uint32_t pflash_page_size = 512U;
uint32_t SystemCoreClock; /* set in clock_config.c */
#ifdef TZEN
static void hal_sau_init(void)
{
/* Non-secure callable area */
sau_init_region(0, WOLFBOOT_NSC_ADDRESS,
WOLFBOOT_NSC_ADDRESS + WOLFBOOT_NSC_SIZE - 1, 1);
/* Non-secure: application flash area (boot partition) */
sau_init_region(1, WOLFBOOT_PARTITION_BOOT_ADDRESS,
WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE - 1,
0);
/* Non-secure RAM */
sau_init_region(2, 0x20020000, 0x20025FFF, 0);
/* Peripherals */
sau_init_region(3, 0x40000000, 0x4005FFFF, 0);
sau_init_region(4, 0x40080000, 0x400DFFFF, 0);
sau_init_region(5, 0x40100000, 0x4013FFFF, 0);
/* Enable SAU */
SAU_CTRL = SAU_INIT_CTRL_ENABLE;
/* Enable securefault handler */
SCB_SHCSR |= SCB_SHCSR_SECUREFAULT_EN;
}
static void periph_unsecure(void)
{
// CLOCK_EnableClock(kCLOCK_Gpio0);
// CLOCK_EnableClock(kCLOCK_Gpio1);
// CLOCK_EnableClock(kCLOCK_Port0);
// CLOCK_EnableClock(kCLOCK_Port1);
// GPIO_EnablePinControlNonSecure(GPIO0, (1UL << 10) | (1UL << 27));
// GPIO_EnablePinControlNonSecure(GPIO1, (1UL << 2) | (1UL << 8) | (1UL << 9));
}
#endif
void hal_init(void)
{
#ifdef __WOLFBOOT
/* lpc55s69 must run < 100 MHz for flash write/erase to work */
BOARD_BootClockFROHF96M();
// BOARD_BootClockPLL150M();
#ifdef DEBUG_UART
uart_init();
#endif
#endif
uart_write("lpc55s69 init\n", 14);
#if defined(__WOLFBOOT) || !defined(TZEN)
memset(&pflash, 0, sizeof(pflash));
FLASH_Init(&pflash);
// FLASH_GetProperty(&pflash, kFLASH_PropertyPflashSectorSize,
// &pflash_sector_size);
#endif
#if defined(TZEN) && !defined(NONSECURE_APP)
hal_sau_init();
#endif
}
#ifdef __WOLFBOOT
/* Assert hook needed by SDK assert() macro. */
void __assert_func(const char *a, int b, const char *c, const char *d)
{
(void)a;
(void)b;
(void)c;
(void)d;
while (1) {
}
}
void hal_prepare_boot(void)
{
#ifdef TZEN
periph_unsecure();
#endif
}
#endif
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
{
if (
address % pflash_page_size == 0 &&
len % pflash_page_size == 0 &&
FLASH_Program(&pflash, address, data, len) == kStatus_FLASH_Success
)
{
return 0;
}
return -1;
}
void RAMFUNCTION hal_flash_unlock(void)
{
}
void RAMFUNCTION hal_flash_lock(void)
{
}
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
{
if (
address % pflash_page_size == 0 &&
len % pflash_page_size == 0 &&
FLASH_Erase(&pflash, address, len, kFLASH_ApiEraseKey)
== kStatus_FLASH_Success &&
FLASH_VerifyErase(&pflash, address, len) == kStatus_FLASH_Success
)
{
return 0;
}
return -1;
}
#ifdef WOLFCRYPT_SECURE_MODE
/* These functions are stubs for now, because the MCUXpresso SDK doesn't
* implement drivers for the MCXN's TRNG. */
void hal_trng_init(void)
{
}
void hal_trng_fini(void)
{
}
int hal_trng_get_entropy(unsigned char *out, unsigned int len)
{
(void)out;
(void)len;
return -1;
}
#endif
#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */
#define IOCON_PIO_FUNC1 0x01u /*!<@brief Selects pin function 1 */
#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */
#define IOCON_PIO_MODE_INACT 0x00u /*!<@brief No addition pin function */
#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */
#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */
void uart_init(void)
{
CLOCK_EnableClock(kCLOCK_Iocon);
const uint32_t port0_pin29_config = (/* Pin is configured as FC0_RXD_SDA_MOSI_DATA */
IOCON_PIO_FUNC1 |
/* No addition pin function */
IOCON_PIO_MODE_INACT |
/* Standard mode, output slew rate control is enabled */
IOCON_PIO_SLEW_STANDARD |
/* Input function is not inverted */
IOCON_PIO_INV_DI |
/* Enables digital function */
IOCON_PIO_DIGITAL_EN |
/* Open drain is disabled */
IOCON_PIO_OPENDRAIN_DI);
/* PORT0 PIN29 (coords: 92) is configured as FC0_RXD_SDA_MOSI_DATA */
IOCON_PinMuxSet(IOCON, 0U, 29U, port0_pin29_config);
const uint32_t port0_pin30_config = (/* Pin is configured as FC0_TXD_SCL_MISO_WS */
IOCON_PIO_FUNC1 |
/* No addition pin function */
IOCON_PIO_MODE_INACT |
/* Standard mode, output slew rate control is enabled */
IOCON_PIO_SLEW_STANDARD |
/* Input function is not inverted */
IOCON_PIO_INV_DI |
/* Enables digital function */
IOCON_PIO_DIGITAL_EN |
/* Open drain is disabled */
IOCON_PIO_OPENDRAIN_DI);
/* PORT0 PIN30 (coords: 94) is configured as FC0_TXD_SCL_MISO_WS */
IOCON_PinMuxSet(IOCON, 0U, 30U, port0_pin30_config);
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0);
RESET_ClearPeripheralReset(kFC0_RST_SHIFT_RSTn);
usart_config_t config;
USART_GetDefaultConfig(&config);
config.baudRate_Bps = 115200U;
config.enableTx = true;
config.enableRx = true;
(void)USART_Init(USART0, &config, 12000000U);
}
void uart_write(const char *buf, unsigned int sz)
{
const char *line;
unsigned int line_sz;
while (sz > 0)
{
line = memchr(buf, '\n', sz);
if (line == NULL) {
(void)USART_WriteBlocking(USART0, (const uint8_t *)buf, sz);
break;
}
line_sz = (unsigned int)(line - buf);
if (line_sz > sz - 1U) {
line_sz = sz - 1U;
}
(void)USART_WriteBlocking(USART0, (const uint8_t *)buf, line_sz);
(void)USART_WriteBlocking(USART0, (const uint8_t *)"\r\n", 2U);
buf = line + 1;
sz -= line_sz + 1U;
}
}

View File

@ -0,0 +1,58 @@
MEMORY
{
FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
}
SECTIONS
{
.text :
{
_start_text = .;
KEEP(*(.isr_vector))
*(.init)
*(.fini)
*(.text*)
KEEP(*(.rodata*))
. = ALIGN(4);
_end_text = .;
} > FLASH
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > FLASH
_stored_data = .;
.data : AT (_stored_data)
{
_start_data = .;
KEEP(*(.data*))
. = ALIGN(4);
KEEP(*(.ramcode))
. = ALIGN(4);
_end_data = .;
} > RAM
.bss :
{
_start_bss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_end_bss = .;
_end = .;
} > RAM
}
_wolfboot_partition_boot_address = @WOLFBOOT_PARTITION_BOOT_ADDRESS@;
_wolfboot_partition_size = @WOLFBOOT_PARTITION_SIZE@;
_wolfboot_partition_update_address = @WOLFBOOT_PARTITION_UPDATE_ADDRESS@;
_wolfboot_partition_swap_address = @WOLFBOOT_PARTITION_SWAP_ADDRESS@;
PROVIDE(_start_heap = _end);
PROVIDE(end = _end);
PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM));

View File

@ -643,6 +643,27 @@ ifeq ($(TARGET),mcxn)
endif
endif
ifeq ($(TARGET),lpc55s69)
ifeq ($(TZEN),1)
LSCRIPT_TEMPLATE=ARM-lpc55s69-ns.ld
CFLAGS:=$(filter-out -mcmse, $(CFLAGS))
else
LSCRIPT_TEMPLATE=ARM-lpc55s69.ld
endif
APP_OBJS+=\
$(MCUXPRESSO_PROJECT_TEMPLATE)/clock_config.o \
$(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \
$(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o \
$(MCUXPRESSO)/drivers/common/fsl_common_arm.o \
$(MCUXPRESSO)/drivers/flexcomm/fsl_flexcomm.o \
$(MCUXPRESSO)/drivers/flexcomm/usart/fsl_usart.o \
$(MCUXPRESSO)/drivers/iap1/fsl_iap.o \
$(MCUXPRESSO)/drivers/lpc_gpio/fsl_gpio.o
ifeq (,$(findstring nosys.specs,$(LDFLAGS)))
LDFLAGS+=--specs=nosys.specs
endif
endif
ifeq ($(TARGET),imx_rt)
LDFLAGS+=\
-mcpu=cortex-m7 -Wall --specs=nosys.specs -fno-common -ffunction-sections -fdata-sections \

View File

@ -0,0 +1,107 @@
/* app_lpc55s69.c
*
* Copyright (C) 2025 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdint.h>
#include "fsl_clock.h"
#include "fsl_gpio.h"
#include "fsl_iocon.h"
#include "target.h"
#include "wolfboot/wolfboot.h"
#include "printf.h"
#define RED_LED 6
#define GREEN_LED 7
#define BLUE_LED 4
extern void hal_init(void);
#define IOCON_PIO_FUNC0 0x00u /*!<@brief Selects pin function 0 */
#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */
#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */
#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */
#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */
#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */
static void leds_init(void)
{
CLOCK_EnableClock(kCLOCK_Iocon);
CLOCK_EnableClock(kCLOCK_Gpio1);
const gpio_pin_config_t LED_GPIOPIN_config = {
.pinDirection = kGPIO_DigitalOutput,
.outputLogic = 1U /* off */
};
GPIO_PinInit(GPIO, 1, 6, &LED_GPIOPIN_config); /* red off */
GPIO_PinInit(GPIO, 1, 7, &LED_GPIOPIN_config); /* green off */
GPIO_PinInit(GPIO, 1, 4, &LED_GPIOPIN_config); /* blue off */
const uint32_t LED_PINMUX_CONFIG = (/* Pin is configured as PIO */
IOCON_PIO_FUNC0 |
/* Selects pull-up function */
IOCON_PIO_MODE_PULLUP |
/* Standard mode, output slew rate control is enabled */
IOCON_PIO_SLEW_STANDARD |
/* Input function is not inverted */
IOCON_PIO_INV_DI |
/* Enables digital function */
IOCON_PIO_DIGITAL_EN |
/* Open drain is disabled */
IOCON_PIO_OPENDRAIN_DI);
IOCON_PinMuxSet(IOCON, 1, 6, LED_PINMUX_CONFIG); /* red */
IOCON_PinMuxSet(IOCON, 1, 7, LED_PINMUX_CONFIG); /* green */
IOCON_PinMuxSet(IOCON, 1, 4, LED_PINMUX_CONFIG); /* blue */
}
void main(void)
{
uint32_t boot_ver;
hal_init();
leds_init();
#ifdef WOLFCRYPT_SECURE_MODE
boot_ver = wolfBoot_nsc_current_firmware_version();
#else
boot_ver = wolfBoot_current_firmware_version();
#endif
wolfBoot_printf("Hello from firmware version %d\n", boot_ver);
if (boot_ver == 1) {
/* blue on */
GPIO_PinWrite(GPIO, 1, BLUE_LED, 0);
}
else {
/* green on */
GPIO_PinWrite(GPIO, 1, GREEN_LED, 0);
#ifdef WOLFCRYPT_SECURE_MODE
wolfBoot_nsc_success();
#else
wolfBoot_success();
#endif
}
while (1) {
__asm__ volatile ("wfi");
}
}