From e574f6882082058b868b2f81955d8204fa1c852d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 3 Oct 2024 09:07:48 +0200 Subject: [PATCH 1/6] mimxrt: Add support for a UF2 bootloader. Allowing to use e.g. the Adafruit bootloaders with MicroPython. The .uf2 file is created in addition to the .bin and .hex files allowing to use the latter ones without the bootloader for debugging and testing. Changes: - Set the location of the ISR Vector and .text segment to 0x6000C000 and 0x6000C400. - Reserve an area at the start of ITCM for a copy of the interrupt vector table and copy the table on reset to this place. - Extend `machine.bootloader()` by setting the magic number to enable the bootloader on reset. - Create a .uf2 file which skips the segments below 0x6000C000. The bootloader has to be installed as a preparation step using the board specific methods, but then the firmware's .uf2 file version can be installed using the bootloader. The bootloader can be invoked with: - double reset - calling machine.bootloader() - Using the touch1200 method Double reset is hard to achieve on MIMXRT boards, since there is no clean reset pin. Some MIMXRT boards provide it by switching the power. Some boards are excluded from the .uf2 build: - MIMXRT1050_EVK: The uf2 bootloader is built for the QSPI version of the board. MicroPython supports the Hyperflash version. - MIMXRT1176_EVK: No support for this board yet, but it should be possible. Signed-off-by: robert-hh --- ports/mimxrt/Makefile | 21 +++++++++++++++++++ .../boards/ADAFRUIT_METRO_M7/mpconfigboard.mk | 2 ++ .../boards/MIMXRT1010_EVK/mpconfigboard.mk | 2 ++ ports/mimxrt/boards/MIMXRT1011.ld | 4 ++-- ports/mimxrt/boards/MIMXRT1015.ld | 4 ++-- .../boards/MIMXRT1015_EVK/mpconfigboard.mk | 2 ++ .../boards/MIMXRT1020_EVK/mpconfigboard.mk | 2 ++ ports/mimxrt/boards/MIMXRT1021.ld | 4 ++-- ports/mimxrt/boards/MIMXRT1052.ld | 4 ++-- .../boards/MIMXRT1060_EVK/mpconfigboard.mk | 2 ++ ports/mimxrt/boards/MIMXRT1062.ld | 4 ++-- ports/mimxrt/boards/MIMXRT1064.ld | 4 ++-- .../boards/MIMXRT1064_EVK/mpconfigboard.mk | 2 ++ .../boards/OLIMEX_RT1010/mpconfigboard.mk | 2 ++ .../boards/SEEED_ARCH_MIX/mpconfigboard.mk | 2 ++ ports/mimxrt/boards/TEENSY40/mpconfigboard.mk | 2 ++ ports/mimxrt/boards/TEENSY41/mpconfigboard.mk | 2 ++ ports/mimxrt/boards/common.ld | 11 +++++----- ports/mimxrt/hal/resethandler_MIMXRT10xx.S | 13 ++++++++++++ ports/mimxrt/modmachine.c | 14 +++++++++++-- ports/mimxrt/mpconfigport.h | 2 ++ tools/autobuild/build-boards.sh | 2 +- 22 files changed, 87 insertions(+), 20 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 3a9550cc974d8..ad7d853b677a5 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -21,6 +21,7 @@ BUILD ?= build-$(BOARD) PORT ?= /dev/ttyACM0 CROSS_COMPILE ?= arm-none-eabi- GIT_SUBMODULES += lib/tinyusb lib/nxp_driver +UF2CONV ?= $(TOP)/tools/uf2conv.py # MicroPython feature configurations MICROPY_VFS_LFS2 ?= 1 @@ -162,6 +163,13 @@ SRC_HAL_IMX_C += \ $(MCU_DIR)/drivers/fsl_romapi.c endif +# If not empty, then it is 10xx. +ifneq ($(findstring MIMXRT10, $(MCU_SERIES)),) +APPLICATION_ADDR := 0x6000C000 +else +APPLICATION_ADDR := 0x3000C000 +endif + ifeq ($(MCU_SERIES), MIMXRT1176) INC += -I$(TOP)/$(MCU_DIR)/drivers/cm7 @@ -253,6 +261,11 @@ else $(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE)) endif +# Set a flag if the UF2 bootloader is used +ifeq ($(USE_UF2_BOOTLOADER),1) + CFLAGS += -DMICROPY_MACHINE_UF2_BOOTLOADER=1 +endif + # Add sources for respective board flash type # Add hal/flexspi_nor_flash.c or hal/flashspi_hyper_flash.c respectively SRC_HAL_C += hal/flexspi_$(subst qspi_,,$(FLEXSPI_FLASH_TYPE)).c @@ -470,7 +483,11 @@ $(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces # Build targets # ============================================================================= +ifeq ($(USE_UF2_BOOTLOADER),1) +all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 +else all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin +endif # Process linker scripts with C preprocessor to exchange LDDEFINES and # aggregate output of preprocessor in a single linker script `link.ld` @@ -487,6 +504,10 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.hex: $(BUILD)/firmware.elf $(Q)$(OBJCOPY) -O ihex -R .eeprom $< $@ +$(BUILD)/firmware.uf2: $(BUILD)/firmware.elf + $(Q)$(OBJCOPY) -O binary -R .stack -R .ivt -R .flash_config $^ $@-binpart + $(Q)$(PYTHON) $(UF2CONV) -b $(APPLICATION_ADDR) -f MIMXRT10XX -c -o $@ $@-binpart + # Making OBJ use an order-only dependency on the generated pins.h file # has the side effect of making the pins.h file before we actually compile # any of the objects. The normal dependency generation will deal with the diff --git a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk index a8f7add6d26ae..74d3a6f0f10e3 100644 --- a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk +++ b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk @@ -8,3 +8,5 @@ MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB MICROPY_PY_NETWORK_NINAW10 ?= 1 MICROPY_PY_SSL ?= 1 MICROPY_SSL_MBEDTLS ?= 1 + +USE_UF2_BOOTLOADER = 1 diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk index dd525859063d9..1aef451e2a6a5 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk @@ -5,6 +5,8 @@ MICROPY_FLOAT_IMPL = single MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB +USE_UF2_BOOTLOADER = 1 + JLINK_PATH ?= /media/RT1010-EVK/ JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink diff --git a/ports/mimxrt/boards/MIMXRT1011.ld b/ports/mimxrt/boards/MIMXRT1011.ld index 908eefffd643f..ab363bd56a025 100644 --- a/ports/mimxrt/boards/MIMXRT1011.ld +++ b/ports/mimxrt/boards/MIMXRT1011.ld @@ -14,9 +14,9 @@ flash_config_start = flash_start + 0x00000400; flash_config_size = 0x00000C00; ivt_start = flash_start + 0x00001000; ivt_size = 0x00001000; -interrupts_start = flash_start + 0x00002000; +interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; -text_start = flash_start + 0x00002400; +text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); diff --git a/ports/mimxrt/boards/MIMXRT1015.ld b/ports/mimxrt/boards/MIMXRT1015.ld index 90336a2437127..0237d348c2498 100644 --- a/ports/mimxrt/boards/MIMXRT1015.ld +++ b/ports/mimxrt/boards/MIMXRT1015.ld @@ -14,9 +14,9 @@ flash_config_start = flash_start; flash_config_size = 0x00001000; ivt_start = flash_start + 0x00001000; ivt_size = 0x00001000; -interrupts_start = flash_start + 0x00002000; +interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; -text_start = flash_start + 0x00002400; +text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk index 34e5cdee51134..0f719ac0a9753 100644 --- a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk @@ -6,3 +6,5 @@ MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB MICROPY_BOOT_BUFFER_SIZE = (32 * 1024) + +USE_UF2_BOOTLOADER = 1 diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk index c98843a1a3c3d..7715e669f8d09 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk @@ -12,6 +12,8 @@ MICROPY_PY_LWIP = 1 MICROPY_PY_SSL = 1 MICROPY_SSL_MBEDTLS = 1 +USE_UF2_BOOTLOADER = 1 + FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py JLINK_PATH ?= /media/RT1020-EVK/ diff --git a/ports/mimxrt/boards/MIMXRT1021.ld b/ports/mimxrt/boards/MIMXRT1021.ld index bef0c13df5505..78add04c0c26c 100644 --- a/ports/mimxrt/boards/MIMXRT1021.ld +++ b/ports/mimxrt/boards/MIMXRT1021.ld @@ -14,9 +14,9 @@ flash_config_start = flash_start; flash_config_size = 0x00001000; ivt_start = flash_start + 0x00001000; ivt_size = 0x00001000; -interrupts_start = flash_start + 0x00002000; +interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; -text_start = flash_start + 0x00002400; +text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); diff --git a/ports/mimxrt/boards/MIMXRT1052.ld b/ports/mimxrt/boards/MIMXRT1052.ld index ca656711a5a77..ea034d713e2f6 100644 --- a/ports/mimxrt/boards/MIMXRT1052.ld +++ b/ports/mimxrt/boards/MIMXRT1052.ld @@ -16,9 +16,9 @@ flash_config_start = flash_start; flash_config_size = 0x00001000; ivt_start = flash_start + 0x00001000; ivt_size = 0x00001000; -interrupts_start = flash_start + 0x00002000; +interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; -text_start = flash_start + 0x00002400; +text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00200000; text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk index 3af7cd231a2ab..f57aaff3b8b17 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk @@ -12,6 +12,8 @@ MICROPY_PY_LWIP = 1 MICROPY_PY_SSL = 1 MICROPY_SSL_MBEDTLS = 1 +USE_UF2_BOOTLOADER = 1 + FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py JLINK_PATH ?= /media/RT1060-EVK/ diff --git a/ports/mimxrt/boards/MIMXRT1062.ld b/ports/mimxrt/boards/MIMXRT1062.ld index 5b91550d97d60..3d7e6d0634196 100644 --- a/ports/mimxrt/boards/MIMXRT1062.ld +++ b/ports/mimxrt/boards/MIMXRT1062.ld @@ -16,9 +16,9 @@ flash_config_start = flash_start; flash_config_size = 0x00001000; ivt_start = flash_start + 0x00001000; ivt_size = 0x00001000; -interrupts_start = flash_start + 0x00002000; +interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; -text_start = flash_start + 0x00002400; +text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); diff --git a/ports/mimxrt/boards/MIMXRT1064.ld b/ports/mimxrt/boards/MIMXRT1064.ld index 708dac4d515c4..7c35cb60c750b 100644 --- a/ports/mimxrt/boards/MIMXRT1064.ld +++ b/ports/mimxrt/boards/MIMXRT1064.ld @@ -10,9 +10,9 @@ flash_config_start = flash_start; flash_config_size = 0x00001000; ivt_start = flash_start + 0x00001000; ivt_size = 0x00001000; -interrupts_start = flash_start + 0x00002000; +interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; -text_start = flash_start + 0x00002400; +text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk index 95cfb4585acc1..f175d26377abc 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk @@ -12,6 +12,8 @@ MICROPY_PY_LWIP = 1 MICROPY_PY_SSL = 1 MICROPY_SSL_MBEDTLS = 1 +USE_UF2_BOOTLOADER = 1 + FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py JLINK_PATH ?= /media/RT1064-EVK/ diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk index 58429d298118e..1de497d74e3f0 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk +++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk @@ -6,6 +6,8 @@ MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB +USE_UF2_BOOTLOADER = 1 + CFLAGS += -DMICROPY_HW_FLASH_DQS=kFlexSPIReadSampleClk_LoopbackInternally SRC_C += \ diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk index 63e68e1e57994..c691e2dcb55c4 100644 --- a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk +++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk @@ -12,6 +12,8 @@ MICROPY_PY_LWIP = 1 MICROPY_PY_SSL = 1 MICROPY_SSL_MBEDTLS = 1 +USE_UF2_BOOTLOADER = 1 + FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py CFLAGS += -DSPI_RETRY_TIMES=1000000 diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk index 07f174944b79c..87c122da9d49d 100644 --- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk +++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk @@ -6,5 +6,7 @@ MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB +USE_UF2_BOOTLOADER = 1 + deploy: $(BUILD)/firmware.hex teensy_loader_cli --mcu=imxrt1062 -v -w $< diff --git a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk index b297448a307e7..e28310d091ad2 100755 --- a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk +++ b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk @@ -10,6 +10,8 @@ MICROPY_PY_LWIP = 1 MICROPY_PY_SSL = 1 MICROPY_SSL_MBEDTLS = 1 +USE_UF2_BOOTLOADER = 1 + FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py deploy: $(BUILD)/firmware.hex diff --git a/ports/mimxrt/boards/common.ld b/ports/mimxrt/boards/common.ld index 587fc82a1953d..477ba38bc89a3 100644 --- a/ports/mimxrt/boards/common.ld +++ b/ports/mimxrt/boards/common.ld @@ -42,7 +42,8 @@ MEMORY m_vfs (RX) : ORIGIN = vfs_start, LENGTH = vfs_size /* Teensy uses the last bit of flash for recovery. */ m_reserved (RX) : ORIGIN = (vfs_start + vfs_size), LENGTH = reserved_size - m_itcm (RX) : ORIGIN = itcm_start, LENGTH = itcm_size + m_isr (RX) : ORIGIN = itcm_start, LENGTH = 0x400 + m_itcm (RX) : ORIGIN = itcm_start + 0x400, LENGTH = itcm_size - 0x400 m_dtcm (RW) : ORIGIN = dtcm_start, LENGTH = dtcm_size m_ocrm (RW) : ORIGIN = ocrm_start, LENGTH = ocrm_size @@ -80,7 +81,8 @@ SECTIONS . = ALIGN(4); } > m_ivt - /* The startup code goes first into internal RAM */ + /* ISR Vector table in flash. Copied to ITCM by ResetHandler(). */ + .interrupts : { __Vectors = .; @@ -90,10 +92,9 @@ SECTIONS . = ALIGN(4); } > m_interrupts - __VECTOR_RAM = __Vectors; - __RAM_VECTOR_TABLE_SIZE_BYTES = 0x0; + __Vectors_RAM = ORIGIN(m_isr); - /* The program code and other data goes into internal RAM */ + /* Some program code and other data goes into internal RAM */ .text : { . = ALIGN(4); diff --git a/ports/mimxrt/hal/resethandler_MIMXRT10xx.S b/ports/mimxrt/hal/resethandler_MIMXRT10xx.S index fe933c6d6002b..2fb8772850b6a 100644 --- a/ports/mimxrt/hal/resethandler_MIMXRT10xx.S +++ b/ports/mimxrt/hal/resethandler_MIMXRT10xx.S @@ -64,6 +64,19 @@ Reset_Handler: * __ram_function_start__/__ram_function_end__ : ramfunction region * copied to. Both must be aligned to 4 bytes boundary. */ +/* Copy the ISR Vector table to the start of ITCM to be available when the + .uf2 bootloader is used */ + + ldr r1, = __Vectors + ldr r2, = __Vectors_RAM + movs r3, 1024 + +.LC_ISR: + subs r3, #4 + ldr r0, [r1, r3] + str r0, [r2, r3] + bgt .LC_ISR + ldr r1, =__etext ldr r2, =__data_start__ ldr r3, =__data_end__ diff --git a/ports/mimxrt/modmachine.c b/ports/mimxrt/modmachine.c index 1212914d3b452..204699bcc4263 100644 --- a/ports/mimxrt/modmachine.c +++ b/ports/mimxrt/modmachine.c @@ -76,6 +76,11 @@ typedef enum { MP_SOFT_RESET } reset_reason_t; +// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21 +#define DBL_TAP_REG SNVS->LPGPR[3] +#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set +#define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef + static mp_obj_t mp_machine_unique_id(void) { unsigned char id[8]; mp_hal_get_unique_id(id); @@ -158,12 +163,17 @@ NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args) { #if defined(MICROPY_BOARD_ENTER_BOOTLOADER) // If a board has a custom bootloader, call it first. MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args); - #elif FSL_ROM_HAS_RUNBOOTLOADER_API + #elif FSL_ROM_HAS_RUNBOOTLOADER_API && !MICROPY_MACHINE_UF2_BOOTLOADER // If not, enter ROM bootloader in serial downloader / USB mode. + // Skip that in case of the UF2 bootloader being available. uint32_t arg = 0xEB110000; ROM_RunBootloader(&arg); #else - // No custom bootloader, or run bootloader API, then just reset. + // No custom bootloader, or run bootloader API, the set + // the flag for the UF2 bootloader + // Pretend to be the first of the two reset presses needed to enter the + // bootloader. That way one reset will end in the bootloader. + DBL_TAP_REG = DBL_TAP_MAGIC; WDOG_TriggerSystemSoftwareReset(WDOG1); #endif while (1) { diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 923eff4dc7064..b45f8408e6415 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -115,6 +115,7 @@ uint32_t trng_random_u32(void); #define MICROPY_PY_MACHINE_UART_SENDBREAK (1) #define MICROPY_PY_MACHINE_UART_IRQ (1) #define MICROPY_PY_ONEWIRE (1) +#define MICROPY_PY_MACHINE_BOOTLOADER (1) // fatfs configuration used in ffconf.h #define MICROPY_FATFS_ENABLE_LFN (2) @@ -151,6 +152,7 @@ uint32_t trng_random_u32(void); #define MICROPY_HW_ENABLE_USBDEV (1) #define MICROPY_HW_USB_CDC (1) +#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1) // Hooks to add builtins diff --git a/tools/autobuild/build-boards.sh b/tools/autobuild/build-boards.sh index 801e7062e5798..bd6828cb40f50 100755 --- a/tools/autobuild/build-boards.sh +++ b/tools/autobuild/build-boards.sh @@ -99,7 +99,7 @@ function build_esp8266_boards { } function build_mimxrt_boards { - build_boards modmimxrt.c $1 $2 bin hex + build_boards modmimxrt.c $1 $2 bin hex uf2 } function build_nrf_boards { From b251aec0fcfef75b43b69c329b9a34c3703a6b90 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 5 Oct 2024 12:57:47 +0200 Subject: [PATCH 2/6] mimxrt/hal: Update the LUT and re-enable PAGEPROGRAM_QUAD. Changes: - Change the LUT table ordering to be similar to the order of the UF2-Bootloader and fsl_romapi.h. - Rewrite the LUT entry for PAGEPROGRAM_QUAD and update the LUT. That enabled QUAD program again. Signed-off-by: robert-hh --- ports/mimxrt/flash.c | 6 +-- ports/mimxrt/hal/flexspi_flash_config.h | 24 ++++++---- ports/mimxrt/hal/flexspi_hyper_flash.c | 3 ++ ports/mimxrt/hal/flexspi_nor_flash.c | 40 ++++++++-------- ports/mimxrt/hal/qspi_nor_flash_config.c | 60 +++++++++++------------- 5 files changed, 67 insertions(+), 66 deletions(-) diff --git a/ports/mimxrt/flash.c b/ports/mimxrt/flash.c index 3a18f8f51b930..7df799884e9e7 100644 --- a/ports/mimxrt/flash.c +++ b/ports/mimxrt/flash.c @@ -28,10 +28,8 @@ void flash_init(void) { // Upload the custom flash configuration - // This should be performed by the boot ROM but for some reason it is not. - FLEXSPI_UpdateLUT(BOARD_FLEX_SPI, 0, - qspiflash_config.memConfig.lookupTable, - ARRAY_SIZE(qspiflash_config.memConfig.lookupTable)); + // And fix the entry for PAGEPROGRAM_QUAD + flexspi_nor_update_lut(); // Configure FLEXSPI IP FIFO access. BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ARDFEN_MASK); diff --git a/ports/mimxrt/hal/flexspi_flash_config.h b/ports/mimxrt/hal/flexspi_flash_config.h index 5320231a1495c..7538537aeae5b 100644 --- a/ports/mimxrt/hal/flexspi_flash_config.h +++ b/ports/mimxrt/hal/flexspi_flash_config.h @@ -75,6 +75,12 @@ (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)) +#define EMPTY_LUT \ + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), \ + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), \ + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), \ + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), \ + // !@brief Definitions for FlexSPI Serial Clock Frequency typedef enum _FlexSpiSerialClockFreq { @@ -209,20 +215,20 @@ typedef struct _FlexSPIConfig } flexspi_mem_config_t; /* */ -#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 0 +#define NOR_CMD_LUT_SEQ_IDX_READ 0 #define NOR_CMD_LUT_SEQ_IDX_READSTATUSREG 1 -#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD 2 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 2 #define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE 3 -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 4 +#define NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG 4 #define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 -#define NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG 6 -#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD 7 -#define NOR_CMD_LUT_SEQ_IDX_READID 8 +#define NOR_CMD_LUT_SEQ_IDX_READQUAD 6 +#define NOR_CMD_LUT_SEQ_IDX_READID 7 +#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 #define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM 9 -#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10 +#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD 10 #define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 -#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 12 -#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 13 +// Index 12 is left empty +#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 #define HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA 0 #define HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA 1 diff --git a/ports/mimxrt/hal/flexspi_hyper_flash.c b/ports/mimxrt/hal/flexspi_hyper_flash.c index 5e5d87166d850..c0cd63ca0be8e 100644 --- a/ports/mimxrt/hal/flexspi_hyper_flash.c +++ b/ports/mimxrt/hal/flexspi_hyper_flash.c @@ -9,6 +9,9 @@ #include "fsl_clock.h" #include "flexspi_hyper_flash.h" +void flexspi_nor_update_lut(void) { +} + // Copy of a few (pseudo-)functions from fsl_clock.h, which were nor reliably // inlined when they should be. That caused DEBUG mode to fail. // It does not increase the code size, since they were supposed to be inline. diff --git a/ports/mimxrt/hal/flexspi_nor_flash.c b/ports/mimxrt/hal/flexspi_nor_flash.c index 956fb657db6dd..a890533a69661 100644 --- a/ports/mimxrt/hal/flexspi_nor_flash.c +++ b/ports/mimxrt/hal/flexspi_nor_flash.c @@ -36,6 +36,23 @@ #include #include "fsl_common.h" #include "flexspi_nor_flash.h" +#include "flexspi_flash_config.h" + +uint32_t LUT_pageprogram_quad[4] = { + // 10 Page Program - quad mode + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 24), + FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_4PAD, 0x04, STOP, FLEXSPI_1PAD, 0), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler +}; + +void flexspi_nor_update_lut(void) { + uint32_t lookuptable_copy[64]; + memcpy(lookuptable_copy, (const uint32_t *)&qspiflash_config.memConfig.lookupTable, 64 * sizeof(uint32_t)); + // write PAGEPROGRAM_QUAD code to entry 10 + memcpy(&lookuptable_copy[10 * 4], LUT_pageprogram_quad, 4 * sizeof(uint32_t)); + FLEXSPI_UpdateLUT(BOARD_FLEX_SPI, 0, lookuptable_copy, 64); +} void flexspi_nor_reset(FLEXSPI_Type *base) __attribute__((section(".ram_functions"))); void flexspi_nor_reset(FLEXSPI_Type *base) { @@ -106,9 +123,9 @@ status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base) __attribute__((section status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base) { flexspi_transfer_t flashXfer; status_t status; - uint32_t writeValue = 0x40; + uint32_t writeValue = qspiflash_config.memConfig.deviceModeArg; - /* Write neable */ + /* Write enable */ status = flexspi_nor_write_enable(base, 0); if (status != kStatus_Success) { @@ -228,22 +245,3 @@ status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, co return status; } - -status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId) __attribute__((section(".ram_functions"))); -status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId) { - uint32_t temp; - flexspi_transfer_t flashXfer; - flashXfer.deviceAddress = 0; - flashXfer.port = kFLEXSPI_PortA1; - flashXfer.cmdType = kFLEXSPI_Read; - flashXfer.SeqNumber = 1; - flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READID; - flashXfer.data = &temp; - flashXfer.dataSize = 2; - - status_t status = FLEXSPI_TransferBlocking(base, &flashXfer); - - *vendorId = temp; - - return status; -} diff --git a/ports/mimxrt/hal/qspi_nor_flash_config.c b/ports/mimxrt/hal/qspi_nor_flash_config.c index a8040737e51b0..9edf44fc64c84 100644 --- a/ports/mimxrt/hal/qspi_nor_flash_config.c +++ b/ports/mimxrt/hal/qspi_nor_flash_config.c @@ -49,76 +49,75 @@ const flexspi_nor_config_t qspiflash_config = { .seqNum = 1u, }, .deviceModeArg = 0x40, - // Enable DDR mode, Wordaddassable, Safe configuration, Differential clock .deviceType = kFlexSpiDeviceType_SerialNOR, .sflashPadType = kSerialFlash_4Pads, .serialClkFreq = MICROPY_HW_FLASH_CLK, .sflashA1Size = MICROPY_HW_FLASH_SIZE, .lookupTable = { - // 0 Read LUTs 0 -> 0 - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18), + // 0 Read LUTs 0 + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 24), FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 1 Read status register -> 1 + // 1 Read status register FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x01), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 2 Fast read quad mode - SDR - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x6B, RADDR_SDR, FLEXSPI_1PAD, 0x18), - FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x08, READ_SDR, FLEXSPI_4PAD, 0x04), + // 2 Read extend parameters + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x81, READ_SDR, FLEXSPI_1PAD, 0x04), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 3 Write Enable -> 3 + // 3 Write Enable FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 4 Read extend parameters - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x81, READ_SDR, FLEXSPI_1PAD, 0x04), + // 4 Write Status Reg + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01, WRITE_SDR, FLEXSPI_1PAD, 0x01), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 5 Erase Sector -> 5 + // 5 Erase Sector FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20, RADDR_SDR, FLEXSPI_1PAD, 24), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 6 Write Status Reg - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01, WRITE_SDR, FLEXSPI_1PAD, 0x04), - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + // 6 Fast read quad mode - SDR + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x6B, RADDR_SDR, FLEXSPI_1PAD, 24), + FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x08, READ_SDR, FLEXSPI_4PAD, 0x04), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 7 Page Program - quad mode (-> 9) - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 0x18), - FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_4PAD, 0x04, STOP, FLEXSPI_1PAD, 0), + // 7 Read ID + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x90, DUMMY_SDR, FLEXSPI_1PAD, 24), + FLEXSPI_LUT_SEQ(READ_SDR, FLEXSPI_1PAD, 0x00, 0, 0, 0), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 8 Read ID - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x90, DUMMY_SDR, FLEXSPI_1PAD, 24), - FLEXSPI_LUT_SEQ(READ_SDR, FLEXSPI_1PAD, 0x00, 0, 0, 0), + // 8 Erase Block (32k) + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x52, RADDR_SDR, FLEXSPI_1PAD, 24), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 9 Page Program - single mode -> 9 + // 9 Page Program - single mode FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02, RADDR_SDR, FLEXSPI_1PAD, 24), FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0, 0, 0, 0), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 10 Enter QPI mode - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x35, STOP, FLEXSPI_1PAD, 0), - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + // 10 Page Program - quad mode + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 24), + FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_4PAD, 0x04, STOP, FLEXSPI_1PAD, 0), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler @@ -128,15 +127,12 @@ const flexspi_nor_config_t qspiflash_config = { FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 12 Exit QPI mode - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_4PAD, 0xF5, STOP, FLEXSPI_1PAD, 0), - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + // 12 Empty LUT + EMPTY_LUT - // 13 Erase Block (32k) -> 13 - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x52, RADDR_SDR, FLEXSPI_1PAD, 24), - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + // 13 READ SDFP + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x5A, RADDR_SDR, FLEXSPI_1PAD, 24), + FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8, READ_SDR, FLEXSPI_1PAD, 0x04), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler }, From 2a80d5c68b5e03570784d18985d5388995ba0e40 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 26 Jan 2025 21:39:58 +0100 Subject: [PATCH 3/6] mimxrt/flash: Swap the order of disabling IRQ and disabling the cache. This change stopped problems with USB IRQ happening during flash writes. Signed-off-by: robert-hh --- ports/mimxrt/flash.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/ports/mimxrt/flash.c b/ports/mimxrt/flash.c index 7df799884e9e7..cdcdc7483d833 100644 --- a/ports/mimxrt/flash.c +++ b/ports/mimxrt/flash.c @@ -43,14 +43,13 @@ void flash_init(void) { __attribute__((section(".ram_functions"))) status_t flash_erase_block(uint32_t erase_addr) { status_t status = kStatus_Fail; - SCB_CleanInvalidateDCache(); - SCB_DisableDCache(); __disable_irq(); + SCB_DisableDCache(); status = flexspi_nor_flash_erase_block(BOARD_FLEX_SPI, erase_addr); - __enable_irq(); SCB_EnableDCache(); + __enable_irq(); return status; } @@ -60,14 +59,13 @@ __attribute__((section(".ram_functions"))) status_t flash_erase_block(uint32_t e __attribute__((section(".ram_functions"))) status_t flash_erase_sector(uint32_t erase_addr) { status_t status = kStatus_Fail; - SCB_CleanInvalidateDCache(); - SCB_DisableDCache(); __disable_irq(); + SCB_DisableDCache(); status = flexspi_nor_flash_erase_sector(BOARD_FLEX_SPI, erase_addr); - __enable_irq(); SCB_EnableDCache(); + __enable_irq(); return status; } @@ -83,10 +81,6 @@ __attribute__((section(".ram_functions"))) status_t flash_write_block(uint32_t d if (length == 0) { status = kStatus_Success; // Nothing to do } else { - - SCB_CleanInvalidateDCache(); - SCB_DisableDCache(); - // write data in chunks not crossing a page boundary do { next_addr = dest_addr - (dest_addr % PAGE_SIZE_BYTES) + PAGE_SIZE_BYTES; // next page boundary @@ -96,7 +90,11 @@ __attribute__((section(".ram_functions"))) status_t flash_write_block(uint32_t d } __disable_irq(); + SCB_DisableDCache(); + status = flexspi_nor_flash_page_program(BOARD_FLEX_SPI, dest_addr, (uint32_t *)src, write_length); + + SCB_EnableDCache(); __enable_irq(); // Update remaining data length @@ -106,9 +104,6 @@ __attribute__((section(".ram_functions"))) status_t flash_write_block(uint32_t d src += write_length; dest_addr += write_length; } while ((length > 0) && (status == kStatus_Success)); - - SCB_EnableDCache(); - } return status; } From 9eb9451d8377c2adc5187cfb51ef68de843b680f Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 7 Oct 2024 08:45:54 +0200 Subject: [PATCH 4/6] mimxrt/boards: Update the deploy instructions for the UF2 bootloader. Signed-off-by: robert-hh --- .../ADAFRUIT_METRO_M7/deploy_metro_m7.md | 148 ++---------------- .../boards/OLIMEX_RT1010/deploy_olimex.md | 42 ++--- ports/mimxrt/boards/SEEED_ARCH_MIX/deploy.md | 58 ++++++- ports/mimxrt/boards/deploy_mimxrt.md | 44 +++++- 4 files changed, 123 insertions(+), 169 deletions(-) diff --git a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/deploy_metro_m7.md b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/deploy_metro_m7.md index bc92016b71751..c5bfd1a28a79f 100644 --- a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/deploy_metro_m7.md +++ b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/deploy_metro_m7.md @@ -1,141 +1,11 @@ ## 1. Deploy the MicroPython firmware to the Metro M7 board. -### 1.1 Deploy the firmware using the serial bootloader. - -For initial deployment of the firmware a few preparation steps are required, which -have to be done once. - -1. Get the files ufconv.py and uf2families.json from the micropython/tools directory, -e.g. at https://github.com/micropython/micropython/tree/master/tools. - -2. Get the NXP program sdphost for your operating system, e.g. from -https://github.com/adafruit/tinyuf2/tree/master/ports/mimxrt10xx/sdphost. -You can also get them from the NXP web sites. - -3. Get the UF2 boot-loader package https://github.com/adafruit/tinyuf2/releases/download/0.9.0/tinyuf2-imxrt1010_evk-0.9.0.zip -and extract the file tinyuf2-imxrt1010_evk-0.9.0.bin. - -Now you have all files at hand that you will need for updating. - -1. Get the firmware you want to upload from the MicroPython download page. - -2. Set the two BOOTSEL DIP switches to the 1/0 position, which is the opposite position of the normal use mode. - -3. Push the reset button. - -4. Run the commands: - -``` -sudo ./sdphost -u 0x1fc9,0x0145 -- write-file 0x20206400 tinyuf2-imxrt1010_evk-0.9.0.bin -sudo ./sdphost -u 0x1fc9,0x0145 -- jump-address 0x20207000 -``` -Wait until a drive icon appears on the computer (or mount it explicitly), and then run: -``` -python3 uf2conv.py --base 0x60000400 -f 0x4fb2d5bd -``` -You can put all of that in a script. Just add a short wait before the 3rd command to let the drive connect. - -5. Once the upload is finished, set the BOOTSEL DIP switches back to the 0/1 position and push reset. - -Using sudo is Linux specific. You may not need it at all, if the access rights are set properly, -and you will not need it for Windows. - -### 1.2 Deploy the firmware using a JTAG adapter. - -With a JTAG adapter the firmware can be easily installed. Appropriate tools are Segger JFlash Lite and -the Segger Edu Mini adapter. Just use the firmware.hex file for loading, which will be loaded at the -proper address. - - -## 2. Deploy the WiFi firmware. - -The NINA firmware in the NINA module has to be updated for use with MicroPython. That can be done -using MicroPython and two small Python scripts. - -The firmware binaries are available at -https://github.com/micropython/micropython-lib/tree/master/micropython/espflash -or https://github.com/robert-hh/Shared-Stuff. For the Metro M7 board, the -NINA_FW_v1.5.0_Airlift.bin file is needed. - -For firmware upload, the following connections to the WiFi module are required: - -- Pin Reset (as above) -- Pin GPIO0 -- UART RX -- UART TX - -The GPIO pins and UART device id varies between boards. At the Adafruit Metro M7 board, -the UART is UART(1), and the Pin names for reset and GPIO0 are ESP_RESET and ESP_GPIO0. -The firmware can be uploaded, using the espflash.py module, a short script -using espflash.py and mpremote. espflash.py is available at -https://github.com/micropython/micropython-lib/tree/master/micropython/espflash. -This place also holds the example script. - -``` -import espflash -from machine import Pin -from machine import UART -import sys -sys.path.append("/flash") - -reset = Pin("ESP_RESET", Pin.OUT) -gpio0 = Pin("ESP_GPIO0", Pin.OUT) -uart = UART(0, 115200, timeout=350) - -md5sum = b"b0b9ab23da820a469e597c41364acb3a" -path = "/remote/NINA_FW_v1.5.0_Airlift.bin" - -esp = espflash.ESPFlash(reset, gpio0, uart) -# Enter bootloader download mode, at 115200 -esp.bootloader() -# Can now change to higher/lower baud rate -esp.set_baudrate(921600) -# Must call this first before any flash functions. -esp.flash_attach() -# Read flash size -size = esp.flash_read_size() -# Configure flash parameters. -esp.flash_config(size) -# Write firmware image from internal storage. -esp.flash_write_file(path) -# Compares file and flash MD5 checksum. -esp.flash_verify_file(path, md5sum) -# Resets the ESP32 chip. -esp.reboot() -``` - -The script shows the set-up for the Metro M7 board. -The md5sum is the one of the WiFi firmware. It may change and -can be recalculated using e.g. the Linux `md5sum` command. It is used to -verify the firmware upload. To upload the firmware, place the firmware -and the above script (let's call it ninaflash.py) into the same directory -on your PC, and run the command: -``` -mpremote connect mount . run ninaflash.py -``` -After a while, the upload will start. A typical start sequence looks like: -``` -Local directory . is mounted at /remote -Failed to read response to command 8. -Failed to read response to command 8. -Changing baudrate => 921600 -Flash attached -Flash size 2.0 MBytes -Flash write size: 1310720 total_blocks: 320 block size: 4096 -Writing sequence number 0/320... -Writing sequence number 1/320... -Writing sequence number 2/320... -Writing sequence number 3/320... -Writing sequence number 4/320... -.... -.... -Writing sequence number 317/320... -Writing sequence number 318/320... -Writing sequence number 319/320... -Flash write finished -Flash verify: File MD5 b'b0b9ab23da820a469e597c41364acb3a' -Flash verify: Flash MD5 b'b0b9ab23da820a469e597c41364acb3a' -Firmware verified. -``` -The initial messages `Failed to read response to command 8.` -can be ignored. +The Metro M7 board comes pre-installed with a UF2 bootloader. It can +be started by pushing reset twice. Then the bootloader drive will +appear. If that does not happen or the bootloader was lost, you can +reinstall the bootloader using the instructions by Adafruit +here: https://learn.adafruit.com/adafruit-metro-m7-microsd/installing-the-bootloader + +Once the bootloader is installed and started, you can install MicroPython +by copying the .uf2 version of the firmware file to the bootloader +drive. When the firmware is installed, the drive will disappear. diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/deploy_olimex.md b/ports/mimxrt/boards/OLIMEX_RT1010/deploy_olimex.md index 92f3df57c9b84..7abba784b940b 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/deploy_olimex.md +++ b/ports/mimxrt/boards/OLIMEX_RT1010/deploy_olimex.md @@ -1,39 +1,43 @@ -For initial deployment of the firmware a few preparation steps are required, which -have to be done once. +The Olimex RT1011 board is delivered without firmware. The best option to +install MicroPython is installing a UF2 bootstrap loader first, which then can be +used to install and update MicroPython. The bootloader has to be installed +only once. -1. Get the files ufconv.py and uf2families.json from the micropython/tools directory, -e.g. at https://github.com/micropython/micropython/tree/master/tools. +For initial deployment of the bootloader a few preparation steps are required, which +have to be done once. -2. Get the NXP program sdphost for your operating system, e.g. from +1. Get the NXP program sdphost for your operating system, e.g. from https://github.com/adafruit/tinyuf2/tree/master/ports/mimxrt10xx/sdphost. You can also get them from the NXP web sites. -3. Get the UF2 boot-loader package https://github.com/adafruit/tinyuf2/releases/download/0.9.0/tinyuf2-imxrt1010_evk-0.9.0.zip -and extract the file tinyuf2-imxrt1010_evk-0.9.0.bin. +2. Get the UF2 boot-loader package https://github.com/adafruit/tinyuf2/releases/tag/0.21.0/tinyuf2-imxrt1010_evk-0.20.1.zip and extract the files `tinyuf2-imxrt1010_evk-0.21.0.bin` +. You may as well go for a newer release. Now you have all files at hand that you will need for updating. -1. Get the firmware you want to upload from the MicroPython download page. +1. Get the firmware file you want to upload with the .uf2 extension from the MicroPython download page. 2. Push and hold the "Boot" button, then press "Reset", and release both buttons. 3. Run the commands: ``` -sudo ./sdphost -u 0x1fc9,0x0145 -- write-file 0x20206400 tinyuf2-imxrt1010_evk-0.9.0.bin +sudo ./sdphost -u 0x1fc9,0x0145 -- write-file 0x20206400 tinyuf2-imxrt1010_evk-0.21.0.bin sudo ./sdphost -u 0x1fc9,0x0145 -- jump-address 0x20207000 ``` -Wait until a drive icon appears on the computer (or mount it explicitly), and then run: -``` -python3 uf2conv.py --base 0x60000400 -f 0x4fb2d5bd -``` -You can put all of that in a script. Just add a short wait before the 3rd command to let the drive connect. - -4. Once the upload is finished, push Reset again. +Wait until a drive icon appears on the computer (or mount it explicitly). Then the UF2 bootloader +is permanently installed. Using sudo is Linux specific. You may not need it at all, if the access rights are set properly, and you will not need it for Windows. -Once the generic boot-loader is available, this procedure is only required for the first -firmware load or in case the flash is corrupted and the existing firmware is not functioning -any more. +4. Once the upload of the bootloader is finished, push Reset twice. + +The bootloader should start and show a drive icon. Copy the .uf2 version of MicroPython +to this drive to install or update MicroPython. + +Once the UF2 bootloader is installed, only step 4 is required to deploy MicroPython. If +MicroPython is already installed, the bootloader can as well be invoked by calling +`machine.bootloader()`. + +If at any time the flash content is corrupted you can always start over from the beginning. diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/deploy.md b/ports/mimxrt/boards/SEEED_ARCH_MIX/deploy.md index e91c48d46cafd..9178c717e36e6 100644 --- a/ports/mimxrt/boards/SEEED_ARCH_MIX/deploy.md +++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/deploy.md @@ -1,6 +1,52 @@ -Firmware upload to the Seed ARCH MIX board can be done using the J-Link interface -For that, follow the instructions given by Seed in their Wiki at -https://wiki.seeedstudio.com/Arch_Mix/#flashing-arduino-bootloader-to-arch-mix. -You will need a J-Link debug probe and software. What has been tested was the -Segger JLlink edu or Segger JLink edu mini. As matching loader tool you can use -Segger JFlashLite. The target address for loading is 0x60000000. +The Seeed Arch Mix board is delivered without firmware. The best option to +install MicroPython is installing a UF2 bootstrap loader first, which then can be +used to install and update MicroPython. The bootloader has to be installed +only once. + +For initial deployment of the bootloader a few preparation steps are required, which +have to be done once. + +1. Get the NXP program sdphost for your operating system, e.g. from +https://github.com/adafruit/tinyuf2/tree/master/ports/mimxrt10xx/sdphost. +You can also get them from the NXP web sites. + +2. Get the UF2 boot-loader package https://github.com/adafruit/tinyuf2/releases/tag/0.20.1/tinyuf2-imxrt1050_evkb-0.21.0.zip and extract the files `tinyuf2-imxrt1050_evkb-0.21.0.bin`. +You may as well go for a newer release. + +Now you have all files at hand that you will need for updating. + +1. Get the firmware file you want to upload with the .uf2 extension from the MicroPython download page. + +2. At the Seeed Arch Mix board, connect the RX pin (J3-19) with 3.3V, and change the DIP switches +3 an 4 at SW1 from 1-0 to 0-1. + +3. Push Reset. + +4. Run the commands: + +``` +sudo ./sdphost -u 0x1fc9,0x0130 -- write-file 0x1000 tinyuf2-imxrt1050_evkb-0.21.0.bin +sudo ./sdphost -u 0x1fc9,0x0130 -- jump-address 0x2000 +``` +Wait until a drive icon appears on the computer (or mount it explicitly). When using the above +mentioned bootloader, it has the label `RT1050BOOT`. Then the UF2 bootloader +is permanently installed. + +Using sudo is Linux specific. You may not need it at all, if the access rights are set properly, +and you will not need it for Windows. + +5. At the Seeed Arch Mix board, disconnect the RX pin (J3-19) with 3.3V, and change the DIP switches +3 an 4 at SW1 back to 1-0. + +6. Once the upload of the bootloader is finished or when it is already installed, push Reset twice. + +The bootloader should start and show a drive icon. Do not push too fast. The i.MX RT MCU +have no dedicated Reset Pin and are reset through power cycling, which may be slow. +Copy the .uf2 version of MicroPython to this drive to install or update MicroPython. +If after steps 1-4 the bootloader drive is already shown, you do not have to reset again. + +Once the UF2 bootloader is installed, only step 6 is required to deploy MicroPython. If +MicroPython is already installed, the bootloader can as well be invoked by calling +`machine.bootloader()` or switching the USB baud rate at the PC to 1200 baud and back. + +If at any time the flash content is corrupted you can always start over from the beginning. diff --git a/ports/mimxrt/boards/deploy_mimxrt.md b/ports/mimxrt/boards/deploy_mimxrt.md index 35752a8362cef..7ad21fe64ca17 100644 --- a/ports/mimxrt/boards/deploy_mimxrt.md +++ b/ports/mimxrt/boards/deploy_mimxrt.md @@ -1,11 +1,45 @@ -Firmware can be loaded to the MIMXRT development boards in various ways. The most convenient -one is using the built-in support MCU. When a PC is connected to the debug USB port, a drive -icon will appear. Firmware can be uploaded to the board by copying it to this drive. The copy -and flashing will take a few moments. At the end of the upload, the drive icon will disappear -and reappear again. Then the reset button has to be pushed, which starts the MicroPython firmware. +## Firmware installation options + +There are two ways to load the MicroPython firmware to the device: + +1. Load the MicroPython firmware directly to the device. The MicroPython +firmware files for that method have the extension .bin or .hex and are available +at the MicroPython download site. +2. Install a resident UF2 bootstrap loader to the device first and use that later for loading +MicroPython. The MicroPython firmware files for that method have the extension .uf2 +and are available at the MicroPython download site. The UF2 bootstrap loader can be obtained +from the site https://github.com/adafruit/tinyuf2. Open the recent release page and +get the version of the bootloader for your board. If there is no specific bootloader +for a specific board, get versions for the respective imxrt10xx-evk board. The file +with the .bin or .hex extension is the one to be installed first. + +## Direct loading of MicroPython or installation of the UF2 bootloader + +The MicroPython firmware or the UF2 bootstrap loader can be loaded to the MIMXRT development +boards in various ways. The most convenient one is using the built-in support MCU. When a PC +is connected to the debug USB port, a drive icon will appear. Firmware can be uploaded to +the board by copying it to this drive. The copy and flashing will take a few moments. +At the end of the upload, the drive icon will disappear and reappear again. Then the reset +button has to be pushed, which starts the MicroPython firmware. Depending on the power jumper settings, both the debug USB and OTG USB port have to be powered during firmware upload. You may as well load the firmware using the JLink port or openSDA interface with the appropriate tools. For more options, consult the user guide of the board. + +## Installing the MicroPython firmware using the UF2 bootloader + +When using the UF2 bootloader, the OTG USB port will be used. +Once the UF2 bootloader is installed, it has to be started to upload MicroPython.The +methods to start the bootloader are: + +- Push reset twice. +- Call machine.bootloader() e.g. from REPL. +- Switch the USB port shortly to 1200 baud and back. That requires MicroPython to be +installed. + +If there is no valid Firmware on the device, the bootloader will start automatically. +Once it's started, a drive ICON will appear. The MicroPython firmware file with .uf2 +extension must then be copied to that drive. When the file is copied and MicroPython +is installed, the drive disappears and MicroPython starts. From d40849d07d2523fa16070bfcae34b51b7b14942b Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 3 Feb 2025 21:12:35 +0100 Subject: [PATCH 5/6] mimxrt/boards: Add flash configuration constants to mpconfigboard.mk. And use these to initialize the LUT table properly for the various flash types. The different flash types differ by 3 parameters. Thus it is easier to just keep one copy of the qspiflash_config structure with the LUT table and update it during flash initialisation as needed. Signed-off-by: robert-hh --- ports/mimxrt/Makefile | 6 ++++ .../boards/ADAFRUIT_METRO_M7/mpconfigboard.mk | 3 ++ .../boards/MIMXRT1010_EVK/mpconfigboard.mk | 3 ++ .../boards/MIMXRT1015_EVK/mpconfigboard.mk | 3 ++ .../boards/MIMXRT1020_EVK/mpconfigboard.mk | 3 ++ .../boards/MIMXRT1050_EVK/mpconfigboard.mk | 3 ++ .../boards/MIMXRT1060_EVK/mpconfigboard.mk | 3 ++ .../boards/MIMXRT1064_EVK/mpconfigboard.mk | 3 ++ .../boards/MIMXRT1170_EVK/mpconfigboard.mk | 3 ++ .../boards/OLIMEX_RT1010/mpconfigboard.mk | 3 ++ .../boards/SEEED_ARCH_MIX/mpconfigboard.mk | 3 ++ ports/mimxrt/boards/TEENSY40/mpconfigboard.mk | 3 ++ ports/mimxrt/boards/TEENSY41/mpconfigboard.mk | 3 ++ ports/mimxrt/hal/flexspi_flash_config.h | 2 +- ports/mimxrt/hal/flexspi_nor_flash.c | 16 +++++++-- ports/mimxrt/hal/flexspi_nor_flash.h | 1 + ports/mimxrt/hal/qspi_nor_flash_config.c | 34 ++++++++----------- 17 files changed, 72 insertions(+), 23 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index ad7d853b677a5..224b38384f718 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -425,6 +425,12 @@ endif ifdef MICROPY_HW_FLASH_CLK CFLAGS += -DMICROPY_HW_FLASH_CLK=$(MICROPY_HW_FLASH_CLK) endif +ifdef MICROPY_HW_FLASH_QE_CMD + CFLAGS += -DMICROPY_HW_FLASH_QE_CMD=$(MICROPY_HW_FLASH_QE_CMD) +endif +ifdef MICROPY_HW_FLASH_QE_ARG + CFLAGS += -DMICROPY_HW_FLASH_QE_ARG=$(MICROPY_HW_FLASH_QE_ARG) +endif CFLAGS += $(CFLAGS_EXTRA) diff --git a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk index 74d3a6f0f10e3..b9c1716a7f60c 100644 --- a/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk +++ b/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.mk @@ -4,6 +4,9 @@ MCU_VARIANT = MIMXRT1011DAE5A MICROPY_FLOAT_IMPL = single MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_133MHz +MICROPY_HW_FLASH_QE_CMD = 0x31 +MICROPY_HW_FLASH_QE_ARG = 0x02 MICROPY_PY_NETWORK_NINAW10 ?= 1 MICROPY_PY_SSL ?= 1 diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk index 1aef451e2a6a5..592b89c68ecf7 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk @@ -4,6 +4,9 @@ MCU_VARIANT = MIMXRT1011DAE5A MICROPY_FLOAT_IMPL = single MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_100MHz +MICROPY_HW_FLASH_QE_CMD = 0x31 +MICROPY_HW_FLASH_QE_ARG = 0x02 USE_UF2_BOOTLOADER = 1 diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk index 0f719ac0a9753..c5d02294bc3df 100644 --- a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk @@ -4,6 +4,9 @@ MCU_VARIANT = MIMXRT1015DAF5A MICROPY_FLOAT_IMPL = single MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_100MHz +MICROPY_HW_FLASH_QE_CMD = 0x31 +MICROPY_HW_FLASH_QE_ARG = 0x02 MICROPY_BOOT_BUFFER_SIZE = (32 * 1024) diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk index 7715e669f8d09..5ef078210a2a2 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk @@ -4,6 +4,9 @@ MCU_VARIANT = MIMXRT1021DAG5A MICROPY_FLOAT_IMPL = double MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_133MHz +MICROPY_HW_FLASH_QE_CMD = 0x01 +MICROPY_HW_FLASH_QE_ARG = 0x40 MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk index ef7bbc8f56cb9..8b048c85eaa98 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk @@ -7,6 +7,9 @@ MICROPY_HW_FLASH_SIZE = 0x4000000 # 64MB MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_133MHz +MICROPY_HW_FLASH_QE_CMD = 0x01 +MICROPY_HW_FLASH_QE_ARG = 0x40 MICROPY_PY_LWIP = 1 MICROPY_PY_SSL = 1 diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk index f57aaff3b8b17..54539952fb4f9 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk @@ -4,6 +4,9 @@ MCU_VARIANT = MIMXRT1062DVJ6A MICROPY_FLOAT_IMPL = double MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_133MHz +MICROPY_HW_FLASH_QE_CMD = 0x01 +MICROPY_HW_FLASH_QE_ARG = 0x40 MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk index f175d26377abc..b393d7ed9f2c6 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk @@ -4,6 +4,9 @@ MCU_VARIANT = MIMXRT1064DVL6A MICROPY_FLOAT_IMPL = double MICROPY_HW_FLASH_TYPE = internal MICROPY_HW_FLASH_SIZE = 0x400000 # 4MB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_100MHz +MICROPY_HW_FLASH_QE_CMD = 0x31 +MICROPY_HW_FLASH_QE_ARG = 0x02 MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk index 6e5ee56aa1081..ef4ab683a215c 100644 --- a/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk +++ b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk @@ -6,6 +6,9 @@ MICROPY_FLOAT_IMPL = double MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash MICROPY_HW_FLASH_SIZE ?= 0x1000000 # 16MB MICROPY_HW_FLASH_RESERVED ?= 0x100000 # 1MB CM4 Code address space +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_133MHz +MICROPY_HW_FLASH_QE_CMD = 0x31 +MICROPY_HW_FLASH_QE_ARG = 0x02 MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x4000000 # 64MB diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk index 1de497d74e3f0..7e9987de0cfe3 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk +++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk @@ -5,6 +5,9 @@ MICROPY_FLOAT_IMPL = single MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_100MHz +MICROPY_HW_FLASH_QE_CMD = 0x01 +MICROPY_HW_FLASH_QE_ARG = 0x40 USE_UF2_BOOTLOADER = 1 diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk index c691e2dcb55c4..7ea107b00df86 100644 --- a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk +++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk @@ -4,6 +4,9 @@ MCU_VARIANT = MIMXRT1052DVL6B MICROPY_FLOAT_IMPL = double MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_133MHz +MICROPY_HW_FLASH_QE_CMD = 0x01 +MICROPY_HW_FLASH_QE_ARG = 0x40 MICROPY_HW_SDRAM_AVAIL = 1 MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk index 87c122da9d49d..9393252d1a863 100644 --- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk +++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk @@ -5,6 +5,9 @@ MICROPY_FLOAT_IMPL = double MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_133MHz +MICROPY_HW_FLASH_QE_CMD = 0x31 +MICROPY_HW_FLASH_QE_ARG = 0x02 USE_UF2_BOOTLOADER = 1 diff --git a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk index e28310d091ad2..6bb9e607f6522 100755 --- a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk +++ b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk @@ -5,6 +5,9 @@ MICROPY_FLOAT_IMPL = double MICROPY_HW_FLASH_TYPE = qspi_nor_flash MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB +MICROPY_HW_FLASH_CLK = kFlexSpiSerialClk_133MHz +MICROPY_HW_FLASH_QE_CMD = 0x31 +MICROPY_HW_FLASH_QE_ARG = 0x02 MICROPY_PY_LWIP = 1 MICROPY_PY_SSL = 1 diff --git a/ports/mimxrt/hal/flexspi_flash_config.h b/ports/mimxrt/hal/flexspi_flash_config.h index 7538537aeae5b..d9aa5ed5eab69 100644 --- a/ports/mimxrt/hal/flexspi_flash_config.h +++ b/ports/mimxrt/hal/flexspi_flash_config.h @@ -75,7 +75,7 @@ (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)) -#define EMPTY_LUT \ +#define EMPTY_LUT_SEQ \ FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), \ FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), \ FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), \ diff --git a/ports/mimxrt/hal/flexspi_nor_flash.c b/ports/mimxrt/hal/flexspi_nor_flash.c index a890533a69661..6d5b830383f68 100644 --- a/ports/mimxrt/hal/flexspi_nor_flash.c +++ b/ports/mimxrt/hal/flexspi_nor_flash.c @@ -46,11 +46,23 @@ uint32_t LUT_pageprogram_quad[4] = { FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler }; +uint32_t LUT_write_status[4] = { + // 4 Write status word for Quad mode + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, MICROPY_HW_FLASH_QE_CMD, WRITE_SDR, FLEXSPI_1PAD, 0x01), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler +}; + void flexspi_nor_update_lut(void) { uint32_t lookuptable_copy[64]; memcpy(lookuptable_copy, (const uint32_t *)&qspiflash_config.memConfig.lookupTable, 64 * sizeof(uint32_t)); + // write WRITESTATUSREG code to entry 10 + memcpy(&lookuptable_copy[NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG * 4], + LUT_write_status, 4 * sizeof(uint32_t)); // write PAGEPROGRAM_QUAD code to entry 10 - memcpy(&lookuptable_copy[10 * 4], LUT_pageprogram_quad, 4 * sizeof(uint32_t)); + memcpy(&lookuptable_copy[NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD * 4], + LUT_pageprogram_quad, 4 * sizeof(uint32_t)); FLEXSPI_UpdateLUT(BOARD_FLEX_SPI, 0, lookuptable_copy, 64); } @@ -123,7 +135,7 @@ status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base) __attribute__((section status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base) { flexspi_transfer_t flashXfer; status_t status; - uint32_t writeValue = qspiflash_config.memConfig.deviceModeArg; + uint32_t writeValue = MICROPY_HW_FLASH_QE_ARG; /* Write enable */ status = flexspi_nor_write_enable(base, 0); diff --git a/ports/mimxrt/hal/flexspi_nor_flash.h b/ports/mimxrt/hal/flexspi_nor_flash.h index 6526142af22f1..2e61effc2b7d8 100644 --- a/ports/mimxrt/hal/flexspi_nor_flash.h +++ b/ports/mimxrt/hal/flexspi_nor_flash.h @@ -47,6 +47,7 @@ extern flexspi_nor_config_t qspiflash_config; status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId); status_t flexspi_nor_init(void); void flexspi_nor_update_lut(void); +status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base); status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address); status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address); status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size); diff --git a/ports/mimxrt/hal/qspi_nor_flash_config.c b/ports/mimxrt/hal/qspi_nor_flash_config.c index 9edf44fc64c84..36ccc30fc1922 100644 --- a/ports/mimxrt/hal/qspi_nor_flash_config.c +++ b/ports/mimxrt/hal/qspi_nor_flash_config.c @@ -48,7 +48,7 @@ const flexspi_nor_config_t qspiflash_config = { .seqId = 4u, .seqNum = 1u, }, - .deviceModeArg = 0x40, + .deviceModeArg = MICROPY_HW_FLASH_QE_ARG, .deviceType = kFlexSpiDeviceType_SerialNOR, .sflashPadType = kSerialFlash_4Pads, .serialClkFreq = MICROPY_HW_FLASH_CLK, @@ -68,10 +68,7 @@ const flexspi_nor_config_t qspiflash_config = { FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler // 2 Read extend parameters - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x81, READ_SDR, FLEXSPI_1PAD, 0x04), - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + EMPTY_LUT_SEQ // 3 Write Enable FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0), @@ -80,7 +77,7 @@ const flexspi_nor_config_t qspiflash_config = { FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler // 4 Write Status Reg - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01, WRITE_SDR, FLEXSPI_1PAD, 0x01), + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, MICROPY_HW_FLASH_QE_CMD, WRITE_SDR, FLEXSPI_1PAD, 0x01), FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler @@ -92,16 +89,10 @@ const flexspi_nor_config_t qspiflash_config = { FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler // 6 Fast read quad mode - SDR - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x6B, RADDR_SDR, FLEXSPI_1PAD, 24), - FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x08, READ_SDR, FLEXSPI_4PAD, 0x04), - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + EMPTY_LUT_SEQ // 7 Read ID - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x90, DUMMY_SDR, FLEXSPI_1PAD, 24), - FLEXSPI_LUT_SEQ(READ_SDR, FLEXSPI_1PAD, 0x00, 0, 0, 0), - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + EMPTY_LUT_SEQ // 8 Erase Block (32k) FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x52, RADDR_SDR, FLEXSPI_1PAD, 24), @@ -127,14 +118,17 @@ const flexspi_nor_config_t qspiflash_config = { FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - // 12 Empty LUT - EMPTY_LUT + // 12 Not used + EMPTY_LUT_SEQ // 13 READ SDFP - FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x5A, RADDR_SDR, FLEXSPI_1PAD, 24), - FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8, READ_SDR, FLEXSPI_1PAD, 0x04), - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler - FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + EMPTY_LUT_SEQ + + // 14 Not used + EMPTY_LUT_SEQ + + // 15 Not used + EMPTY_LUT_SEQ }, }, .pageSize = 256u, From 0a433a02e1eab1c95e57129a1e828780c871be42 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 4 Feb 2025 18:17:47 +0100 Subject: [PATCH 6/6] mimxrt/hal: Set the flexspi flash CLK frequency on boot. The flash clock frequency may have been set to a different value by a bootloader. Set the frequency according to the configured value. Use a table of pre-calculated dividers to get the closest value for the flash frequency, achieving for MIMXRT10xx: 30 -> 30.85 MHz 50 -> 49.65 MHz 60 -> 60 MHz 75 -> 75.13 MHz 80 -> 80 MHz 100 -> 99.31 Mhz 133 -> 132.92 MHz 166 -> 166.15 MHz for MIMXRT1176: 30 -> 31 MHz 50 -> 52.8 MJz 60 -> 58.7 MHz 75 -> 75.4 MHz 80 -> 75.4 MHz 100 -> 105.6 MHz 133 -> 132 MHz 166 -> 176 MHz Signed-off-by: robert-hh --- ports/mimxrt/flash.c | 3 +- ports/mimxrt/hal/flexspi_hyper_flash.c | 2 +- ports/mimxrt/hal/flexspi_hyper_flash.h | 2 +- ports/mimxrt/hal/flexspi_nor_flash.c | 93 +++++++++++++++++++++++++- ports/mimxrt/hal/flexspi_nor_flash.h | 3 +- 5 files changed, 95 insertions(+), 8 deletions(-) diff --git a/ports/mimxrt/flash.c b/ports/mimxrt/flash.c index cdcdc7483d833..57091b36ddcfd 100644 --- a/ports/mimxrt/flash.c +++ b/ports/mimxrt/flash.c @@ -29,7 +29,8 @@ void flash_init(void) { // Upload the custom flash configuration // And fix the entry for PAGEPROGRAM_QUAD - flexspi_nor_update_lut(); + // Update the flash CLK + flexspi_nor_update_lut_clk(MICROPY_HW_FLASH_CLK); // Configure FLEXSPI IP FIFO access. BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ARDFEN_MASK); diff --git a/ports/mimxrt/hal/flexspi_hyper_flash.c b/ports/mimxrt/hal/flexspi_hyper_flash.c index c0cd63ca0be8e..9171640a9ed83 100644 --- a/ports/mimxrt/hal/flexspi_hyper_flash.c +++ b/ports/mimxrt/hal/flexspi_hyper_flash.c @@ -9,7 +9,7 @@ #include "fsl_clock.h" #include "flexspi_hyper_flash.h" -void flexspi_nor_update_lut(void) { +void flexspi_nor_update_lut_clk(uint32_t freq_index) { } // Copy of a few (pseudo-)functions from fsl_clock.h, which were nor reliably diff --git a/ports/mimxrt/hal/flexspi_hyper_flash.h b/ports/mimxrt/hal/flexspi_hyper_flash.h index a6454a1c9a234..40416d6e21d7f 100644 --- a/ports/mimxrt/hal/flexspi_hyper_flash.h +++ b/ports/mimxrt/hal/flexspi_hyper_flash.h @@ -47,7 +47,7 @@ extern flexspi_nor_config_t qspiflash_config; status_t flexspi_nor_hyperflash_cfi(FLEXSPI_Type *base); void flexspi_hyper_flash_init(void); -void flexspi_nor_update_lut(void); +void flexspi_nor_update_lut_clk(uint32_t freq_index); status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address); status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address); status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size); diff --git a/ports/mimxrt/hal/flexspi_nor_flash.c b/ports/mimxrt/hal/flexspi_nor_flash.c index 6d5b830383f68..7fdb6b7c13df6 100644 --- a/ports/mimxrt/hal/flexspi_nor_flash.c +++ b/ports/mimxrt/hal/flexspi_nor_flash.c @@ -38,6 +38,9 @@ #include "flexspi_nor_flash.h" #include "flexspi_flash_config.h" +bool flash_busy_status_pol = 0; +bool flash_busy_status_offset = 0; + uint32_t LUT_pageprogram_quad[4] = { // 10 Page Program - quad mode FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 24), @@ -54,16 +57,100 @@ uint32_t LUT_write_status[4] = { FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler }; -void flexspi_nor_update_lut(void) { +#if defined(MIMXRT117x_SERIES) +static uint8_t div_table_mhz[] = { + 17, // Entry 0 is out of range + 17, // 30 -> 31 MHz + 10, // 50 -> 52.8 MHz + 9, // 60 -> 58.7 MHz + 7, // 75 -> 75.4 MHz + 7, // 80 -> 75.4 MHz + 5, // 100 -> 105.6 Mhz + 4, // 133 -> 132 MHz + 3 // 166 -> 176 MHz +}; + +#else +typedef struct _ps_div_t { + uint8_t pfd480_div; + uint8_t podf_div; +} ps_div_t; + +static ps_div_t div_table_mhz[] = { + { 35, 8 }, // Entry 0 is out of range + { 35, 8 }, // 30 -> 30.85 MHz + { 29, 6 }, // 50 -> 49.65 MHz + { 18, 8 }, // 60 -> 60 MHz + { 23, 5 }, // 75 -> 75.13 MHz + { 18, 6 }, // 80 -> 80 MHz + { 17, 5 }, // 100 -> 191 Mhz + { 13, 5 }, // 133 -> 132.92 MHz + { 13, 4 } // 166 -> 166.15 MHz +}; +#endif + +__attribute__((section(".ram_functions"))) void flexspi_nor_update_lut_clk(uint32_t freq_index) { + // Create a local copy of the LookupTable. Modify the entry for WRITESTATUSREG + // Add an entry for PAGEPROGRAM_QUAD. uint32_t lookuptable_copy[64]; memcpy(lookuptable_copy, (const uint32_t *)&qspiflash_config.memConfig.lookupTable, 64 * sizeof(uint32_t)); - // write WRITESTATUSREG code to entry 10 + // write local WRITESTATUSREG code to index 4 memcpy(&lookuptable_copy[NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG * 4], LUT_write_status, 4 * sizeof(uint32_t)); - // write PAGEPROGRAM_QUAD code to entry 10 + // write local PAGEPROGRAM_QUAD code to index 10 memcpy(&lookuptable_copy[NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD * 4], LUT_pageprogram_quad, 4 * sizeof(uint32_t)); + // Update the LookupTable. FLEXSPI_UpdateLUT(BOARD_FLEX_SPI, 0, lookuptable_copy, 64); + + __DSB(); + __ISB(); + __disable_irq(); + SCB_DisableDCache(); + + #if defined(MIMXRT117x_SERIES) + volatile uint8_t pll2_div = div_table_mhz[freq_index] - 1; + + while (!FLEXSPI_GetBusIdleStatus(BOARD_FLEX_SPI)) { + } + FLEXSPI_Enable(BOARD_FLEX_SPI, false); + + // Disable FlexSPI clock + // Flexspi is clocked by PLL2. Only the divider can be changed. + CCM->LPCG[kCLOCK_Flexspi1].DIRECT = ((uint32_t)kCLOCK_Off & CCM_LPCG_DIRECT_ON_MASK); + // Change the PLL divider + CCM->CLOCK_ROOT[kCLOCK_Root_Flexspi1].CONTROL = (CCM->CLOCK_ROOT[kCLOCK_Root_Flexspi1].CONTROL & ~CCM_CLOCK_ROOT_CONTROL_DIV_MASK) | + CCM_CLOCK_ROOT_CONTROL_DIV(pll2_div); + // Re-enable FlexSPI clock + CCM->LPCG[kCLOCK_Flexspi1].DIRECT = ((uint32_t)kCLOCK_On & CCM_LPCG_DIRECT_ON_MASK); + + #else + + volatile uint8_t pfd480_div = div_table_mhz[freq_index].pfd480_div; + volatile uint8_t podf_div = div_table_mhz[freq_index].podf_div - 1; + + while (!FLEXSPI_GetBusIdleStatus(BOARD_FLEX_SPI)) { + } + FLEXSPI_Enable(BOARD_FLEX_SPI, false); + + // Disable FlexSPI clock + CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK; + // Changing the clock is OK now. + // Change the PFD + CCM_ANALOG->PFD_480 = (CCM_ANALOG->PFD_480 & ~CCM_ANALOG_PFD_480_TOG_PFD0_FRAC_MASK) | CCM_ANALOG_PFD_480_TOG_PFD0_FRAC(pfd480_div); + // Change the flexspi divider + CCM->CSCMR1 = (CCM->CSCMR1 & ~CCM_CSCMR1_FLEXSPI_PODF_MASK) | CCM_CSCMR1_FLEXSPI_PODF(podf_div); + // Re-enable FlexSPI + CCM->CCGR6 |= CCM_CCGR6_CG5_MASK; + #endif + + FLEXSPI_Enable(BOARD_FLEX_SPI, true); + FLEXSPI_SoftwareReset(BOARD_FLEX_SPI); + while (!FLEXSPI_GetBusIdleStatus(BOARD_FLEX_SPI)) { + } + + SCB_EnableDCache(); + __enable_irq(); } void flexspi_nor_reset(FLEXSPI_Type *base) __attribute__((section(".ram_functions"))); diff --git a/ports/mimxrt/hal/flexspi_nor_flash.h b/ports/mimxrt/hal/flexspi_nor_flash.h index 2e61effc2b7d8..dc5798d97f409 100644 --- a/ports/mimxrt/hal/flexspi_nor_flash.h +++ b/ports/mimxrt/hal/flexspi_nor_flash.h @@ -45,8 +45,7 @@ extern flexspi_nor_config_t qspiflash_config; status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId); -status_t flexspi_nor_init(void); -void flexspi_nor_update_lut(void); +void flexspi_nor_update_lut_clk(uint32_t freq_index); status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base); status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address); status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address);