From 081b04f05ee3fa2a9f2476fe77bd268621908d24 Mon Sep 17 00:00:00 2001 From: jturnsek Date: Fri, 24 Feb 2023 07:12:28 +0100 Subject: [PATCH] iMXRT MCUboot support --- arch/arm/src/imxrt/Kconfig | 116 +++ arch/arm/src/imxrt/Make.defs | 3 + arch/arm/src/imxrt/imxrt106x_flash.c | 789 ++++++++++++++++++ arch/arm/src/imxrt/imxrt_flash.c | 35 + .../configs/mcuboot-app/defconfig | 85 ++ .../configs/mcuboot-loader/defconfig | 59 ++ .../arm/imxrt/imxrt1064-evk/scripts/Make.defs | 16 +- .../scripts/flash-mcuboot-app.ld | 119 +++ .../scripts/flash-mcuboot-loader.ld | 139 +++ boards/arm/imxrt/imxrt1064-evk/src/Makefile | 12 + .../imxrt/imxrt1064-evk/src/imxrt1064-evk.h | 15 + .../imxrt1064-evk/src/imxrt_boot_image.c | 180 ++++ .../imxrt/imxrt1064-evk/src/imxrt_bringup.c | 10 + .../imxrt/imxrt1064-evk/src/imxrt_progmem.c | 255 ++++++ .../arm/imxrt/imxrt1064-evk/src/imxrt_reset.c | 62 ++ 15 files changed, 1891 insertions(+), 4 deletions(-) create mode 100644 arch/arm/src/imxrt/imxrt106x_flash.c create mode 100644 arch/arm/src/imxrt/imxrt_flash.c create mode 100644 boards/arm/imxrt/imxrt1064-evk/configs/mcuboot-app/defconfig create mode 100644 boards/arm/imxrt/imxrt1064-evk/configs/mcuboot-loader/defconfig create mode 100644 boards/arm/imxrt/imxrt1064-evk/scripts/flash-mcuboot-app.ld create mode 100644 boards/arm/imxrt/imxrt1064-evk/scripts/flash-mcuboot-loader.ld create mode 100644 boards/arm/imxrt/imxrt1064-evk/src/imxrt_boot_image.c create mode 100644 boards/arm/imxrt/imxrt1064-evk/src/imxrt_progmem.c create mode 100644 boards/arm/imxrt/imxrt1064-evk/src/imxrt_reset.c diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig index 5dc6c436cb1..296732fff56 100644 --- a/arch/arm/src/imxrt/Kconfig +++ b/arch/arm/src/imxrt/Kconfig @@ -151,6 +151,47 @@ config ARCH_FAMILY_IMXRT106x select ARMV7M_HAVE_DTCM select IMXRT_HIGHSPEED_GPIO +config IMXRT_HAVE_OTA_PARTITION + bool + default n + +config IMXRT_PROGMEM + bool "Flash progmem support" + default n + select ARCH_HAVE_PROGMEM + ---help--- + Add progmem support, start block and end block options are provided to + obtain an uniform flash memory mapping. + +menu "Application Image Configuration" +choice + prompt "Application Image Format" + default IMXRT_APP_FORMAT_LEGACY + ---help--- + Depending on the chosen 2nd stage bootloader, the application may + be required to be perform a specific startup routine. Furthermore, + the image binary must be formatted according to the definition from + the 2nd stage bootloader. + +config IMXRT_APP_FORMAT_LEGACY + bool "Legacy format" + ---help--- + This is the legacy application image format. + +config IMXRT_APP_FORMAT_MCUBOOT + bool "MCUboot-bootable format" + select IMXRT_HAVE_OTA_PARTITION + depends on EXPERIMENTAL + ---help--- + The MCUboot support of loading the firmware images. + +comment "MCUboot support depends on CONFIG_EXPERIMENTAL" + depends on !EXPERIMENTAL + +endchoice # Application Image Format + +endmenu # Application Image Configuration + # Peripheral support config IMXRT_USDHC @@ -2781,4 +2822,79 @@ config IMXRT_USBDEV_REGDEBUG endmenu # USB device controller driver (DCD) options endif # IMXRT_USBDEV +menu "Progmem MTD configuration" + +if IMXRT_PROGMEM + +comment "Progmem instance support" + +config IMXRT_PROGMEM_FLEXSPI_INSTANCE + int "FlexSPI instance number (0 or 1)" + default 1 + ---help--- + FlexSPI instance number. Base address 0x60000000 is used for instance 0 + and 0x70000000 for instance 1. Other values are not supported. + +endif #IMXRT_PROGMEM + +if IMXRT_HAVE_OTA_PARTITION + +comment "Application Image OTA Update support" + +config IMXRT_PROGMEM_OTA_PARTITION + bool "MTD driver" + default n + select BCH + select MTD + select MTD_BYTE_WRITE + select MTD_PARTITION + select MTD_PROGMEM + select IMXRT_PROGMEM + ---help--- + Initialize an MTD driver for the Flash, which will + add an entry at /dev for application access from userspace. + +if IMXRT_PROGMEM_OTA_PARTITION +config IMXRT_MCUBOOT_HEADER_SIZE + hex + default 0x200 + depends on IMXRT_APP_FORMAT_MCUBOOT + +config IMXRT_OTA_PRIMARY_SLOT_DEVPATH + string "Application image primary slot device path" + default "/dev/ota0" + +config IMXRT_OTA_SECONDARY_SLOT_DEVPATH + string "Application image secondary slot device path" + default "/dev/ota1" + +config IMXRT_OTA_SCRATCH_DEVPATH + string "Scratch partition device path" + default "/dev/otascratch" + +config IMXRT_OTA_PRIMARY_SLOT_OFFSET + hex "MCUboot application image primary slot offset" + default "0x40000" + +config IMXRT_OTA_SECONDARY_SLOT_OFFSET + hex "MCUboot application image secondary slot offset" + default "0x200000" + +config IMXRT_OTA_SCRATCH_OFFSET + hex "MCUboot scratch partition offset" + default "0x3c0000" + +config IMXRT_OTA_SLOT_SIZE + hex "MCUboot application image slot size (in bytes)" + default "0x1c0000" + +config IMXRT_OTA_SCRATCH_SIZE + hex "MCUboot scratch partition size (in bytes)" + default "0x40000" + +endif #IMXRT_PROGMEM_OTA_PARTITION +endif #IMXRT_HAVE_OTA_PARTITION + +endmenu # Progmem configuration + endif # ARCH_CHIP_IMXRT diff --git a/arch/arm/src/imxrt/Make.defs b/arch/arm/src/imxrt/Make.defs index f67aa27b9ce..bfbd4776ac3 100644 --- a/arch/arm/src/imxrt/Make.defs +++ b/arch/arm/src/imxrt/Make.defs @@ -25,6 +25,9 @@ include armv7-m/Make.defs # Required i.MX RT files CHIP_CSRCS = imxrt_allocateheap.c imxrt_start.c imxrt_clockconfig.c +ifeq ($(CONFIG_IMXRT_PROGMEM),y) +CHIP_CSRCS += imxrt_flash.c +endif CHIP_CSRCS += imxrt_periphclks.c imxrt_irq.c imxrt_clrpend.c imxrt_gpio.c CHIP_CSRCS += imxrt_daisy.c imxrt_wdog.c imxrt_iomuxc.c imxrt_serial.c CHIP_CSRCS += imxrt_xbar.c imxrt_ocotp.c imxrt_lowputc.c diff --git a/arch/arm/src/imxrt/imxrt106x_flash.c b/arch/arm/src/imxrt/imxrt106x_flash.c new file mode 100644 index 00000000000..ef9b5ed6153 --- /dev/null +++ b/arch/arm/src/imxrt/imxrt106x_flash.c @@ -0,0 +1,789 @@ +/**************************************************************************** + * arch/arm/src/imxrt/imxrt106x_flash.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* Provides standard flash access functions, to be used by the flash mtd + * driver. The interface is defined in the include/nuttx/progmem.h + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "barriers.h" + +#include "hardware/rt106x/imxrt106x_memorymap.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if CONFIG_IMXRT_PROGMEM_FLEXSPI_INSTANCE == 0 +#define FLEXSPI_INSTANCE (0) +#else +#define FLEXSPI_INSTANCE (1) +#endif + +#define FLASH_PAGE_SIZE (256UL) +#define FLASH_SECTOR_SIZE (4096UL) +#define FLASH_ERASEDVALUE (0xffu) +#define FLASH_ERASEDVALUE_DW (0xffffffffu) +#define PROGMEM_NBLOCKS (1024UL) +#define FLASH_NPAGES ((4UL * 1024UL * 1024UL) / FLASH_PAGE_SIZE) + +#define FLEXSPI_CFG_BLK_TAG (0x42464346UL) +#define FLEXSPI_CFG_BLK_VERSION (0x56010400UL) +#define FLEXSPI_CFG_BLK_SIZE (512) + +#define CMD_SDR 0x01 +#define CMD_DDR 0x21 +#define RADDR_SDR 0x02 +#define RADDR_DDR 0x22 +#define CADDR_SDR 0x03 +#define CADDR_DDR 0x23 +#define MODE1_SDR 0x04 +#define MODE1_DDR 0x24 +#define MODE2_SDR 0x05 +#define MODE2_DDR 0x25 +#define MODE4_SDR 0x06 +#define MODE4_DDR 0x26 +#define MODE8_SDR 0x07 +#define MODE8_DDR 0x27 +#define WRITE_SDR 0x08 +#define WRITE_DDR 0x28 +#define READ_SDR 0x09 +#define READ_DDR 0x29 +#define LEARN_SDR 0x0a +#define LEARN_DDR 0x2a +#define DATSZ_SDR 0x0b +#define DATSZ_DDR 0x2b +#define DUMMY_SDR 0x0c +#define DUMMY_DDR 0x2c +#define DUMMY_RWDS_SDR 0x0d +#define DUMMY_RWDS_DDR 0x2d +#define JMP_ON_CS 0x1f +#define STOP 0 + +#define FLEXSPI_1PAD 0 +#define FLEXSPI_2PAD 1 +#define FLEXSPI_4PAD 2 +#define FLEXSPI_8PAD 3 + +#define FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ + (FLEXSPI_LUT_OPERAND0(op0) | \ + FLEXSPI_LUT_NUM_PADS0(pad0) | \ + FLEXSPI_LUT_OPCODE0(cmd0) | \ + FLEXSPI_LUT_OPERAND1(op1) | \ + FLEXSPI_LUT_NUM_PADS1(pad1) | \ + FLEXSPI_LUT_OPCODE1(cmd1)) + +typedef enum +{ + FLEXSPI_SERIAL_CLK_NO_CHANGE = 0, + FLEXSPI_SERIAL_CLK_30MHz = 1, + FLEXSPI_SERIAL_CLK_50MHz = 2, + FLEXSPI_SERIAL_CLK_60MHz = 3, + FLEXSPI_SERIAL_CLK_75MHz = 4, + FLEXSPI_SERIAL_CLK_80MHz = 5, + FLEXSPI_SERIAL_CLK_100MHz = 6, + FLEXSPI_SERIAL_CLK_120MHz = 7, + FLEXSPI_SERIAL_CLK_133MHz = 8, + FLEXSPI_SERIAL_CLK_166MHz = 9, +} flexspi_serial_clk_freq_t; + +enum +{ + FLEXSPI_CLK_SDR, + FLEXSPI_CLK_DDR, +}; + +typedef enum +{ + FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_INTERNALLY = 0, + FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_FROM_DQS_PAD = 1, + FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_FROM_SCK_PAD = 2, + FLEXSPI_READ_SAMPLE_CLK_EXTERNAL_INPUT_FROM_DQS_PAD = 3, +} flexspi_read_sample_clk_t; + +enum +{ + FLEXSPI_MISC_OFFSET_DIFF_CLK_ENABLE = 0, + FLEXSPI_MISC_OFFSET_CK2_ENABLE = 1, + FLEXSPI_MISC_OFFSET_PARALLEL_ENABLE = 2, + FLEXSPI_MISC_OFFSET_WORD_ADDRESSABLE_ENABLE = 3, + FLEXSPI_MISC_OFFSET_SAFE_CONFIG_FREQ_ENABLE = 4, + FLEXSPI_MISC_OFFSET_PAD_SETTING_OVERRIDE_ENABLE = 5, + FLEXSPI_MISC_OFFSET_DDR_MODE_ENABLE = 6, + FLEXSPI_MISC_OFFSET_USE_VALID_TIME_FOR_ALL_FREQ = 7, + FLEXSPI_MISC_OFFSET_SECOND_PINMUX = 8, +}; + +enum +{ + FLEXSPI_DEVICE_TYPE_SERIAL_NOR = 1, + FLEXSPI_DEVICE_TYPE_SERIAL_NAND = 2, +}; + +enum +{ + SERIAL_FLASH_1PAD = 1, + SERIAL_FLASH_2PADS = 2, + SERIAL_FLASH_4PADS = 4, + SERIAL_FLASH_8PADS = 8, +}; + +typedef struct _lut_sequence +{ + uint8_t seq_num; + uint8_t seq_id; + uint16_t reserved; +} flexspi_lut_seq_t; + +enum +{ + DEVICE_CONFIG_CMD_TYPE_GENERIC, + DEVICE_CONFIG_CMD_TYPE_QUADENABLE, + DEVICE_CONFIG_CMD_TYPE_SPI2XPI, + DEVICE_CONFIG_CMD_TYPE_XPI2SPI, + DEVICE_CONFIG_CMD_TYPE_SPI2NOCMD, + DEVICE_CONFIG_CMD_TYPE_RESET, +}; + +typedef struct +{ + uint8_t time_100ps; + uint8_t delay_cells; +} flexspi_dll_time_t; + +typedef struct +{ + uint32_t tag; + uint32_t version; + uint32_t reserved0; + uint8_t read_sample_clk_src; + uint8_t data_hold_time; + uint8_t data_setup_time; + uint8_t column_address_width; + uint8_t device_mode_cfg_enable; + uint8_t device_mode_type; + uint16_t wait_time_cfg_commands; + flexspi_lut_seq_t device_mode_seq; + uint32_t device_mode_arg; + uint8_t config_cmd_enable; + uint8_t config_mode_type[3]; + flexspi_lut_seq_t config_cmd_seqs[3]; + uint32_t reserved1; + uint32_t config_cmd_args[3]; + uint32_t reserved2; + uint32_t controller_misc_option; + uint8_t device_type; + uint8_t sflash_pad_type; + uint8_t serial_clk_freq; + uint8_t lut_custom_seq_enable; + uint32_t reserved3[2]; + uint32_t sflash_a1_size; + uint32_t sflash_a2_size; + uint32_t sflash_b1_size; + uint32_t sflash_b2_size; + uint32_t cs_pad_setting_override; + uint32_t sclk_pad_setting_override; + uint32_t data_pad_setting_override; + uint32_t dqs_pad_setting_override; + uint32_t timeout_in_ms; + uint32_t command_interval; + flexspi_dll_time_t data_valid_time[2]; + uint16_t busy_offset; + uint16_t busy_bit_polarity; + uint32_t lookup_table[64]; + flexspi_lut_seq_t lut_custom_seq[12]; + uint32_t reserved4[4]; +} flexspi_mem_config_t; + +typedef enum +{ + FLEXSPI_OPERATION_COMMAND, + FLEXSPI_OPERATION_CONFIG, + FLEXSPI_OPERATION_WRITE, + FLEXSPI_OPERATION_READ, + FLEXSPI_OPERATION_END = FLEXSPI_OPERATION_READ, +} flexspi_operation_t; + +typedef struct +{ + flexspi_operation_t operation; + uint32_t base_address; + uint32_t seq_id; + uint32_t seq_num; + bool is_parallel_mode_enable; + uint32_t *tx_buffer; + uint32_t tx_size; + uint32_t *rx_buffer; + uint32_t rx_size; +} flexspi_xfer_t; + +typedef enum +{ + FLEXSPI_CLOCK_CORE_CLOCK, + FLEXSPI_CLOCK_AHB_CLOCK, + FLEXSPI_CLOCK_SERIAL_ROOT_CLOCK, + FLEXSPI_CLOCK_IPG_CLOCK, +} flexspi_clock_type_t; + +#define FLEXSPI_BITMASK(bit_offset) (1u << (bit_offset)) + +enum +{ + STATUS_GROUP_GENERIC = 0, + STATUS_GROUP_FLEXSPINOR = 201, +}; + +typedef int32_t status_t; + +#define MAKE_STATUS(group, code) ((((group)*100) + (code))) + +enum +{ + STATUS_SUCCESS = MAKE_STATUS(STATUS_GROUP_GENERIC, 0), + STATUS_FAIL = MAKE_STATUS(STATUS_GROUP_GENERIC, 1), + STATUS_READONLY = MAKE_STATUS(STATUS_GROUP_GENERIC, 2), + STATUS_OUTOFRANGE = MAKE_STATUS(STATUS_GROUP_GENERIC, 3), + STATUS_INVALIDARGUMENT = MAKE_STATUS(STATUS_GROUP_GENERIC, 4), + STATUS_TIMEOUT = MAKE_STATUS(STATUS_GROUP_GENERIC, 5), + STATUS_NOTRANSFERINPROGRESS = + MAKE_STATUS(STATUS_GROUP_GENERIC, 6), + STATUS_BUSY = MAKE_STATUS(STATUS_GROUP_GENERIC, 7), + STATUS_NODATA = + MAKE_STATUS(STATUS_GROUP_GENERIC, 8), +}; + +enum _flexspi_nor_status +{ + STATUS_FLEXSPINOR_PROGRAMFAIL = MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 0), + STATUS_FLEXSPINOR_ERASESECTORFAIL = + MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 1), + STATUS_FLEXSPINOR_ERASEALLFAIL = MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 2), + STATUS_FLEXSPINOR_WAITTIMEOUT = MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 3), + STATUS_FLEXSPINOR_NOTSUPPORTED = MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 4), + STATUS_FLEXSPINOR_WRITEALIGNMENTERROR = + MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 5), + STATUS_FLEXSPINOR_COMMANDFAILURE = + MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 6), + STATUS_FLEXSPINOR_SFDP_NOTFOUND = MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 7), + STATUS_FLEXSPINOR_UNSUPPORTED_SFDP_VERSION = + MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 8), + STATUS_FLEXSPINOR_FLASH_NOTFOUND = MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 9), + STATUS_FLEXSPINOR_DTRREAD_DUMMYPROBEFAILED = + MAKE_STATUS(STATUS_GROUP_FLEXSPINOR, 10), +}; + +enum +{ + SERIAL_NOR_CFG_OPTION_TAG = 0x0c, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_READSFDP_SDR = 0, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_READSFDP_DDR = 1, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_HYPERFLASH1V8 = 2, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_HYPERFLASH3V0 = 3, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_MACRONIXOCTALDDR = 4, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_MACRONIXOCTALSDR = 5, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_MICRONOCTALDDR = 6, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_MICRONOCTALSDR = 7, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_ADESTOOCTALDDR = 8, + SERIAL_NOR_CFG_OPTION_DEVICETYPE_ADESTOOCTALSDR = 9, +}; + +enum +{ + SERIAL_NOR_QUAD_MODE_NOTCONFIG = 0, + SERIAL_NOR_QUAD_MODE_STATUSREG1_BIT6 = 1, + SERIAL_NOR_QUAD_MODE_STATUSREG2_BIT1 = 2, + SERIAL_NOR_QUAD_MODE_STATUSREG2_BIT7 = 3, + SERIAL_NOR_QUAD_MODE_STATUSREG2_BIT1_0X31 = 4, +}; + +enum +{ + SERIAL_NOR_ENHANCE_MODE_DISABLED = 0, + SERIAL_NOR_ENHANCE_MODE_0_4_4_MODE = 1, + SERIAL_NOR_ENHANCE_MODE_0_8_8_MODE = 2, + SERIAL_NOR_ENHANCE_MODE_DATAORDERSWAPPED = 3, + SERIAL_NOR_ENHANCE_MODE_2NDPINMUX = 4, +}; + +typedef struct _serial_nor_config_option +{ + union + { + struct + { + uint32_t max_freq : 4; + uint32_t misc_mode : 4; + uint32_t quad_mode_setting : 4; + uint32_t cmd_pads : 4; + uint32_t query_pads : 4; + uint32_t device_type : 4; + uint32_t option_size : 4; + uint32_t tag : 4; + } B; + uint32_t U; + } option0; + + union + { + struct + { + uint32_t dummy_cycles : 8; + uint32_t status_override : 8; + uint32_t is_pinmux_group2 : 4; + uint32_t reserved : 12; + } B; + uint32_t U; + } option1; +} serial_nor_config_option_t; + +typedef struct _flexspi_nor_config +{ + flexspi_mem_config_t mem_config; + uint32_t page_size; + uint32_t sector_size; + uint8_t ipcmd_serial_clk_freq; + uint8_t is_uniform_block_size; + uint8_t is_data_order_swapped; + uint8_t reserved0[1]; + uint8_t serial_nor_type; + uint8_t need_exit_no_cmd_mode; + uint8_t half_clk_for_non_read_cmd; + uint8_t need_restore_no_cmd_mode; + uint32_t block_size; + uint32_t reserve2[11]; +} flexspi_nor_config_t; + +typedef struct +{ + uint32_t version; + status_t (*init)(uint32_t instance, flexspi_nor_config_t *config); + status_t (*program)(uint32_t instance, flexspi_nor_config_t *config, + uint32_t dst_addr, const uint32_t *src); + status_t (*erase_all)(uint32_t instance, flexspi_nor_config_t *config); + status_t (*erase)(uint32_t instance, flexspi_nor_config_t *config, + uint32_t start, uint32_t length_in_bytes); + status_t (*read)(uint32_t instance, flexspi_nor_config_t *config, + uint32_t *dst, uint32_t addr, uint32_t length_in_bytes); + void (*clear_cache)(uint32_t instance); + status_t (*xfer)(uint32_t instance, flexspi_xfer_t *xfer); + status_t (*update_lut)(uint32_t instance, uint32_t seq_index, + const uint32_t *lut_base, uint32_t seq_number); + status_t (*get_config)(uint32_t instance, flexspi_nor_config_t *config, + serial_nor_config_option_t *option); +} flexspi_nor_driver_interface_t; + +typedef struct +{ + const uint32_t version; + const char *copyright; + void (*run_bootloader)(void *arg); + const uint32_t *reserved0; + const flexspi_nor_driver_interface_t *flexspi_nor_driver; + const uint32_t *reserved1[2]; + const void *rtwdog_driver; + const void *wdog_driver; + const uint32_t *reserved2; +} bootloader_api_entry_t; + +enum +{ + ENTER_BOOTLOADER_TAG = 0xeb, + ENTER_BOOTLOADER_MODE_DEFAULT = 0, + ENTER_BOOTLOADER_MODE_SERIALDOWNLOADER = 1, + + ENTER_BOOTLOADER_SERIALINTERFACE_AUTO = 0, + ENTER_BOOTLOADER_SERIALINTERFACE_USB = 1, + ENTER_BOOTLOADER_SERIALINTERFACE_UART = 2, + + ENTER_BOOTLOADER_IMAGEINDEX_MAX = 3, +}; + +typedef union +{ + struct + { + uint32_t image_index : 4; + uint32_t reserved : 12; + uint32_t serial_boot_interface : 4; + uint32_t boot_mode : 4; + uint32_t tag : 8; + } B; + uint32_t U; +} run_bootloader_ctx_t; + +#define g_bootloader_tree (*(bootloader_api_entry_t**)0x0020001c) + +static inline void run_bootloader(run_bootloader_ctx_t *ctx) +{ + g_bootloader_tree->run_bootloader(ctx); +} + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +status_t flexspi_nor_flash_init(uint32_t instance, + flexspi_nor_config_t *config) +{ + return g_bootloader_tree->flexspi_nor_driver->init(instance, config); +} + +status_t flexspi_nor_flash_page_program(uint32_t instance, + flexspi_nor_config_t *config, + uint32_t dst_addr, + const uint32_t *src) +{ + return g_bootloader_tree->flexspi_nor_driver->program(instance, config, + dst_addr, src); +} + +status_t flexspi_nor_flash_erase_all(uint32_t instance, + flexspi_nor_config_t *config) +{ + return g_bootloader_tree->flexspi_nor_driver->erase_all(instance, config); +} + +status_t flexspi_nor_get_config(uint32_t instance, + flexspi_nor_config_t *config, + serial_nor_config_option_t *option) +{ + return g_bootloader_tree->flexspi_nor_driver->get_config(instance, config, + option); +} + +status_t flexspi_nor_flash_erase(uint32_t instance, + flexspi_nor_config_t *config, + uint32_t start, + uint32_t length) +{ + return g_bootloader_tree->flexspi_nor_driver->erase(instance, config, + start, length); +} + +status_t flexspi_nor_flash_read(uint32_t instance, + flexspi_nor_config_t *config, + uint32_t *dst, + uint32_t start, + uint32_t bytes) +{ + return g_bootloader_tree->flexspi_nor_driver->read(instance, config, + dst, start, bytes); +} + +status_t flexspi_update_lut(uint32_t instance, + uint32_t seq_index, + const uint32_t *lut_base, + uint32_t number_of_seq) +{ + return g_bootloader_tree->flexspi_nor_driver->update_lut(instance, + seq_index, + lut_base, + number_of_seq); +} + +status_t flexspi_command_xfer(uint32_t instance, flexspi_xfer_t *xfer) +{ + return g_bootloader_tree->flexspi_nor_driver->xfer(instance, xfer); +} + +void flexspi_clear_cache(uint32_t instance) +{ + g_bootloader_tree->flexspi_nor_driver->clear_cache(instance); +} + +struct imxrt106x_flash_priv_s +{ + mutex_t lock; + uint32_t ifbase; + uint32_t base; + uint32_t stblock; + uint32_t stpage; +}; + +#if CONFIG_IMXRT_PROGMEM_FLEXSPI_INSTANCE == 0 +static struct imxrt106x_flash_priv_s imxrt106x_flash_priv = +{ + .lock = NXMUTEX_INITIALIZER, + .ifbase = IMXRT_FLEXSPIC_BASE, + .base = IMXRT_FLEXCIPHER_BASE, + .stblock = 0, + .stpage = 0, +}; +#else +static struct imxrt106x_flash_priv_s imxrt106x_flash_priv = +{ + .lock = NXMUTEX_INITIALIZER, + .ifbase = IMXRT_FLEXSPI2C_BASE, + .base = IMXRT_FLEX2CIPHER_BASE, + .stblock = 0, + .stpage = 0, +}; +#endif + +static flexspi_nor_config_t flash_config; +static serial_nor_config_option_t config_option; + +static int imxrt106x_israngeerased(size_t startaddress, size_t size) +{ + uint32_t *addr; + uint8_t *baddr; + size_t count = 0; + size_t bwritten = 0; + + addr = (uint32_t *)startaddress; + while (count + 4 <= size) + { + if (getreg32(addr) != FLASH_ERASEDVALUE_DW) + { + bwritten++; + } + + addr++; + count += 4; + } + + baddr = (uint8_t *)addr; + while (count < size) + { + if (getreg8(baddr) != FLASH_ERASEDVALUE) + { + bwritten++; + } + + baddr++; + count++; + } + + return bwritten; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +size_t up_progmem_erasesize(size_t block) +{ + return FLASH_SECTOR_SIZE; +} + +size_t up_progmem_pagesize(size_t page) +{ + return up_progmem_erasesize(page); +} + +ssize_t up_progmem_getpage(size_t addr) +{ + struct imxrt106x_flash_priv_s *priv = &imxrt106x_flash_priv; + + return priv->stpage + ((addr - priv->base) / FLASH_SECTOR_SIZE); +} + +size_t up_progmem_getaddress(size_t page) +{ + struct imxrt106x_flash_priv_s *priv = &imxrt106x_flash_priv; + + if (page >= PROGMEM_NBLOCKS) + { + return SIZE_MAX; + } + + return priv->base + (page - priv->stpage) * FLASH_SECTOR_SIZE; +} + +size_t up_progmem_neraseblocks(void) +{ + return PROGMEM_NBLOCKS; +} + +bool up_progmem_isuniform(void) +{ + return true; +} + +ssize_t up_progmem_ispageerased(size_t page) +{ + size_t addr; + size_t count; + size_t bwritten = 0; + + if (page >= PROGMEM_NBLOCKS) + { + return -EFAULT; + } + + for (addr = up_progmem_getaddress(page), count = up_progmem_pagesize(page); + count; count--, addr++) + { + if (getreg8(addr) != FLASH_ERASEDVALUE) + { + bwritten++; + } + } + + return bwritten; +} + +ssize_t up_progmem_eraseblock(size_t block) +{ + struct imxrt106x_flash_priv_s *priv = &imxrt106x_flash_priv; + int ret; + status_t status; + size_t block_address = (block * FLASH_SECTOR_SIZE); + + ret = nxmutex_lock(&priv->lock); + if (ret < 0) + { + return (ssize_t)ret; + } + + config_option.option0.U = 0xc0000008; + + up_irq_disable(); + up_disable_icache(); + up_disable_dcache(); + + status = flexspi_nor_get_config(FLEXSPI_INSTANCE, &flash_config, + &config_option); + if (status != STATUS_SUCCESS) + { + ret = -EIO; + goto exit_with_lock; + } + + status = flexspi_nor_flash_init(FLEXSPI_INSTANCE, &flash_config); + if (status != STATUS_SUCCESS) + { + ret = -EIO; + goto exit_with_lock; + } + + status = flexspi_nor_flash_erase(FLEXSPI_INSTANCE, &flash_config, + block_address, FLASH_SECTOR_SIZE); + if (status != STATUS_SUCCESS) + { + ret = -EIO; + goto exit_with_lock; + } + + ret = 0; + +exit_with_lock: + nxmutex_unlock(&priv->lock); + + /* Verify */ + + if (ret == 0 && + imxrt106x_israngeerased(priv->base + block_address, + up_progmem_erasesize(block)) == 0) + { + ret = up_progmem_erasesize(block); /* success */ + } + else + { + ret = -EIO; /* failure */ + } + + up_enable_dcache(); + up_enable_icache(); + up_irq_enable(); + + return ret; +} + +ssize_t up_progmem_write(size_t addr, const void *buf, size_t count) +{ + struct imxrt106x_flash_priv_s *priv = &imxrt106x_flash_priv; + size_t written = count; + uint32_t *ll = (uint32_t *)buf; + size_t faddr; + status_t status; + int ret; + const size_t pagesize = FLASH_PAGE_SIZE; + const size_t llperpage = pagesize / sizeof(uint32_t); + size_t pcount = count / pagesize; + + ret = nxmutex_lock(&priv->lock); + if (ret < 0) + { + return (ssize_t)ret; + } + + /* Check address and count alignment */ + + DEBUGASSERT(!(addr % pagesize)); + DEBUGASSERT(!(count % pagesize)); + + config_option.option0.U = 0xc0000008; + + up_irq_disable(); + up_disable_icache(); + + status = flexspi_nor_get_config(FLEXSPI_INSTANCE, &flash_config, + &config_option); + if (status != STATUS_SUCCESS) + { + written = -EIO; + goto exit_with_lock; + } + + status = flexspi_nor_flash_init(FLEXSPI_INSTANCE, &flash_config); + if (status != STATUS_SUCCESS) + { + written = -EIO; + goto exit_with_lock; + } + + for (ll = (uint32_t *)buf, faddr = addr - priv->base; pcount; + pcount -= 1, ll += llperpage, faddr += pagesize) + { + status = flexspi_nor_flash_page_program(FLEXSPI_INSTANCE, + &flash_config, faddr, ll); + if (status != STATUS_SUCCESS) + { + written = -EIO; + break; + } + } + +exit_with_lock: + nxmutex_unlock(&priv->lock); + up_enable_icache(); + up_irq_enable(); + + return written; +} + +uint8_t up_progmem_erasestate(void) +{ + return FLASH_ERASEDVALUE; +} diff --git a/arch/arm/src/imxrt/imxrt_flash.c b/arch/arm/src/imxrt/imxrt_flash.c new file mode 100644 index 00000000000..62f769735b3 --- /dev/null +++ b/arch/arm/src/imxrt/imxrt_flash.c @@ -0,0 +1,35 @@ +/**************************************************************************** + * arch/arm/src/imxrt/imxrt_flash.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_ARCH_FAMILY_IMXRT106x) +# include "imxrt106x_flash.c" +#else +# error "Unsupported IMXRT chip" +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ diff --git a/boards/arm/imxrt/imxrt1064-evk/configs/mcuboot-app/defconfig b/boards/arm/imxrt/imxrt1064-evk/configs/mcuboot-app/defconfig new file mode 100644 index 00000000000..16078de3cd6 --- /dev/null +++ b/boards/arm/imxrt/imxrt1064-evk/configs/mcuboot-app/defconfig @@ -0,0 +1,85 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="imxrt1064-evk" +CONFIG_ARCH_BOARD_IMXRT1064_EVK=y +CONFIG_ARCH_CHIP="imxrt" +CONFIG_ARCH_CHIP_IMXRT=y +CONFIG_ARCH_CHIP_MIMXRT1064DVL6A=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=104926 +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_ETH0_PHY_KSZ8081=y +CONFIG_EXAMPLES_MCUBOOT_SLOT_CONFIRM=y +CONFIG_EXAMPLES_MCUBOOT_SWAP_TEST=y +CONFIG_EXAMPLES_MCUBOOT_UPDATE_AGENT=y +CONFIG_EXAMPLES_MCUBOOT_UPDATE_AGENT_DL_BUFFER_SIZE=4096 +CONFIG_EXPERIMENTAL=y +CONFIG_FAT_LCNAMES=y +CONFIG_FS_FAT=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_IMXRT_APP_FORMAT_MCUBOOT=y +CONFIG_IMXRT_ENET=y +CONFIG_IMXRT_LPUART1=y +CONFIG_IMXRT_PROGMEM_OTA_PARTITION=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=4096 +CONFIG_IOB_NBUFFERS=128 +CONFIG_LIBC_HOSTNAME="i.MXRT1064 EVK" +CONFIG_LPUART1_BAUD=9600 +CONFIG_LPUART1_SERIAL_CONSOLE=y +CONFIG_NET=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDEV_STATISTICS=y +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_DISCOVER=y +CONFIG_NETUTILS_WEBCLIENT=y +CONFIG_NET_ARP_SEND=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1514 +CONFIG_NET_GUARDSIZE=4 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_ICMPv6=y +CONFIG_NET_ICMPv6_NEIGHBOR=y +CONFIG_NET_ICMPv6_SOCKET=y +CONFIG_NET_IPv6=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_TCPBACKLOG=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_WRITE_BUFFERS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_MOTD=y +CONFIG_NSH_MOTD_STRING="Welcome to Nuttx from MCUboot, this is the FIRST firmware." +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=1048576 +CONFIG_RAM_START=0x20200000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=14 +CONFIG_START_MONTH=3 +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y diff --git a/boards/arm/imxrt/imxrt1064-evk/configs/mcuboot-loader/defconfig b/boards/arm/imxrt/imxrt1064-evk/configs/mcuboot-loader/defconfig new file mode 100644 index 00000000000..ec8ca693313 --- /dev/null +++ b/boards/arm/imxrt/imxrt1064-evk/configs/mcuboot-loader/defconfig @@ -0,0 +1,59 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="imxrt1064-evk" +CONFIG_ARCH_BOARD_IMXRT1064_EVK=y +CONFIG_ARCH_CHIP="imxrt" +CONFIG_ARCH_CHIP_IMXRT=y +CONFIG_ARCH_CHIP_MIMXRT1064DVL6A=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=104926 +CONFIG_BOOT_MCUBOOT=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXPERIMENTAL=y +CONFIG_FAT_LCNAMES=y +CONFIG_FS_FAT=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_IMXRT_APP_FORMAT_MCUBOOT=y +CONFIG_IMXRT_LPUART1=y +CONFIG_IMXRT_PROGMEM_OTA_PARTITION=y +CONFIG_INIT_ENTRYPOINT="mcuboot_loader_main" +CONFIG_INIT_STACKSIZE=4096 +CONFIG_LIBM=y +CONFIG_LPUART1_BAUD=9600 +CONFIG_LPUART1_SERIAL_CONSOLE=y +CONFIG_MCUBOOT_BOOTLOADER=y +CONFIG_MCUBOOT_VERSION="414ac87cfd8d9cedeb781f812ad6f5072e6d8a39" +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LIBRARY=y +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_MOTD=y +CONFIG_NSH_MOTD_STRING="Welcome to Nuttx MCUboot-Loader!" +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=1048576 +CONFIG_RAM_START=0x20200000 +CONFIG_RAW_BINARY=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=14 +CONFIG_START_MONTH=3 +CONFIG_TASK_NAME_SIZE=0 +CONFIG_WQUEUE_NOTIFIER=y diff --git a/boards/arm/imxrt/imxrt1064-evk/scripts/Make.defs b/boards/arm/imxrt/imxrt1064-evk/scripts/Make.defs index 4a2f40105bd..f6dbc5f7a02 100644 --- a/boards/arm/imxrt/imxrt1064-evk/scripts/Make.defs +++ b/boards/arm/imxrt/imxrt1064-evk/scripts/Make.defs @@ -22,10 +22,18 @@ include $(TOPDIR)/.config include $(TOPDIR)/tools/Config.mk include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs -ifeq ($(CONFIG_BOOT_RUNFROMFLASH),y) - LDSCRIPT = flash.ld -else ifeq ($(CONFIG_BOOT_RUNFROMISRAM),y) - LDSCRIPT = flash-ocram.ld +ifeq ($(CONFIG_IMXRT_APP_FORMAT_MCUBOOT),y) + ifeq ($(CONFIG_MCUBOOT_BOOTLOADER),y) + LDSCRIPT = flash-mcuboot-loader.ld + else + LDSCRIPT = flash-mcuboot-app.ld + endif +else + ifeq ($(CONFIG_BOOT_RUNFROMFLASH),y) + LDSCRIPT = flash.ld + else ifeq ($(CONFIG_BOOT_RUNFROMISRAM),y) + LDSCRIPT = flash-ocram.ld + endif endif ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) diff --git a/boards/arm/imxrt/imxrt1064-evk/scripts/flash-mcuboot-app.ld b/boards/arm/imxrt/imxrt1064-evk/scripts/flash-mcuboot-app.ld new file mode 100644 index 00000000000..7b70b44a599 --- /dev/null +++ b/boards/arm/imxrt/imxrt1064-evk/scripts/flash-mcuboot-app.ld @@ -0,0 +1,119 @@ +/**************************************************************************** + * boards/arm/imxrt/imxrt1064-evk/scripts/flash.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* Specify the memory areas */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x70040200, LENGTH = 1792K - 512 + sram (rwx) : ORIGIN = 0x20200000, LENGTH = 512M + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 128K + dtcm (rwx) : ORIGIN = 0x20000000, LENGTH = 128K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) + +ENTRY(_stext) + +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + .ARM.exidx : + { + __exidx_start = ABSOLUTE(.); + *(.ARM.exidx*) + __exidx_end = ABSOLUTE(.); + } > flash + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .ramfunc ALIGN(4): + { + _sramfuncs = ABSOLUTE(.); + *(.ramfunc .ramfunc.*) + _eramfuncs = ABSOLUTE(.); + } > sram AT > flash + + _framfuncs = LOADADDR(.ramfunc); + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/imxrt/imxrt1064-evk/scripts/flash-mcuboot-loader.ld b/boards/arm/imxrt/imxrt1064-evk/scripts/flash-mcuboot-loader.ld new file mode 100644 index 00000000000..7c80d9dee76 --- /dev/null +++ b/boards/arm/imxrt/imxrt1064-evk/scripts/flash-mcuboot-loader.ld @@ -0,0 +1,139 @@ +/**************************************************************************** + * boards/arm/imxrt/imxrt1064-evk/scripts/flash.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* Specify the memory areas */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x70000000, LENGTH = 256K + sram (rwx) : ORIGIN = 0x20200000, LENGTH = 512M + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 128K + dtcm (rwx) : ORIGIN = 0x20000000, LENGTH = 128K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +EXTERN(g_flash_config) +EXTERN(g_image_vector_table) +EXTERN(g_boot_data) + +ENTRY(_stext) + +SECTIONS +{ + /* Image Vector Table and Boot Data for booting from external flash */ + + .boot_hdr : ALIGN(4) + { + FILL(0xff) + __boot_hdr_start__ = ABSOLUTE(.) ; + KEEP(*(.boot_hdr.conf)) + . = 0x1000 ; + KEEP(*(.boot_hdr.ivt)) + . = 0x1020 ; + KEEP(*(.boot_hdr.boot_data)) + . = 0x1030 ; + KEEP(*(.boot_hdr.dcd_data)) + __boot_hdr_end__ = ABSOLUTE(.) ; + . = 0x2000 ; + } >flash + + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + .ARM.exidx : + { + __exidx_start = ABSOLUTE(.); + *(.ARM.exidx*) + __exidx_end = ABSOLUTE(.); + } > flash + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .ramfunc ALIGN(4): + { + _sramfuncs = ABSOLUTE(.); + *(.ramfunc .ramfunc.*) + _eramfuncs = ABSOLUTE(.); + } > sram AT > flash + + _framfuncs = LOADADDR(.ramfunc); + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/imxrt/imxrt1064-evk/src/Makefile b/boards/arm/imxrt/imxrt1064-evk/src/Makefile index bffdbca9ea4..92dc98b1c18 100644 --- a/boards/arm/imxrt/imxrt1064-evk/src/Makefile +++ b/boards/arm/imxrt/imxrt1064-evk/src/Makefile @@ -86,4 +86,16 @@ ifeq ($(CONFIG_IMXRT_FLEXSPI),y) CSRCS += imxrt_flexspi_nor.c endif +ifeq ($(CONFIG_IMXRT_PROGMEM),y) +CSRCS += imxrt_progmem.c +endif + +ifeq ($(CONFIG_BOARDCTL_RESET),y) +CSRCS += imxrt_reset.c +endif + +ifeq ($(CONFIG_BOARDCTL_BOOT_IMAGE),y) +CSRCS += imxrt_boot_image.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/imxrt/imxrt1064-evk/src/imxrt1064-evk.h b/boards/arm/imxrt/imxrt1064-evk/src/imxrt1064-evk.h index 17894c23651..3a6111264cf 100644 --- a/boards/arm/imxrt/imxrt1064-evk/src/imxrt1064-evk.h +++ b/boards/arm/imxrt/imxrt1064-evk/src/imxrt1064-evk.h @@ -40,6 +40,14 @@ * Pre-processor Definitions ****************************************************************************/ +/* Configuration ************************************************************/ + +#define HAVE_PROGMEM_CHARDEV 1 + +#if !defined(CONFIG_IMXRT_PROGMEM) || !defined(CONFIG_MTD_PROGMEM) +# undef HAVE_PROGMEM_CHARDEV +#endif + /* Touchscreen definitions **************************************************/ /* The IMXRT 1050/1060 have connectors for the LCD model RK043FN02H-CT. @@ -317,5 +325,12 @@ int imxrt_usbhost_initialize(void); int imxrt_flexspi_nor_initialize(void); #endif +#ifdef CONFIG_MTD + +#ifdef HAVE_PROGMEM_CHARDEV +int imxrt_progmem_init(void); +#endif /* HAVE_PROGMEM_CHARDEV */ +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM_IMXRT_IMXRT1064_EVK_SRC_IMXRT1064_EVK_H */ diff --git a/boards/arm/imxrt/imxrt1064-evk/src/imxrt_boot_image.c b/boards/arm/imxrt/imxrt1064-evk/src/imxrt_boot_image.c new file mode 100644 index 00000000000..ccfa93ffff0 --- /dev/null +++ b/boards/arm/imxrt/imxrt1064-evk/src/imxrt_boot_image.c @@ -0,0 +1,180 @@ +/**************************************************************************** + * boards/arm/imxrt/imxrt1064-evk/src/imxrt_boot_image.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "nvic.h" +#include "arm_internal.h" +#include "barriers.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the first two entries on NVIC vector table */ + +struct arm_vector_table +{ + uint32_t spr; /* Stack pointer on reset */ + uint32_t reset; /* Pointer to reset exception handler */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void cleanup_arm_nvic(void); +static void systick_disable(void); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cleanup_arm_nvic + * + * Description: + * Acknowledge and disable all interrupts in NVIC + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void cleanup_arm_nvic(void) +{ + int i; + + /* Allow any pending interrupts to be recognized */ + + ARM_ISB(); + cpsid(); + + /* Disable all interrupts */ + + for (i = 0; i < NR_IRQS; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); + } + + /* Clear all pending interrupts */ + + for (i = 0; i < NR_IRQS; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLRPEND(i)); + } +} + +/**************************************************************************** + * Name: systick_disable + * + * Description: + * Disable the SysTick system timer + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void systick_disable(void) +{ + putreg32(0, NVIC_SYSTICK_CTRL); + putreg32(NVIC_SYSTICK_RELOAD_MASK, NVIC_SYSTICK_RELOAD); + putreg32(0, NVIC_SYSTICK_CURRENT); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_boot_image + * + * Description: + * This entry point is called by bootloader to jump to application image. + * + ****************************************************************************/ + +int board_boot_image(const char *path, uint32_t hdr_size) +{ + static struct arm_vector_table vt; + int fd; + ssize_t bytes; + + fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) + { + syslog(LOG_ERR, "Failed to open %s with: %d", path, fd); + return fd; + } + + bytes = pread(fd, &vt, sizeof(vt), hdr_size); + if (bytes != sizeof(vt)) + { + syslog(LOG_ERR, "Failed to read ARM vector table: %d", bytes); + return bytes < 0 ? bytes : -1; + } + + systick_disable(); + + cleanup_arm_nvic(); + +#ifdef CONFIG_ARMV7M_DCACHE + up_disable_dcache(); +#endif +#ifdef CONFIG_ARMV7M_ICACHE + up_disable_icache(); +#endif + +#ifdef CONFIG_ARM_MPU + mpu_control(false, false, false); +#endif + + /* Set main and process stack pointers */ + + __asm__ __volatile__("\tmsr msp, %0\n" : : "r" (vt.spr)); + setcontrol(0x00); + ARM_ISB(); + ((void (*)(void))vt.reset)(); + + return 0; +} diff --git a/boards/arm/imxrt/imxrt1064-evk/src/imxrt_bringup.c b/boards/arm/imxrt/imxrt1064-evk/src/imxrt_bringup.c index 58272f7da4b..666f68fd9b1 100644 --- a/boards/arm/imxrt/imxrt1064-evk/src/imxrt_bringup.c +++ b/boards/arm/imxrt/imxrt1064-evk/src/imxrt_bringup.c @@ -287,6 +287,16 @@ int imxrt_bringup(void) } #endif /* CONFIG_IMXRT_FLEXSPI */ +#ifdef CONFIG_MTD +#ifdef HAVE_PROGMEM_CHARDEV + ret = imxrt_progmem_init(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize MTD progmem: %d\n", ret); + } +#endif /* HAVE_PROGMEM_CHARDEV */ +#endif /* CONFIG_MTD */ + UNUSED(ret); return OK; } diff --git a/boards/arm/imxrt/imxrt1064-evk/src/imxrt_progmem.c b/boards/arm/imxrt/imxrt1064-evk/src/imxrt_progmem.c new file mode 100644 index 00000000000..bd031ee9797 --- /dev/null +++ b/boards/arm/imxrt/imxrt1064-evk/src/imxrt_progmem.c @@ -0,0 +1,255 @@ +/**************************************************************************** + * boards/arm/imxrt/imxrt1064-evk/src/imxrt_progmem.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef CONFIG_BCH +#include +#endif + +#include "imxrt1064-evk.h" + +#ifdef HAVE_PROGMEM_CHARDEV + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) + +#define PARTITION_LABEL_LEN 16 + +/* Configuration ************************************************************/ + +/* Make sure that support for MTD partitions is enabled */ +#ifdef CONFIG_MTD + +#ifndef CONFIG_MTD_PARTITION +# error "CONFIG_MTD_PARTITION is required" +#endif + +#endif +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#if defined(CONFIG_IMXRT_PROGMEM_OTA_PARTITION) + +struct ota_partition_s +{ + uint32_t offset; /* Partition offset from the beginning of MTD */ + uint32_t size; /* Partition size in bytes */ + const char *devpath; /* Partition device path */ +}; + +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#if defined(CONFIG_IMXRT_PROGMEM_OTA_PARTITION) +static struct mtd_dev_s *progmem_alloc_mtdpart(uint32_t mtd_offset, + uint32_t mtd_size); +static int init_ota_partitions(void); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct mtd_dev_s *g_progmem_mtd; + +#if defined(CONFIG_IMXRT_PROGMEM_OTA_PARTITION) +static const struct ota_partition_s g_ota_partition_table[] = +{ + { + .offset = CONFIG_IMXRT_OTA_PRIMARY_SLOT_OFFSET, + .size = CONFIG_IMXRT_OTA_SLOT_SIZE, + .devpath = CONFIG_IMXRT_OTA_PRIMARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_IMXRT_OTA_SECONDARY_SLOT_OFFSET, + .size = CONFIG_IMXRT_OTA_SLOT_SIZE, + .devpath = CONFIG_IMXRT_OTA_SECONDARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_IMXRT_OTA_SCRATCH_OFFSET, + .size = CONFIG_IMXRT_OTA_SCRATCH_SIZE, + .devpath = CONFIG_IMXRT_OTA_SCRATCH_DEVPATH + } +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if defined(CONFIG_IMXRT_PROGMEM_OTA_PARTITION) + +/**************************************************************************** + * Name: progmem_alloc_mtdpart + * + * Description: + * Allocate an MTD partition from FLASH. + * + * Input Parameters: + * mtd_offset - MTD Partition offset from the base address in FLASH. + * mtd_size - Size for the MTD partition. + * + * Returned Value: + * MTD partition data pointer on success, NULL on failure. + * + ****************************************************************************/ + +static struct mtd_dev_s *progmem_alloc_mtdpart(uint32_t mtd_offset, + uint32_t mtd_size) +{ + uint32_t blocks; + ssize_t startblock; + + ASSERT((mtd_offset % up_progmem_pagesize(0)) == 0); + ASSERT((mtd_size % up_progmem_pagesize(0)) == 0); + + finfo("\tMTD offset = 0x%"PRIx32"\n", mtd_offset); + finfo("\tMTD size = 0x%"PRIx32"\n", mtd_size); + + startblock = up_progmem_getpage(mtd_offset + up_progmem_getaddress(0)); + if (startblock < 0) + { + return NULL; + } + + blocks = mtd_size / up_progmem_pagesize(0); + + return mtd_partition(g_progmem_mtd, startblock, blocks); +} + +/**************************************************************************** + * Name: init_ota_partitions + * + * Description: + * Initialize partitions that are dedicated to firmware OTA update. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int init_ota_partitions(void) +{ + int i; + struct mtd_dev_s *mtd; + int ret = 0; + char path[PARTITION_LABEL_LEN + 1]; + + for (i = 0; i < ARRAYSIZE(g_ota_partition_table); ++i) + { + const struct ota_partition_s *part = &g_ota_partition_table[i]; + mtd = progmem_alloc_mtdpart(part->offset, part->size); + + strncpy(path, (char *)part->devpath, PARTITION_LABEL_LEN); + path[PARTITION_LABEL_LEN] = '\0'; + + finfo("INFO: [label]: %s\n", path); + finfo("INFO: [offset]: 0x%08" PRIx32 "\n", part->offset); + finfo("INFO: [size]: 0x%08" PRIx32 "\n", part->size); + + if (!mtd) + { + ferr("ERROR: Failed to create MTD partition\n"); + ret = -1; + } + + ret = register_mtddriver(path, mtd, 0777, NULL); + if (ret < 0) + { + ferr("ERROR: Failed to register MTD @ %s\n", path); + ret = -1; + } + } + + return ret; +} +#endif /* CONFIG_IMXRT_PROGMEM_OTA_PARTITION */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_progmem_init + * + * Initialize Progmem partition. Read partition information, and use + * these data for creating MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +int imxrt_progmem_init(void) +{ + int ret = 0; + + g_progmem_mtd = progmem_initialize(); + if (g_progmem_mtd == NULL) + { + ferr("ERROR: Failed to get progmem flash MTD\n"); + ret = -EIO; + } + +#ifdef CONFIG_IMXRT_PROGMEM_OTA_PARTITION + ret = init_ota_partitions(); + if (ret < 0) + { + ferr("ERROR: Failed to create OTA partition from MTD\n"); + ret = -EIO; + } +#endif + + return ret; +} + +#endif /* HAVE_PROGMEM_CHARDEV */ diff --git a/boards/arm/imxrt/imxrt1064-evk/src/imxrt_reset.c b/boards/arm/imxrt/imxrt1064-evk/src/imxrt_reset.c new file mode 100644 index 00000000000..f05c427060b --- /dev/null +++ b/boards/arm/imxrt/imxrt1064-evk/src/imxrt_reset.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * boards/arm/imxrt/imxrt1064-evk/src/imxrt_reset.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef CONFIG_BOARDCTL_RESET + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_reset + * + * Description: + * Reset board. Support for this function is required by board-level + * logic if CONFIG_BOARDCTL_RESET is selected. + * + * Input Parameters: + * status - Status information provided with the reset event. This + * meaning of this status information is board-specific. If not + * used by a board, the value zero may be provided in calls to + * board_reset(). + * + * Returned Value: + * If this function returns, then it was not possible to power-off the + * board due to some constraints. The return value int this case is a + * board-specific reason for the failure to shutdown. + * + ****************************************************************************/ + +int board_reset(int status) +{ + up_systemreset(); + return 0; +} + +#endif /* CONFIG_BOARDCTL_RESET */