diff --git a/arch.mk b/arch.mk index 22250773..84131fd9 100644 --- a/arch.mk +++ b/arch.mk @@ -335,6 +335,36 @@ ifeq ($(TARGET),kinetis) endif endif +ifeq ($(TARGET),mcxa) + CORTEX_M33=1 + CFLAGS+=\ + -I$(MCUXPRESSO_DRIVERS) \ + -I$(MCUXPRESSO_DRIVERS)/drivers \ + -I$(MCUXPRESSO)/drivers \ + -I$(MCUXPRESSO)/drivers/common \ + -I$(MCUXPRESSO_CMSIS)/Include \ + -I$(MCUXPRESSO_CMSIS)/Core/Include + CFLAGS+=\ + -DCPU_$(MCUXPRESSO_CPU) -DDEBUG_CONSOLE_ASSERT_DISABLE=1 -DNVM_FLASH_WRITEONCE=1 + CFLAGS+=-Wno-old-style-declaration + CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33 -U__ARM_FEATURE_DSP + LDFLAGS+=-mcpu=cortex-m33 + OBJS+=\ + $(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \ + $(MCUXPRESSO_DRIVERS)/drivers/fsl_spc.o + + ifeq ($(MCUXSDK),1) + CFLAGS+=\ + -I$(MCUXPRESSO)/drivers/flash \ + -I$(MCUXPRESSO)/drivers/sysmpu \ + -I$(MCUXPRESSO)/drivers/ltc \ + -I$(MCUXPRESSO)/drivers/port \ + -I$(MCUXPRESSO)/drivers/gpio + + else + endif +endif + ifeq ($(TARGET),imx_rt) CFLAGS+=\ -I$(MCUXPRESSO_DRIVERS) \ diff --git a/config/examples/mcxa.config b/config/examples/mcxa.config new file mode 100644 index 00000000..d13fc5da --- /dev/null +++ b/config/examples/mcxa.config @@ -0,0 +1,28 @@ +ARCH?=ARM +TARGET?=mcxa +SIGN?=ECC256 +HASH?=SHA256 +MCUXSDK?=0 +MCUXPRESSO?=$(PWD)/../NXP/MCXA153 +MCUXPRESSO_CMSIS?=$(MCUXPRESSO)/CMSIS +MCUXPRESSO_CPU?=MCXA153VLH +MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/MCXA153 +DEBUG?=0 +VTOR?=1 +CORTEX_M0?=0 +NO_ASM?=1 +EXT_FLASH?=0 +SPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=1 +WOLFBOOT_VERSION?=0 +V?=0 +SPMATH?=1 +RAM_CODE?=1 +DUALBANK_SWAP?=0 +PKA?=1 +WOLFBOOT_PARTITION_SIZE?=0xB000 +WOLFBOOT_SECTOR_SIZE?=0x2000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x8000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x13000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x1E000 diff --git a/docs/Targets.md b/docs/Targets.md index 0185f87e..d687d6c0 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -14,6 +14,7 @@ This README describes configuration of supported targets. * [NXP P1021 PPC](#nxp-qoriq-p1021-ppc) * [NXP T1024 PPC](#nxp-qoriq-t1024-ppc) * [NXP T2080 PPC](#nxp-qoriq-t2080-ppc) +* [NXP MCXA153](#nxp-mcxa153) * [SiFive HiFive1 RISC-V](#sifive-hifive1-risc-v) * [STM32F4](#stm32f4) * [STM32F7](#stm32f7) @@ -1710,6 +1711,35 @@ Executing Initialization File: /opt/Freescale/CodeWarrior_PA_10.5.1/PA/PA_Suppor thread break: Stopped, 0x0, 0x0, cpuPowerPCBig, Connected (state, tid, pid, cpu, target) ``` +## NXP MCXA153 + +NXP MCXA153 is a Cortex-M33 microcontroller running at 96MHz. +The support has been tested using FRDM-MCXA153 with the onboard MCU-Link +configured in JLink mode. + +### Configuring and compiling + +Copy the example configuration file: + +`cp config/examples/mcxa.config .config` + +Compile via: + +`make` + +### Loading the firmware + +Use JLinkExe tool to upload the initial firmware: + +`JLinkExe -if swd -Device MCXA153` + +At the Jlink prompt, type: + +``` +J-Link>loadbin factory.bin 0 +``` + + ## TI Hercules TMS570LC435 diff --git a/hal/mcxa.c b/hal/mcxa.c new file mode 100644 index 00000000..22f117e0 --- /dev/null +++ b/hal/mcxa.c @@ -0,0 +1,172 @@ +/* mcxa.c + * + * Copyright (C) 2021 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 2 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 +#include +#include "image.h" +/* FSL includes */ +#include "fsl_common.h" + +/* Clock + RAM voltage settings */ +#include "fsl_clock.h" +#include "fsl_spc.h" + +/* Flash driver */ +#include "fsl_romapi.h" + +#define BOARD_BOOTCLOCKFRO96M_CORE_CLOCK 96000000U /*!< Core clock frequency: 96000000Hz */ + +static flash_config_t pflash; +//static ftfx_cache_config_t pcache; +static int flash_init = 0; + +#ifdef __WOLFBOOT +/* Assert hook needed by Kinetis SDK */ +void __assert_func(const char *a, int b, const char *c, const char *d) +{ + while(1) + ; +} + +/* The following clock setting function is autogenerated by the MCUXpresso IDE */ +void BOARD_BootClockFRO96M(void) +{ + uint32_t coreFreq; + spc_active_mode_core_ldo_option_t ldoOption; + spc_sram_voltage_config_t sramOption; + + /* Get the CPU Core frequency */ + coreFreq = CLOCK_GetCoreSysClkFreq(); + + /* The flow of increasing voltage and frequency */ + if (coreFreq <= BOARD_BOOTCLOCKFRO96M_CORE_CLOCK) { + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_NormalVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x2U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P1V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + } + + CLOCK_SetupFROHFClocking(96000000U); /*!< Enable FRO HF(96MHz) output */ + + CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ + + CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /* !< Switch MAIN_CLK to FRO_HF */ + + /* The flow of decreasing voltage and frequency */ + if (coreFreq > BOARD_BOOTCLOCKFRO96M_CORE_CLOCK) { + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x2U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P1V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_NormalVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + } + + /*!< Set up clock selectors - Attach clocks to the peripheries */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ +} + + +void hal_init(void) +{ + /* Clock setting */ + BOARD_BootClockFRO96M(); + + /* Clear the FLASH configuration structure */ + memset(&pflash, 0, sizeof(pflash)); + /* FLASH driver init */ + FLASH_Init(&pflash); +} + +void hal_prepare_boot(void) +{ +} + + +#endif + +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + int w = 0; + int ret; + const uint8_t empty_qword[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + while (len > 0) { + if ((len < 16) || address & 0x0F) { + uint8_t aligned_qword[16]; + uint32_t address_align = address - (address & 0x0F); + uint32_t start_off = address - address_align; + int i; + memcpy(aligned_qword, (void*)address_align, 16); + for (i = start_off; ((i < 16) && (i < len + (int)start_off)); i++) + aligned_qword[i] = data[w++]; + if (memcmp(aligned_qword, empty_qword, 16) != 0) { + ret = FLASH_ProgramPhrase(&pflash, address_align, aligned_qword, 16); + if (ret != kStatus_Success) + return -1; + } + address += i; + len -= i; + } else { + uint32_t len_align = len - (len & 0x0F); + ret = FLASH_ProgramPhrase(&pflash, address, (uint8_t*)data + w, len_align); + if (ret != kStatus_Success) + return -1; + len -= len_align; + address += len_align; + } + } + return 0; +} + +void RAMFUNCTION hal_flash_unlock(void) +{ +} + +void RAMFUNCTION hal_flash_lock(void) +{ +} + + +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) +{ + while ((address % 4) != 0) + address --; + if (FLASH_EraseSector(&pflash, address, len, kFLASH_ApiEraseKey) != kStatus_Success) + return -1; + return 0; +} + + diff --git a/hal/mcxa.ld b/hal/mcxa.ld new file mode 100644 index 00000000..0de30f32 --- /dev/null +++ b/hal/mcxa.ld @@ -0,0 +1,54 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = @BOOTLOADER_PARTITION_SIZE@ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 24K +} + +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); + _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); diff --git a/test-app/ARM-mcxa.ld b/test-app/ARM-mcxa.ld new file mode 100644 index 00000000..a4911d2f --- /dev/null +++ b/test-app/ARM-mcxa.ld @@ -0,0 +1,57 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 24K +} + +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_stack = ORIGIN(RAM) + LENGTH(RAM)); diff --git a/test-app/Makefile b/test-app/Makefile index 96e5e7a1..feb962e7 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -222,6 +222,13 @@ ifeq ($(TARGET),kinetis) endif endif +ifeq ($(TARGET),mcxa) + LSCRIPT_TEMPLATE=ARM-mcxa.ld + APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o + APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o + APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_gpio.o +endif + ifeq ($(TARGET),imx_rt) LDFLAGS+=\ -mcpu=cortex-m7 -Wall --specs=nosys.specs -fno-common -ffunction-sections -fdata-sections \ diff --git a/test-app/app_mcxa.c b/test-app/app_mcxa.c new file mode 100644 index 00000000..6509588b --- /dev/null +++ b/test-app/app_mcxa.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include "fsl_common.h" +#include "fsl_port.h" +#include "fsl_gpio.h" +#include "fsl_clock.h" +#include "wolfboot/wolfboot.h" + + +#define BOARD_LED_GPIO_PORT PORT3 +#define BOARD_LED_GPIO GPIO3 +#define BOARD_LED_GPIO_PIN 12U + + +void gpio_init(void) +{ + /* Write to GPIO3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GateGPIO3); + /* Write to PORT3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT3); + /* GPIO3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); + /* PORT3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); + + gpio_pin_config_t LED_RED_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 0U + }; + /* Initialize GPIO functionality on pin PIO3_12 (pin 38) */ + GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, &LED_RED_config); + + const port_pin_config_t LED_RED = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as P3_12 */ + kPORT_MuxAlt0, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_12 (pin 38) is configured as P3_12 */ + PORT_SetPinConfig(BOARD_LED_GPIO_PORT, BOARD_LED_GPIO_PIN, &LED_RED); +} + + +void main(void) { + int i = 0; + gpio_pin_config_t led_config = { + kGPIO_DigitalOutput, 0, + }; + /* Write to GPIO3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GateGPIO3); + /* Write to PORT3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT3); + /* GPIO3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); + /* PORT3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); + gpio_init(); + + GPIO_PinWrite(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, 0); + + while(1) + __WFI(); +}