diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index b4f581ccdc..7feab6cd75 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -17,6 +17,7 @@ QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h # MicroPython feature configurations FROZEN_MANIFEST ?= boards/manifest.py +MICROPY_VFS_LFS2 ?= 1 # Include py core make definitions include $(TOP)/py/py.mk @@ -24,7 +25,7 @@ include $(TOP)/py/py.mk GIT_SUBMODULES = lib/tinyusb lib/nxp_driver MCU_DIR = lib/nxp_driver/sdk/devices/$(MCU_SERIES) -LD_FILES = boards/$(MCU_SERIES).ld $(TOP)/$(MCU_DIR)/gcc/$(MCU_SERIES)xxxxx_flexspi_nor.ld +LD_FILES = boards/$(BOARD)/$(BOARD).ld boards/$(MCU_SERIES).ld boards/common.ld MAKE_PINS = boards/make-pins.py BOARD_PINS = $(BOARD_DIR)/pins.csv @@ -59,8 +60,10 @@ CFLAGS += -DXIP_EXTERNAL_FLASH=1 \ -DXIP_BOOT_HEADER_ENABLE=1 \ -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX \ -D__STARTUP_CLEAR_BSS \ + -D__STARTUP_INITIALIZE_RAMFUNCTION \ -D__START=main \ -DCPU_HEADER_H='<$(MCU_SERIES).h>' +CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) LDFLAGS = $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref --print-memory-usage LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) @@ -101,6 +104,8 @@ SRC_TINYUSB_IMX_C += \ $(MCU_DIR)/drivers/fsl_common.c \ $(MCU_DIR)/drivers/fsl_lpuart.c \ $(MCU_DIR)/drivers/fsl_flexram.c \ + $(MCU_DIR)/drivers/fsl_flexspi.c \ + $(MCU_DIR)/drivers/fsl_trng.c \ SRC_C = \ main.c \ @@ -112,15 +117,20 @@ SRC_C = \ $(BOARD_DIR)/flash_config.c \ machine_led.c \ machine_pin.c \ + mimxrt_flash.c \ modutime.c \ modmachine.c \ + modmimxrt.c \ + moduos.c \ mphalport.c \ + hal/flexspi_nor_flash.c \ lib/mp-readline/readline.c \ lib/libc/string0.c \ lib/utils/gchelper_native.c \ lib/utils/printf.c \ lib/utils/pyexec.c \ lib/utils/stdout_helpers.c \ + lib/utils/sys_stdio_mphal.c \ $(SRC_TINYUSB_C) \ $(SRC_TINYUSB_IMX_C) \ @@ -132,15 +142,20 @@ SRC_S = lib/utils/gchelper_m3.s \ SRC_QSTR += \ machine_led.c \ machine_pin.c \ + mimxrt_flash.c \ modutime.c \ modmachine.c \ + modmimxrt.c \ + moduos.c \ pin.c \ + lib/utils/sys_stdio_mphal.c \ $(GEN_PINS_SRC) \ OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_SS:.S=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(BUILD)/pins_gen.o # Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };" diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/MIMXRT1010_EVK.ld b/ports/mimxrt/boards/MIMXRT1010_EVK/MIMXRT1010_EVK.ld new file mode 100644 index 0000000000..83da7ec73c --- /dev/null +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/MIMXRT1010_EVK.ld @@ -0,0 +1 @@ +flash_size = 16M; \ No newline at end of file diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/evkmimxrt1010_flexspi_nor_config.h b/ports/mimxrt/boards/MIMXRT1010_EVK/evkmimxrt1010_flexspi_nor_config.h index 8fa31c8320..2cb4535edc 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/evkmimxrt1010_flexspi_nor_config.h +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/evkmimxrt1010_flexspi_nor_config.h @@ -211,34 +211,19 @@ typedef struct _FlexSPIConfig } flexspi_mem_config_t; /* */ -#define NOR_CMD_INDEX_READ CMD_INDEX_READ //!< 0 -#define NOR_CMD_INDEX_READSTATUS CMD_INDEX_READSTATUS //!< 1 -#define NOR_CMD_INDEX_WRITEENABLE CMD_INDEX_WRITEENABLE //!< 2 -#define NOR_CMD_INDEX_ERASESECTOR 3 //!< 3 -#define NOR_CMD_INDEX_PAGEPROGRAM CMD_INDEX_WRITE //!< 4 -#define NOR_CMD_INDEX_CHIPERASE 5 //!< 5 -#define NOR_CMD_INDEX_DUMMY 6 //!< 6 -#define NOR_CMD_INDEX_ERASEBLOCK 7 //!< 7 - -#define NOR_CMD_LUT_SEQ_IDX_READ CMD_LUT_SEQ_IDX_READ //!< 0 READ LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS \ - CMD_LUT_SEQ_IDX_READSTATUS //!< 1 Read Status LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI \ - 2 //!< 2 Read status DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE \ - CMD_LUT_SEQ_IDX_WRITEENABLE //!< 3 Write Enable sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE_XPI \ - 4 //!< 4 Write Enable DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 //!< 5 Erase Sector sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 //!< 8 Erase Block sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM \ - CMD_LUT_SEQ_IDX_WRITE //!< 9 Program sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 //!< 11 Chip Erase sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 //!< 13 Read SFDP sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_RESTORE_NOCMD \ - 14 //!< 14 Restore 0-4-4/0-8-8 mode sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_EXIT_NOCMD \ - 15 //!< 15 Exit 0-4-4/0-8-8 mode sequence id in lookupTable stored in config blobk +#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 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_WRITEENABLE 3 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 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_PAGEPROGRAM 9 +#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10 +#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 +#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 12 /* * Serial NOR configuration block @@ -259,6 +244,9 @@ typedef struct _flexspi_nor_config uint32_t reserve2[11]; //!< Reserved for future use } flexspi_nor_config_t; +#define FLASH_BUSY_STATUS_POL 0 +#define FLASH_BUSY_STATUS_OFFSET 0 + #ifdef __cplusplus extern "C" { #endif diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/flash_config.c b/ports/mimxrt/boards/MIMXRT1010_EVK/flash_config.c index a03ee07865..5e7e5dcf15 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/flash_config.c +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/flash_config.c @@ -37,9 +37,83 @@ const flexspi_nor_config_t qspiflash_config = { .sflashA1Size = 16u * 1024u * 1024u, .lookupTable = { - // Read LUTs + // 0 Read LUTs 0 -> 0 FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18), 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 + 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), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 3 Write Enable -> 3 + 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), + 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 + 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 + 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), + 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), + 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 + 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 + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 11 Erase Chip + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, 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 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 }, }, .pageSize = 256u, diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h index 5a89423b50..3eb3268125 100644 --- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h @@ -7,3 +7,4 @@ #define MICROPY_HW_LED1_PIN (pin_GPIO_11) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) +#define BOARD_FLASH_CONFIG_HEADER_H "evkmimxrt1010_flexspi_nor_config.h" diff --git a/ports/mimxrt/boards/MIMXRT1011.ld b/ports/mimxrt/boards/MIMXRT1011.ld index 9db30adee8..d9a4956856 100644 --- a/ports/mimxrt/boards/MIMXRT1011.ld +++ b/ports/mimxrt/boards/MIMXRT1011.ld @@ -1,5 +1,25 @@ -/* 24kiB stack. */ -__stack_size__ = 0x4000; +/* Memory configuration */ +flash_start = 0x60000000; +flash_end = DEFINED(reserved_size) ? ((flash_start) + (flash_size - reserved_size)) : ((flash_start) + (flash_size)); +flash_config_start = 0x60000400; +flash_config_size = 0x00000C00; +ivt_start = 0x60001000; +ivt_size = 0x00001000; +interrupts_start = 0x60002000; +interrupts_size = 0x00000400; +text_start = 0x60002400; +text_size = ((((text_start) + 1M) + (4k - 1)) & ~(4k - 1)) - (text_start); /* reserve 1M for code but align on 4k boundary */ +vfs_start = (text_start) + (text_size); +vfs_size = ((flash_end) - (vfs_start)); +itcm_start = 0x00000000; +itcm_size = 0x00008000; +dtcm_start = 0x20000000; +dtcm_size = 0x00008000; +ocrm_start = 0x20200000; +ocrm_size = 0x00010000; + +/* 20kiB stack. */ +__stack_size__ = 0x5000; _estack = __StackTop; _sstack = __StackLimit; @@ -7,5 +27,5 @@ _sstack = __StackLimit; __heap_size__ = 0; /* Use second OCRAM bank for GC heap. */ -_gc_heap_start = ORIGIN(m_data2); -_gc_heap_end = ORIGIN(m_data2) + LENGTH(m_data2); +_gc_heap_start = ORIGIN(m_ocrm); +_gc_heap_end = ORIGIN(m_ocrm) + LENGTH(m_ocrm); diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/MIMXRT1020_EVK.ld b/ports/mimxrt/boards/MIMXRT1020_EVK/MIMXRT1020_EVK.ld new file mode 100644 index 0000000000..fd1bf32ede --- /dev/null +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/MIMXRT1020_EVK.ld @@ -0,0 +1 @@ +flash_size = 8M; \ No newline at end of file diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/evkmimxrt1020_flexspi_nor_config.h b/ports/mimxrt/boards/MIMXRT1020_EVK/evkmimxrt1020_flexspi_nor_config.h index c0c6ea2436..195c0c225e 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/evkmimxrt1020_flexspi_nor_config.h +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/evkmimxrt1020_flexspi_nor_config.h @@ -212,34 +212,19 @@ typedef struct _FlexSPIConfig } flexspi_mem_config_t; /* */ -#define NOR_CMD_INDEX_READ CMD_INDEX_READ //!< 0 -#define NOR_CMD_INDEX_READSTATUS CMD_INDEX_READSTATUS //!< 1 -#define NOR_CMD_INDEX_WRITEENABLE CMD_INDEX_WRITEENABLE //!< 2 -#define NOR_CMD_INDEX_ERASESECTOR 3 //!< 3 -#define NOR_CMD_INDEX_PAGEPROGRAM CMD_INDEX_WRITE //!< 4 -#define NOR_CMD_INDEX_CHIPERASE 5 //!< 5 -#define NOR_CMD_INDEX_DUMMY 6 //!< 6 -#define NOR_CMD_INDEX_ERASEBLOCK 7 //!< 7 - -#define NOR_CMD_LUT_SEQ_IDX_READ CMD_LUT_SEQ_IDX_READ //!< 0 READ LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS \ - CMD_LUT_SEQ_IDX_READSTATUS //!< 1 Read Status LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI \ - 2 //!< 2 Read status DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE \ - CMD_LUT_SEQ_IDX_WRITEENABLE //!< 3 Write Enable sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE_XPI \ - 4 //!< 4 Write Enable DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 //!< 5 Erase Sector sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 //!< 8 Erase Block sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM \ - CMD_LUT_SEQ_IDX_WRITE //!< 9 Program sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 //!< 11 Chip Erase sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 //!< 13 Read SFDP sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_RESTORE_NOCMD \ - 14 //!< 14 Restore 0-4-4/0-8-8 mode sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_EXIT_NOCMD \ - 15 //!< 15 Exit 0-4-4/0-8-8 mode sequence id in lookupTable stored in config blobk +#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 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_WRITEENABLE 3 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 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_PAGEPROGRAM 9 +#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10 +#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 +#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 12 /* * Serial NOR configuration block @@ -260,6 +245,9 @@ typedef struct _flexspi_nor_config uint32_t reserve2[11]; //!< Reserved for future use } flexspi_nor_config_t; +#define FLASH_BUSY_STATUS_POL 0 +#define FLASH_BUSY_STATUS_OFFSET 0 + #ifdef __cplusplus extern "C" { #endif diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/flash_config.c b/ports/mimxrt/boards/MIMXRT1020_EVK/flash_config.c index 56007931a9..5377cc1b25 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/flash_config.c +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/flash_config.c @@ -32,20 +32,105 @@ const flexspi_nor_config_t qspiflash_config = { .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad, .csHoldTime = 3u, .csSetupTime = 3u, + .busyOffset = FLASH_BUSY_STATUS_OFFSET, // Status bit 0 indicates busy. + .busyBitPolarity = FLASH_BUSY_STATUS_POL, // Busy when the bit is 1. + .deviceModeCfgEnable = 1u, + .deviceModeType = kDeviceConfigCmdType_QuadEnable, + .deviceModeSeq = { + .seqId = 4u, + .seqNum = 1u, + }, + .deviceModeArg = 0x40, // Enable DDR mode, Wordaddassable, Safe configuration, Differential clock + .deviceType = kFlexSpiDeviceType_SerialNOR, .sflashPadType = kSerialFlash_4Pads, - .serialClkFreq = kFlexSpiSerialClk_100MHz, + .serialClkFreq = kFlexSpiSerialClk_30MHz, .sflashA1Size = 8u * 1024u * 1024u, .lookupTable = { - // Read LUTs + // 0 Read LUTs 0 -> 0 FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18), 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 + 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), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 3 Write Enable -> 3 + 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), + 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 + 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 + 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), + 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), + 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 + 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 + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 11 Erase Chip + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, 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 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 }, }, .pageSize = 256u, .sectorSize = 4u * 1024u, .blockSize = 256u * 1024u, .isUniformBlockSize = false, + .ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz, }; #endif /* XIP_BOOT_HEADER_ENABLE */ diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h index d8c0f00e27..a025c85bf3 100644 --- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h @@ -8,3 +8,4 @@ #define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_05) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) +#define BOARD_FLASH_CONFIG_HEADER_H "evkmimxrt1020_flexspi_nor_config.h" diff --git a/ports/mimxrt/boards/MIMXRT1021.ld b/ports/mimxrt/boards/MIMXRT1021.ld index 6b59649fca..de0f259dcc 100644 --- a/ports/mimxrt/boards/MIMXRT1021.ld +++ b/ports/mimxrt/boards/MIMXRT1021.ld @@ -1,8 +1,28 @@ +/* Memory configuration */ +flash_start = 0x60000000; +flash_end = DEFINED(reserved_size) ? ((flash_start) + (flash_size - reserved_size)) : ((flash_start) + (flash_size)); +flash_config_start = flash_start; +flash_config_size = 0x00001000; +ivt_start = 0x60001000; +ivt_size = 0x00001000; +interrupts_start = 0x60002000; +interrupts_size = 0x00000400; +text_start = 0x60002400; +text_size = ((((text_start) + 1M) + (4k - 1)) & ~(4k - 1)) - (text_start); /* reserve 1M for code but align on 4k boundary */ +vfs_start = (text_start) + (text_size); +vfs_size = ((flash_end) - (vfs_start)); +itcm_start = 0x00000000; +itcm_size = 0x00010000; +dtcm_start = 0x20000000; +dtcm_size = 0x00010000; +ocrm_start = 0x20200000; +ocrm_size = 0x00020000; + /* 24kiB stack. */ __stack_size__ = 0x6000; _estack = __StackTop; _sstack = __StackLimit; /* Use second OCRAM bank for GC heap. */ -_gc_heap_start = ORIGIN(m_data2); -_gc_heap_end = ORIGIN(m_data2) + LENGTH(m_data2); +_gc_heap_start = ORIGIN(m_ocrm); +_gc_heap_end = ORIGIN(m_ocrm) + LENGTH(m_ocrm); diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/MIMXRT1050_EVK.ld b/ports/mimxrt/boards/MIMXRT1050_EVK/MIMXRT1050_EVK.ld new file mode 100644 index 0000000000..fd1bf32ede --- /dev/null +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/MIMXRT1050_EVK.ld @@ -0,0 +1 @@ +flash_size = 8M; \ No newline at end of file diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/evkmimxrt1050_flexspi_nor_config.h b/ports/mimxrt/boards/MIMXRT1050_EVK/evkmimxrt1050_flexspi_nor_config.h index d8e842452e..e038967e17 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/evkmimxrt1050_flexspi_nor_config.h +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/evkmimxrt1050_flexspi_nor_config.h @@ -209,34 +209,19 @@ typedef struct _FlexSPIConfig } flexspi_mem_config_t; /* */ -#define NOR_CMD_INDEX_READ CMD_INDEX_READ //!< 0 -#define NOR_CMD_INDEX_READSTATUS CMD_INDEX_READSTATUS //!< 1 -#define NOR_CMD_INDEX_WRITEENABLE CMD_INDEX_WRITEENABLE //!< 2 -#define NOR_CMD_INDEX_ERASESECTOR 3 //!< 3 -#define NOR_CMD_INDEX_PAGEPROGRAM CMD_INDEX_WRITE //!< 4 -#define NOR_CMD_INDEX_CHIPERASE 5 //!< 5 -#define NOR_CMD_INDEX_DUMMY 6 //!< 6 -#define NOR_CMD_INDEX_ERASEBLOCK 7 //!< 7 - -#define NOR_CMD_LUT_SEQ_IDX_READ CMD_LUT_SEQ_IDX_READ //!< 0 READ LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS \ - CMD_LUT_SEQ_IDX_READSTATUS //!< 1 Read Status LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI \ - 2 //!< 2 Read status DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE \ - CMD_LUT_SEQ_IDX_WRITEENABLE //!< 3 Write Enable sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE_XPI \ - 4 //!< 4 Write Enable DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 //!< 5 Erase Sector sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 //!< 8 Erase Block sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM \ - CMD_LUT_SEQ_IDX_WRITE //!< 9 Program sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 //!< 11 Chip Erase sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 //!< 13 Read SFDP sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_RESTORE_NOCMD \ - 14 //!< 14 Restore 0-4-4/0-8-8 mode sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_EXIT_NOCMD \ - 15 //!< 15 Exit 0-4-4/0-8-8 mode sequence id in lookupTable stored in config blobk +#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 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_WRITEENABLE 3 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 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_PAGEPROGRAM 9 +#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10 +#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 +#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 12 /* * Serial NOR configuration block @@ -257,6 +242,9 @@ typedef struct _flexspi_nor_config uint32_t reserve2[11]; //!< Reserved for future use } flexspi_nor_config_t; +#define FLASH_BUSY_STATUS_POL 0 +#define FLASH_BUSY_STATUS_OFFSET 0 + #ifdef __cplusplus extern "C" { #endif diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/flash_config.c b/ports/mimxrt/boards/MIMXRT1050_EVK/flash_config.c index 8203f4811a..2a9303fc98 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/flash_config.c +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/flash_config.c @@ -41,10 +41,83 @@ const flexspi_nor_config_t qspiflash_config = { .dataValidTime = {16u, 16u}, .lookupTable = { - // Read LUTs - FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0xA0, RADDR_DDR, FLEXSPI_8PAD, 0x18), - FLEXSPI_LUT_SEQ(CADDR_DDR, FLEXSPI_8PAD, 0x10, DUMMY_DDR, FLEXSPI_8PAD, 0x06), - FLEXSPI_LUT_SEQ(READ_DDR, FLEXSPI_8PAD, 0x04, STOP, FLEXSPI_1PAD, 0x0), + // 0 Read LUTs 0 -> 0 + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18), + 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 + 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), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 3 Write Enable -> 3 + 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), + 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 + 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 + 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), + 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), + 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 + 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 + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 11 Erase Chip + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, 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 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 }, }, .pageSize = 512u, diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h index 2337496d2a..9b7664841e 100644 --- a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h @@ -7,3 +7,4 @@ #define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_09) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) +#define BOARD_FLASH_CONFIG_HEADER_H "evkmimxrt1050_flexspi_nor_config.h" diff --git a/ports/mimxrt/boards/MIMXRT1052.ld b/ports/mimxrt/boards/MIMXRT1052.ld index 836a119e5e..f78773531a 100644 --- a/ports/mimxrt/boards/MIMXRT1052.ld +++ b/ports/mimxrt/boards/MIMXRT1052.ld @@ -1,7 +1,28 @@ +/* Memory configuration */ +flash_start = 0x60000000; +flash_end = DEFINED(reserved_size) ? ((flash_start) + (flash_size - reserved_size)) : ((flash_start) + (flash_size)); +flash_config_start = flash_start; +flash_config_size = 0x00001000; +ivt_start = 0x60001000; +ivt_size = 0x00001000; +interrupts_start = 0x60002000; +interrupts_size = 0x00000400; +text_start = 0x60002400; +text_size = ((((text_start) + 1M) + (4k - 1)) & ~(4k - 1)) - (text_start); /* reserve 1M for code but align on 4k boundary */ +vfs_start = (text_start) + (text_size); +vfs_size = ((flash_end) - (vfs_start)); +itcm_start = 0x00000000; +itcm_size = 0x00020000; +dtcm_start = 0x20000000; +dtcm_size = 0x00020000; +ocrm_start = 0x20200000; +ocrm_size = 0x00040000; + +/* 24kiB stack. */ __stack_size__ = 0x6000; _estack = __StackTop; _sstack = __StackLimit; /* Use second OCRAM bank for GC heap. */ -_gc_heap_start = ORIGIN(m_data2); -_gc_heap_end = ORIGIN(m_data2) + LENGTH(m_data2); +_gc_heap_start = ORIGIN(m_ocrm); +_gc_heap_end = ORIGIN(m_ocrm) + LENGTH(m_ocrm); diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/MIMXRT1060_EVK.ld b/ports/mimxrt/boards/MIMXRT1060_EVK/MIMXRT1060_EVK.ld new file mode 100644 index 0000000000..fd1bf32ede --- /dev/null +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/MIMXRT1060_EVK.ld @@ -0,0 +1 @@ +flash_size = 8M; \ No newline at end of file diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/evkmimxrt1060_flexspi_nor_config.h b/ports/mimxrt/boards/MIMXRT1060_EVK/evkmimxrt1060_flexspi_nor_config.h index 8bb771fd8a..03bdac1f1c 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/evkmimxrt1060_flexspi_nor_config.h +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/evkmimxrt1060_flexspi_nor_config.h @@ -210,34 +210,19 @@ typedef struct _FlexSPIConfig } flexspi_mem_config_t; /* */ -#define NOR_CMD_INDEX_READ CMD_INDEX_READ //!< 0 -#define NOR_CMD_INDEX_READSTATUS CMD_INDEX_READSTATUS //!< 1 -#define NOR_CMD_INDEX_WRITEENABLE CMD_INDEX_WRITEENABLE //!< 2 -#define NOR_CMD_INDEX_ERASESECTOR 3 //!< 3 -#define NOR_CMD_INDEX_PAGEPROGRAM CMD_INDEX_WRITE //!< 4 -#define NOR_CMD_INDEX_CHIPERASE 5 //!< 5 -#define NOR_CMD_INDEX_DUMMY 6 //!< 6 -#define NOR_CMD_INDEX_ERASEBLOCK 7 //!< 7 - -#define NOR_CMD_LUT_SEQ_IDX_READ CMD_LUT_SEQ_IDX_READ //!< 0 READ LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS \ - CMD_LUT_SEQ_IDX_READSTATUS //!< 1 Read Status LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI \ - 2 //!< 2 Read status DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE \ - CMD_LUT_SEQ_IDX_WRITEENABLE //!< 3 Write Enable sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE_XPI \ - 4 //!< 4 Write Enable DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 //!< 5 Erase Sector sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 //!< 8 Erase Block sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM \ - CMD_LUT_SEQ_IDX_WRITE //!< 9 Program sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 //!< 11 Chip Erase sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 //!< 13 Read SFDP sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_RESTORE_NOCMD \ - 14 //!< 14 Restore 0-4-4/0-8-8 mode sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_EXIT_NOCMD \ - 15 //!< 15 Exit 0-4-4/0-8-8 mode sequence id in lookupTable stored in config blobk +#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 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_WRITEENABLE 3 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 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_PAGEPROGRAM 9 +#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10 +#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 +#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 12 /* * Serial NOR configuration block @@ -258,6 +243,9 @@ typedef struct _flexspi_nor_config uint32_t reserve2[11]; //!< Reserved for future use } flexspi_nor_config_t; +#define FLASH_BUSY_STATUS_POL 0 +#define FLASH_BUSY_STATUS_OFFSET 0 + #ifdef __cplusplus extern "C" { #endif diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/flash_config.c b/ports/mimxrt/boards/MIMXRT1060_EVK/flash_config.c index 095a922e9e..3fa584b73a 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/flash_config.c +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/flash_config.c @@ -35,9 +35,83 @@ const flexspi_nor_config_t qspiflash_config = { .sflashA1Size = 8u * 1024u * 1024u, .lookupTable = { - // Read LUTs + // 0 Read LUTs 0 -> 0 FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18), 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 + 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), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 3 Write Enable -> 3 + 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), + 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 + 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 + 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), + 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), + 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 + 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 + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 11 Erase Chip + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, 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 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 }, }, .pageSize = 256u, diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h index c9e6d8bf2c..3974f93257 100644 --- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h @@ -7,3 +7,4 @@ #define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_09) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) +#define BOARD_FLASH_CONFIG_HEADER_H "evkmimxrt1060_flexspi_nor_config.h" diff --git a/ports/mimxrt/boards/MIMXRT1062.ld b/ports/mimxrt/boards/MIMXRT1062.ld index 23520b5624..5ab7e15332 100644 --- a/ports/mimxrt/boards/MIMXRT1062.ld +++ b/ports/mimxrt/boards/MIMXRT1062.ld @@ -1,8 +1,28 @@ +/* Memory configuration */ +flash_start = 0x60000000; +flash_end = DEFINED(reserved_size) ? ((flash_start) + (flash_size - reserved_size)) : ((flash_start) + (flash_size)); +flash_config_start = flash_start; +flash_config_size = 0x00001000; +ivt_start = 0x60001000; +ivt_size = 0x00001000; +interrupts_start = 0x60002000; +interrupts_size = 0x00000400; +text_start = 0x60002400; +text_size = ((((text_start) + 1M) + (4k - 1)) & ~(4k - 1)) - (text_start); /* reserve 1M for code but align on 4k boundary */ +vfs_start = (text_start) + (text_size); +vfs_size = ((flash_end) - (vfs_start)); +itcm_start = 0x00000000; +itcm_size = 0x00020000; +dtcm_start = 0x20000000; +dtcm_size = 0x00020000; +ocrm_start = 0x20200000; +ocrm_size = 0x000C0000; + /* 32kiB stack. */ __stack_size__ = 0x8000; _estack = __StackTop; _sstack = __StackLimit; /* Use second OCRAM bank for GC heap. */ -_gc_heap_start = ORIGIN(m_data2); -_gc_heap_end = ORIGIN(m_data2) + LENGTH(m_data2); +_gc_heap_start = ORIGIN(m_ocrm); +_gc_heap_end = ORIGIN(m_ocrm) + LENGTH(m_ocrm); diff --git a/ports/mimxrt/boards/MIMXRT1064.ld b/ports/mimxrt/boards/MIMXRT1064.ld index bf37c21802..236d984293 100644 --- a/ports/mimxrt/boards/MIMXRT1064.ld +++ b/ports/mimxrt/boards/MIMXRT1064.ld @@ -1,8 +1,28 @@ +/* Memory configuration */ +flash_start = 0x60000000; +flash_end = DEFINED(reserved_size) ? ((flash_start) + (flash_size - reserved_size)) : ((flash_start) + (flash_size)); +flash_config_start = flash_start; +flash_config_size = 0x00001000; +ivt_start = 0x60001000; +ivt_size = 0x00001000; +interrupts_start = 0x60002000; +interrupts_size = 0x00000400; +text_start = 0x60002400; +text_size = ((((text_start) + 1M) + (4k - 1)) & ~(4k - 1)) - (text_start); /* reserve 1M for code but align on 4k boundary */ +vfs_start = (text_start) + (text_size); +vfs_size = ((flash_end) - (vfs_start)); +itcm_start = 0x00000000; +itcm_size = 0x00020000; +dtcm_start = 0x20000000; +dtcm_size = 0x00020000; +ocrm_start = 0x20200000; +ocrm_size = 0x000C0000; + /* 24kiB stack. */ __stack_size__ = 0x6000; _estack = __StackTop; _sstack = __StackLimit; /* Use second OCRAM bank for GC heap. */ -_gc_heap_start = ORIGIN(m_data2); -_gc_heap_end = ORIGIN(m_data2) + LENGTH(m_data2); \ No newline at end of file +_gc_heap_start = ORIGIN(m_ocrm); +_gc_heap_end = ORIGIN(m_ocrm) + LENGTH(m_ocrm); \ No newline at end of file diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/MIMXRT1064_EVK.ld b/ports/mimxrt/boards/MIMXRT1064_EVK/MIMXRT1064_EVK.ld new file mode 100644 index 0000000000..fd1bf32ede --- /dev/null +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/MIMXRT1064_EVK.ld @@ -0,0 +1 @@ +flash_size = 8M; \ No newline at end of file diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/evkmimxrt1064_flexspi_nor_config.h b/ports/mimxrt/boards/MIMXRT1064_EVK/evkmimxrt1064_flexspi_nor_config.h index efdfe583fb..3c433f3be9 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/evkmimxrt1064_flexspi_nor_config.h +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/evkmimxrt1064_flexspi_nor_config.h @@ -210,35 +210,19 @@ typedef struct _FlexSPIConfig } flexspi_mem_config_t; /* */ -#define NOR_CMD_INDEX_READ CMD_INDEX_READ //!< 0 -#define NOR_CMD_INDEX_READSTATUS CMD_INDEX_READSTATUS //!< 1 -#define NOR_CMD_INDEX_WRITEENABLE CMD_INDEX_WRITEENABLE //!< 2 -#define NOR_CMD_INDEX_ERASESECTOR 3 //!< 3 -#define NOR_CMD_INDEX_PAGEPROGRAM CMD_INDEX_WRITE //!< 4 -#define NOR_CMD_INDEX_CHIPERASE 5 //!< 5 -#define NOR_CMD_INDEX_DUMMY 6 //!< 6 -#define NOR_CMD_INDEX_ERASEBLOCK 7 //!< 7 - -#define NOR_CMD_LUT_SEQ_IDX_READ CMD_LUT_SEQ_IDX_READ //!< 0 READ LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS \ - CMD_LUT_SEQ_IDX_READSTATUS //!< 1 Read Status LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI \ - 2 //!< 2 Read status DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE \ - CMD_LUT_SEQ_IDX_WRITEENABLE //!< 3 Write Enable sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE_XPI \ - 4 //!< 4 Write Enable DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 //!< 5 Erase Sector sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 //!< 8 Erase Block sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM \ - CMD_LUT_SEQ_IDX_WRITE //!< 9 Program sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 //!< 11 Chip Erase sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 //!< 13 Read SFDP sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_RESTORE_NOCMD \ - 14 //!< 14 Restore 0-4-4/0-8-8 mode sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_EXIT_NOCMD \ - 15 //!< 15 Exit 0-4-4/0-8-8 mode sequence id in lookupTable stored in config blobk - +#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 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_WRITEENABLE 3 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 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_PAGEPROGRAM 9 +#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10 +#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 +#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 12 /* * Serial NOR configuration block */ @@ -258,6 +242,9 @@ typedef struct _flexspi_nor_config uint32_t reserve2[11]; //!< Reserved for future use } flexspi_nor_config_t; +#define FLASH_BUSY_STATUS_POL 0 +#define FLASH_BUSY_STATUS_OFFSET 0 + #ifdef __cplusplus extern "C" { #endif diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/flash_config.c b/ports/mimxrt/boards/MIMXRT1064_EVK/flash_config.c index bfb1c2d59a..9338c6948a 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/flash_config.c +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/flash_config.c @@ -36,9 +36,83 @@ const flexspi_nor_config_t qspiflash_config = { .sflashA1Size = 8u * 1024u * 1024u, .lookupTable = { - // Read LUTs + // 0 Read LUTs 0 -> 0 FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18), 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 + 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), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 3 Write Enable -> 3 + 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), + 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 + 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 + 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), + 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), + 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 + 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 + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 11 Erase Chip + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, 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 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 }, }, .pageSize = 256u, diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h index 3eddb41021..01e2e10bb5 100644 --- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h +++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h @@ -6,3 +6,4 @@ #define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_09) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) +#define BOARD_FLASH_CONFIG_HEADER_H "evkmimxrt1064_flexspi_nor_config.h" diff --git a/ports/mimxrt/boards/TEENSY40/TEENSY40.ld b/ports/mimxrt/boards/TEENSY40/TEENSY40.ld new file mode 100644 index 0000000000..a3b696db66 --- /dev/null +++ b/ports/mimxrt/boards/TEENSY40/TEENSY40.ld @@ -0,0 +1,2 @@ +flash_size = 2M; +reserved_size = 4K; \ No newline at end of file diff --git a/ports/mimxrt/boards/TEENSY40/flash_config.c b/ports/mimxrt/boards/TEENSY40/flash_config.c index 39a6b91088..7a63cf825d 100644 --- a/ports/mimxrt/boards/TEENSY40/flash_config.c +++ b/ports/mimxrt/boards/TEENSY40/flash_config.c @@ -32,20 +32,113 @@ const flexspi_nor_config_t qspiflash_config = { .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad, .csHoldTime = 3u, .csSetupTime = 3u, + + .busyOffset = FLASH_BUSY_STATUS_OFFSET, // Status bit 0 indicates busy. + .busyBitPolarity = FLASH_BUSY_STATUS_POL, // Busy when the bit is 1. + + .deviceModeCfgEnable = 1u, + .deviceModeType = kDeviceConfigCmdType_QuadEnable, + .deviceModeSeq = { + .seqId = 4u, + .seqNum = 1u, + }, + .deviceModeArg = 0x0200, + .configCmdEnable = 1u, + .configModeType[0] = kDeviceConfigCmdType_Generic, + .configCmdSeqs[0] = { + .seqId = 2u, + .seqNum = 1u, + }, + .deviceType = kFlexSpiDeviceType_SerialNOR, // Enable DDR mode, Wordaddassable, Safe configuration, Differential clock .sflashPadType = kSerialFlash_4Pads, - .serialClkFreq = kFlexSpiSerialClk_100MHz, + .serialClkFreq = kFlexSpiSerialClk_60MHz, .sflashA1Size = 2u * 1024u * 1024u, .lookupTable = { - // Read LUTs + // 0 Read LUTs 0 -> 0 FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18), 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 + 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), + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 3 Write Enable -> 3 + 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), + 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 + 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 + 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), + 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), + 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 + 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 + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler + + // 11 Erase Chip + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, 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 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 }, }, .pageSize = 256u, .sectorSize = 4u * 1024u, - .blockSize = 256u * 1024u, + .ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz, + .blockSize = 0x00010000, .isUniformBlockSize = false, }; #endif /* XIP_BOOT_HEADER_ENABLE */ diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.h b/ports/mimxrt/boards/TEENSY40/mpconfigboard.h index e3d7c6a129..c6f11b51d1 100644 --- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.h +++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.h @@ -7,3 +7,4 @@ #define MICROPY_HW_LED1_PIN (pin_GPIO_B0_03) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) +#define BOARD_FLASH_CONFIG_HEADER_H "teensy40_flexspi_nor_config.h" diff --git a/ports/mimxrt/boards/TEENSY40/teensy40_flexspi_nor_config.h b/ports/mimxrt/boards/TEENSY40/teensy40_flexspi_nor_config.h index 2c7bf48b62..445a0baccc 100644 --- a/ports/mimxrt/boards/TEENSY40/teensy40_flexspi_nor_config.h +++ b/ports/mimxrt/boards/TEENSY40/teensy40_flexspi_nor_config.h @@ -28,7 +28,7 @@ /* FLEXSPI Feature related definitions */ #define FLEXSPI_FEATURE_HAS_PARALLEL_MODE 1 -/* Lookup table related defintions */ +/* Lookup table related definitions */ #define CMD_INDEX_READ 0 #define CMD_INDEX_READSTATUS 1 #define CMD_INDEX_WRITEENABLE 2 @@ -37,6 +37,7 @@ #define CMD_LUT_SEQ_IDX_READ 0 #define CMD_LUT_SEQ_IDX_READSTATUS 1 #define CMD_LUT_SEQ_IDX_WRITEENABLE 3 +#define CMD_LUT_SEQ_IDX_ERASE 5 #define CMD_LUT_SEQ_IDX_WRITE 9 #define CMD_SDR 0x01 @@ -212,34 +213,19 @@ typedef struct _FlexSPIConfig } flexspi_mem_config_t; /* */ -#define NOR_CMD_INDEX_READ CMD_INDEX_READ //!< 0 -#define NOR_CMD_INDEX_READSTATUS CMD_INDEX_READSTATUS //!< 1 -#define NOR_CMD_INDEX_WRITEENABLE CMD_INDEX_WRITEENABLE //!< 2 -#define NOR_CMD_INDEX_ERASESECTOR 3 //!< 3 -#define NOR_CMD_INDEX_PAGEPROGRAM CMD_INDEX_WRITE //!< 4 -#define NOR_CMD_INDEX_CHIPERASE 5 //!< 5 -#define NOR_CMD_INDEX_DUMMY 6 //!< 6 -#define NOR_CMD_INDEX_ERASEBLOCK 7 //!< 7 - -#define NOR_CMD_LUT_SEQ_IDX_READ CMD_LUT_SEQ_IDX_READ //!< 0 READ LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS \ - CMD_LUT_SEQ_IDX_READSTATUS //!< 1 Read Status LUT sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI \ - 2 //!< 2 Read status DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE \ - CMD_LUT_SEQ_IDX_WRITEENABLE //!< 3 Write Enable sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE_XPI \ - 4 //!< 4 Write Enable DPI/QPI/OPI sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 //!< 5 Erase Sector sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 //!< 8 Erase Block sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM \ - CMD_LUT_SEQ_IDX_WRITE //!< 9 Program sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 //!< 11 Chip Erase sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 //!< 13 Read SFDP sequence in lookupTable id stored in config block -#define NOR_CMD_LUT_SEQ_IDX_RESTORE_NOCMD \ - 14 //!< 14 Restore 0-4-4/0-8-8 mode sequence id in lookupTable stored in config block -#define NOR_CMD_LUT_SEQ_IDX_EXIT_NOCMD \ - 15 //!< 15 Exit 0-4-4/0-8-8 mode sequence id in lookupTable stored in config blobk +#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 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_WRITEENABLE 3 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 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_PAGEPROGRAM 9 +#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10 +#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 +#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 12 /* * Serial NOR configuration block @@ -260,6 +246,9 @@ typedef struct _flexspi_nor_config uint32_t reserve2[11]; //!< Reserved for future use } flexspi_nor_config_t; +#define FLASH_BUSY_STATUS_POL 0 +#define FLASH_BUSY_STATUS_OFFSET 0 + #ifdef __cplusplus extern "C" { #endif diff --git a/ports/mimxrt/boards/common.ld b/ports/mimxrt/boards/common.ld new file mode 100644 index 0000000000..e5d91f1191 --- /dev/null +++ b/ports/mimxrt/boards/common.ld @@ -0,0 +1,262 @@ +/* +** ################################################################### +** Linker script inspired by NXP linker script for MIMXRT10xx +** +** Copyright for original linker script: +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2018 NXP +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** Integrated ideas from CircuitPython: +** SPDX-License-Identifier: The MIT License (MIT) +** SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft (tannewt) +** +** Copyright (c) 2021 Philipp Ebensberger +** +** ################################################################### +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400; +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400; + +/* Reserved Area + * Users can create a reserved area at the end of the flash memory via + * 'reserved_size' variable. The size of the reserved area should be a multiple + * of the sector size of the flash memory! + */ +reserved_size = DEFINED(reserved_size) ? reserved_size : 0k; + +/* Specify the memory areas */ +MEMORY +{ + m_flash_config (RX) : ORIGIN = flash_config_start, LENGTH = flash_config_size + m_ivt (RX) : ORIGIN = ivt_start, LENGTH = ivt_size + m_interrupts (RX) : ORIGIN = interrupts_start, LENGTH = interrupts_size + m_text (RX) : ORIGIN = text_start, LENGTH = text_size + 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_dtcm (RW) : ORIGIN = dtcm_start, LENGTH = dtcm_size + m_ocrm (RW) : ORIGIN = ocrm_start, LENGTH = ocrm_size +} + +/* Define output sections */ +SECTIONS +{ + __flash_start = flash_start; + __vfs_start = ORIGIN(m_vfs); + __vfs_end = __vfs_start + LENGTH(m_vfs); + + .flash_config : + { + . = ALIGN(4); + __FLASH_BASE = .; + KEEP(* (.boot_hdr.conf)) /* flash config section */ + . = ALIGN(4); + } > m_flash_config + + ivt_begin = ORIGIN(m_flash_config) + LENGTH(m_flash_config); + + .ivt : AT(ivt_begin) + { + . = ALIGN(4); + KEEP(* (.boot_hdr.ivt)) /* ivt section */ + KEEP(* (.boot_hdr.boot_data)) /* boot section */ + KEEP(* (.boot_hdr.dcd_data)) /* dcd section */ + . = ALIGN(4); + } > m_ivt + + /* The startup code goes first into internal RAM */ + .interrupts : + { + __VECTOR_TABLE = .; + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } > m_interrupts + + __VECTOR_RAM = __VECTOR_TABLE; + __RAM_VECTOR_TABLE_SIZE_BYTES = 0x0; + + /* The program code and other data goes into internal RAM */ + .text : + { + . = ALIGN(4); + *(EXCLUDE_FILE(*fsl_flexspi.o) .text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + } > m_text + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > m_text + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > m_text + + .ctors : + { + __CTOR_LIST__ = .; + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + } > m_text + + .dtors : + { + __DTOR_LIST__ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + } > m_text + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > m_text + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } > m_text + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > m_text + + __etext = .; /* define a global symbol at end of code */ + __DATA_ROM = .; /* Symbol is used by startup for data initialization */ + + .data : AT(__DATA_ROM) + { + . = ALIGN(4); + __DATA_RAM = .; + __data_start__ = .; /* create a global symbol at data start */ + *(m_usb_dma_init_data) + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + KEEP(*(.jcr*)) + . = ALIGN(4); + __data_end__ = .; /* define a global symbol at data end */ + } > m_dtcm + + __RAM_FUNCTIONS_ROM = __DATA_ROM + (__data_end__ - __data_start__); + .ram_functions : AT(__RAM_FUNCTIONS_ROM) + { + . = ALIGN(4); + __ram_function_start__ = .; + *fsl_flexspi.o(.text*) + *(.ram_functions*) + . = ALIGN(4); + __ram_function_end__ = .; + } > m_itcm + + __NDATA_ROM = __DATA_ROM + (__ram_function_end__ - __data_start__); + .ncache.init : AT(__NDATA_ROM) + { + __noncachedata_start__ = .; /* create a global symbol at ncache data start */ + *(NonCacheable.init) + . = ALIGN(4); + __noncachedata_init_end__ = .; /* create a global symbol at initialized ncache data end */ + } > m_dtcm + . = __noncachedata_init_end__; + .ncache : + { + *(NonCacheable) + . = ALIGN(4); + __noncachedata_end__ = .; /* define a global symbol at ncache data end */ + } > m_dtcm + + __DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__); + text_end = ORIGIN(m_text) + LENGTH(m_text); + ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") + + /* Uninitialized data section */ + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + . = ALIGN(4); + __START_BSS = .; + __bss_start__ = .; + *(m_usb_dma_noninit_data) + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + __END_BSS = .; + } > m_dtcm + + .heap : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + __HeapBase = .; + . += HEAP_SIZE; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } > m_dtcm + + .stack : + { + . = ALIGN(8); + . += STACK_SIZE; + } > m_dtcm + + /* Initializes stack on the end of block */ + __StackTop = ORIGIN(m_dtcm) + LENGTH(m_dtcm); + __StackLimit = __StackTop - STACK_SIZE; + PROVIDE(__stack = __StackTop); + + .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT(__StackLimit >= __HeapLimit, "region m_dtcm overflowed with stack and heap") +} + diff --git a/ports/mimxrt/hal/flexspi_nor_flash.c b/ports/mimxrt/hal/flexspi_nor_flash.c new file mode 100644 index 0000000000..a70d234d6e --- /dev/null +++ b/ports/mimxrt/hal/flexspi_nor_flash.c @@ -0,0 +1,219 @@ +/* + * Based largely on examples provided by NXP: + * + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Port-specific extensions and adaptions: + * + * The MIT License (MIT) + * This file is part of the MicroPython project, http://micropython.org/ + * + * Copyright (c) 2021 Damien P. George + * Copyright (c) 2021 Philipp Ebensberger + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include "fsl_common.h" +#include "flexspi_nor_flash.h" + +void flexspi_nor_reset(FLEXSPI_Type *base) __attribute__((section(".ram_functions"))); +void flexspi_nor_reset(FLEXSPI_Type *base) { + // Using content of FLEXSPI_SoftwareReset directly to prevent issues when compiler does not inline function + base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK; + while (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) + { + } +} + +status_t flexspi_nor_write_enable(FLEXSPI_Type *base, uint32_t baseAddr) __attribute__((section(".ram_functions"))); +status_t flexspi_nor_write_enable(FLEXSPI_Type *base, uint32_t baseAddr) { + flexspi_transfer_t flashXfer; + status_t status; + + /* Write neable */ + flashXfer.deviceAddress = baseAddr; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Command; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + return status; +} + +status_t flexspi_nor_wait_bus_busy(FLEXSPI_Type *base) __attribute__((section(".ram_functions"))) ; +status_t flexspi_nor_wait_bus_busy(FLEXSPI_Type *base) { + /* Wait status ready. */ + bool isBusy; + uint32_t readValue; + status_t status; + 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_READSTATUSREG; + flashXfer.data = &readValue; + flashXfer.dataSize = 1; + + do { + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + if (status != kStatus_Success) { + return status; + } + if (FLASH_BUSY_STATUS_POL) { + if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET)) { + isBusy = false; + } else { + isBusy = true; + } + } else { + if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET)) { + isBusy = true; + } else { + isBusy = false; + } + } + } while (isBusy); + + return status; +} + +status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base) __attribute__((section(".ram_functions"))) ; +status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base) { + flexspi_transfer_t flashXfer; + status_t status; + uint32_t writeValue = 0x40; + + /* Write neable */ + status = flexspi_nor_write_enable(base, 0); + + if (status != kStatus_Success) { + return status; + } + + /* Enable quad mode. */ + flashXfer.deviceAddress = 0; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Write; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG; + flashXfer.data = &writeValue; + flashXfer.dataSize = 1; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + if (status != kStatus_Success) { + return status; + } + + status = flexspi_nor_wait_bus_busy(base); + + return status; +} + +status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address) __attribute__((section(".ram_functions"))) ; +status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address) { + status_t status; + flexspi_transfer_t flashXfer; + + /* Write enable */ + status = flexspi_nor_write_enable(base, address); + + if (status != kStatus_Success) { + return status; + } + + /* Erase sector */ + flashXfer.deviceAddress = address; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Command; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASESECTOR; + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + if (status != kStatus_Success) { + return status; + } + + status = flexspi_nor_wait_bus_busy(base); + + flexspi_nor_reset(base); + + return status; +} + +status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t size) __attribute__((section(".ram_functions"))) ; +status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t size) { + status_t status; + flexspi_transfer_t flashXfer; + + /* Write enable */ + status = flexspi_nor_write_enable(base, dstAddr); + + if (status != kStatus_Success) { + return status; + } + + /* Prepare page program command */ + flashXfer.deviceAddress = dstAddr; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Write; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD; + flashXfer.data = (uint32_t *) src; + flashXfer.dataSize = size; + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + if (status != kStatus_Success) { + return status; + } + + status = flexspi_nor_wait_bus_busy(base); + + flexspi_nor_reset(FLEXSPI); + + 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/flexspi_nor_flash.h b/ports/mimxrt/hal/flexspi_nor_flash.h new file mode 100644 index 0000000000..43cd7efdc7 --- /dev/null +++ b/ports/mimxrt/hal/flexspi_nor_flash.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_MIMXRT_HAL_FLEXSPI_NOR_FLASH_H +#define MICROPY_INCLUDED_MIMXRT_HAL_FLEXSPI_NOR_FLASH_H + +#include "fsl_flexspi.h" +#include "mpconfigport.h" +#include BOARD_FLASH_CONFIG_HEADER_H + +// Defined in boards flash_config.c +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_flash_erase_sector(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); + +#endif // MICROPY_INCLUDED_MIMXRT_HAL_FLEXSPI_NOR_FLASH_H diff --git a/ports/mimxrt/main.c b/ports/mimxrt/main.c index 387c96ef33..76fd7ef76c 100644 --- a/ports/mimxrt/main.c +++ b/ports/mimxrt/main.c @@ -30,6 +30,7 @@ #include "py/gc.h" #include "py/mperrno.h" #include "py/stackctrl.h" +#include "lib/mp-readline/readline.h" #include "lib/utils/gchelper.h" #include "lib/utils/pyexec.h" #include "ticks.h" @@ -57,6 +58,24 @@ int main(void) { mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); + // Initialise sub-systems. + readline_init0(); + + // Execute _boot.py to set up the filesystem. + pyexec_frozen_module("_boot.py"); + + // Execute user scripts. + int ret = pyexec_file_if_exists("boot.py"); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { + ret = pyexec_file_if_exists("main.py"); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + } + for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { @@ -69,6 +88,7 @@ int main(void) { } } + soft_reset_exit: mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); gc_sweep_all(); mp_deinit(); @@ -83,19 +103,6 @@ void gc_collect(void) { gc_collect_end(); } -mp_lexer_t *mp_lexer_new_from_file(const char *filename) { - mp_raise_OSError(MP_ENOENT); -} - -mp_import_stat_t mp_import_stat(const char *path) { - return MP_IMPORT_STAT_NO_EXIST; -} - -mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); - void nlr_jump_fail(void *val) { for (;;) { } diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c new file mode 100644 index 0000000000..6b89bfa532 --- /dev/null +++ b/ports/mimxrt/mimxrt_flash.c @@ -0,0 +1,221 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * Copyright (c) 2021 Philipp Ebensberger + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/runtime.h" +#include "extmod/vfs.h" +#include "modmimxrt.h" +#include "hal/flexspi_nor_flash.h" + +// BOARD_FLASH_SIZE is defined in mpconfigport.h +#define SECTOR_SIZE_BYTES (qspiflash_config.sectorSize) +#define PAGE_SIZE_BYTES (qspiflash_config.pageSize) + +#ifndef MICROPY_HW_FLASH_STORAGE_BYTES +#define MICROPY_HW_FLASH_STORAGE_BYTES (((uint32_t)&__vfs_end) - ((uint32_t)&__vfs_start)) +#endif + +#ifndef MICROPY_HW_FLASH_STORAGE_BASE +#define MICROPY_HW_FLASH_STORAGE_BASE (((uint32_t)&__vfs_start) - ((uint32_t)&__flash_start)) +#endif + +// Linker symbols +extern uint8_t __vfs_start; +extern uint8_t __vfs_end; +extern uint8_t __flash_start; + +extern flexspi_nor_config_t qspiflash_config; + +typedef struct _mimxrt_flash_obj_t { + mp_obj_base_t base; + uint32_t flash_base; + uint32_t flash_size; +} mimxrt_flash_obj_t; + +STATIC mimxrt_flash_obj_t mimxrt_flash_obj = { + .base = { &mimxrt_flash_type } +}; + +// flash_erase_block(erase_addr_bytes) +// erases the 4k sector starting at adddr +status_t flash_erase_block(uint32_t erase_addr) __attribute__((section(".ram_functions"))); +status_t flash_erase_block(uint32_t erase_addr) { + status_t status; + SCB_CleanInvalidateDCache(); + SCB_DisableDCache(); + __disable_irq(); + status = flexspi_nor_flash_erase_sector(FLEXSPI, erase_addr); + __enable_irq(); + SCB_EnableDCache(); + return status; +} + +// flash_write_block(flash_dest_addr_bytes, data_source, length_bytes) +// writes length_byte data to the destination address +// length is a multiple of the page size = 256 +// the vfs driver takes care for erasing the sector if required +status_t flash_write_block(uint32_t dest_addr, const uint8_t *src, uint32_t length) __attribute__((section(".ram_functions"))); +status_t flash_write_block(uint32_t dest_addr, const uint8_t *src, uint32_t length) { + status_t status; + SCB_CleanInvalidateDCache(); + SCB_DisableDCache(); + // write sector in page size chunks + for (int i = 0; i < length; i += PAGE_SIZE_BYTES) { + __disable_irq(); + status = flexspi_nor_flash_page_program(FLEXSPI, dest_addr + i, (uint32_t *)(src + i), PAGE_SIZE_BYTES); + __enable_irq(); + if (status != kStatus_Success) { + break; + } + } + SCB_EnableDCache(); + return status; +} + +STATIC mp_obj_t mimxrt_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // Check args. + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // Upload the custom flash configuration + // This should be performed by the boot ROM but for some reason it is not. + FLEXSPI_UpdateLUT(FLEXSPI, 0, + qspiflash_config.memConfig.lookupTable, + sizeof(qspiflash_config.memConfig.lookupTable) / sizeof(qspiflash_config.memConfig.lookupTable[0])); + + // Configure FLEXSPI IP FIFO access. + FLEXSPI->MCR0 &= ~(FLEXSPI_MCR0_ARDFEN_MASK); + FLEXSPI->MCR0 &= ~(FLEXSPI_MCR0_ATDFEN_MASK); + FLEXSPI->MCR0 |= FLEXSPI_MCR0_ARDFEN(0); + FLEXSPI->MCR0 |= FLEXSPI_MCR0_ATDFEN(0); + + // Update information based on linker symbols. + mimxrt_flash_obj.flash_base = MICROPY_HW_FLASH_STORAGE_BASE; + mimxrt_flash_obj.flash_size = MICROPY_HW_FLASH_STORAGE_BYTES; + + // Return singleton object. + return MP_OBJ_FROM_PTR(&mimxrt_flash_obj); +} + +// readblocks(block_num, buf, [offset]) +// read size of buffer number of bytes from block (with offset) into buffer +STATIC mp_obj_t mimxrt_flash_readblocks(size_t n_args, const mp_obj_t *args) { + mimxrt_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); + // if (n_args == 4) { + // mp_printf(MP_PYTHON_PRINTER, "readblocks: nargs = %d, block = %d, offset = %d, len = %d\n", + // n_args, mp_obj_get_int(args[1]), mp_obj_get_int(args[3]), bufinfo.len); + // } else { + // mp_printf(MP_PYTHON_PRINTER, "readblocks: nargs = %d, block = %d, len = %d\n", + // n_args, mp_obj_get_int(args[1]), bufinfo.len); + // } + // Calculate read offset from block number. + uint32_t offset = mp_obj_get_int(args[1]) * SECTOR_SIZE_BYTES; + // Add optional offset + if (n_args == 4) { + offset += mp_obj_get_int(args[3]); + } + memcpy(bufinfo.buf, (uint8_t *)(FlexSPI_AMBA_BASE + self->flash_base + offset), bufinfo.len); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mimxrt_flash_readblocks_obj, 3, 4, mimxrt_flash_readblocks); + +// writeblocks(block_num, buf, [offset]) +// Erase block based on block_num and write buffer size number of bytes from buffer into block. If additional offset +// parameter is provided only write operation at block start + offset will be performed. +// This requires a prior erase operation of the block! +STATIC mp_obj_t mimxrt_flash_writeblocks(size_t n_args, const mp_obj_t *args) { + status_t status; + mimxrt_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + + // Calculate read offset from block number. + uint32_t offset = mp_obj_get_int(args[1]) * SECTOR_SIZE_BYTES; + + if (n_args == 3) { + status = flash_erase_block(self->flash_base + offset); + + if (status != kStatus_Success) { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("flash erase command failed with %d"), status); + } + } else { + // Add optional offset + offset += mp_obj_get_int(args[3]); + } + + status = flash_write_block(self->flash_base + offset, bufinfo.buf, bufinfo.len); + + if (status != kStatus_Success) { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("flash block write command failed with %d"), status); + } + + return MP_OBJ_NEW_SMALL_INT(status != kStatus_Success); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mimxrt_flash_writeblocks_obj, 3, 4, mimxrt_flash_writeblocks); + +// ioctl(op, arg) +STATIC mp_obj_t mimxrt_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { + mimxrt_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t cmd = mp_obj_get_int(cmd_in); + status_t status; + switch (cmd) { + case MP_BLOCKDEV_IOCTL_INIT: + return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_DEINIT: + return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_SYNC: + return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + return MP_OBJ_NEW_SMALL_INT(self->flash_size / SECTOR_SIZE_BYTES); + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + return MP_OBJ_NEW_SMALL_INT(SECTOR_SIZE_BYTES); + case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: { + uint32_t offset = mp_obj_get_int(arg_in) * SECTOR_SIZE_BYTES; + status = flash_erase_block(self->flash_base + offset); + return MP_OBJ_NEW_SMALL_INT(status != kStatus_Success); + } + default: + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mimxrt_flash_ioctl_obj, mimxrt_flash_ioctl); + +STATIC const mp_rom_map_elem_t mimxrt_flash_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&mimxrt_flash_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&mimxrt_flash_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mimxrt_flash_ioctl_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mimxrt_flash_locals_dict, mimxrt_flash_locals_dict_table); + +const mp_obj_type_t mimxrt_flash_type = { + { &mp_type_type }, + .name = MP_QSTR_Flash, + .make_new = mimxrt_flash_make_new, + .locals_dict = (mp_obj_dict_t *)&mimxrt_flash_locals_dict, +}; diff --git a/ports/mimxrt/modmimxrt.c b/ports/mimxrt/modmimxrt.c new file mode 100644 index 0000000000..addd4ba4d2 --- /dev/null +++ b/ports/mimxrt/modmimxrt.c @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "modmimxrt.h" + +STATIC const mp_rom_map_elem_t mimxrt_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mimxrt) }, + { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&mimxrt_flash_type) }, +}; +STATIC MP_DEFINE_CONST_DICT(mimxrt_module_globals, mimxrt_module_globals_table); + +const mp_obj_module_t mp_module_mimxrt = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mimxrt_module_globals, +}; diff --git a/ports/mimxrt/modmimxrt.h b/ports/mimxrt/modmimxrt.h new file mode 100644 index 0000000000..e047716691 --- /dev/null +++ b/ports/mimxrt/modmimxrt.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_MIMXRT_MODMIMXRT_H +#define MICROPY_INCLUDED_MIMXRT_MODMIMXRT_H + +#include "py/obj.h" + +extern const mp_obj_type_t mimxrt_flash_type; +extern const mp_obj_module_t mp_module_mimxrt; + +#endif // MICROPY_INCLUDED_MIMXRT_MODMIMXRT_H diff --git a/ports/mimxrt/modules/_boot.py b/ports/mimxrt/modules/_boot.py new file mode 100644 index 0000000000..892d004735 --- /dev/null +++ b/ports/mimxrt/modules/_boot.py @@ -0,0 +1,15 @@ +# _boot.py +# Try to mount the filesystem, and format the flash if it doesn't exist. +# Note: the flash requires the programming size to be aligned to 256 bytes. + +import os +import mimxrt + +bdev = mimxrt.Flash() + +try: + vfs = os.VfsLfs2(bdev, progsize=256) +except: + os.VfsLfs2.mkfs(bdev, progsize=256) + vfs = os.VfsLfs2(bdev, progsize=256) +os.mount(vfs, "/") diff --git a/ports/mimxrt/moduos.c b/ports/mimxrt/moduos.c new file mode 100644 index 0000000000..fe914ce610 --- /dev/null +++ b/ports/mimxrt/moduos.c @@ -0,0 +1,129 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * use of the TRNG by + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2019 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/objstr.h" +#include "py/runtime.h" +#include "extmod/vfs.h" +#include "extmod/vfs_lfs.h" +#include "genhdr/mpversion.h" +#include "fsl_trng.h" + +STATIC const qstr os_uname_info_fields[] = { + MP_QSTR_sysname, MP_QSTR_nodename, + MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine +}; +STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM); +STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM); +STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); +STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); +STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); + +STATIC MP_DEFINE_ATTRTUPLE( + os_uname_info_obj, + os_uname_info_fields, + 5, + (mp_obj_t)&os_uname_info_sysname_obj, + (mp_obj_t)&os_uname_info_nodename_obj, + (mp_obj_t)&os_uname_info_release_obj, + (mp_obj_t)&os_uname_info_version_obj, + (mp_obj_t)&os_uname_info_machine_obj + ); + +STATIC mp_obj_t os_uname(void) { + return (mp_obj_t)&os_uname_info_obj; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); + +STATIC mp_obj_t os_urandom(mp_obj_t num) { + mp_int_t n = mp_obj_get_int(num); + static bool initialized = false; + vstr_t vstr; + vstr_init_len(&vstr, n); + + if (!initialized) { + trng_config_t trngConfig; + + TRNG_GetDefaultConfig(&trngConfig); + trngConfig.sampleMode = kTRNG_SampleModeVonNeumann; + + TRNG_Init(TRNG, &trngConfig); + initialized = true; + } + TRNG_GetRandomData(TRNG, vstr.buf, n); + + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); + +STATIC const mp_rom_map_elem_t os_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, + + { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, + { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, + + #if MICROPY_VFS + { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, + { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, + { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, + #endif + + // The following are MicroPython extensions. + + #if MICROPY_PY_OS_DUPTERM + { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, + #endif + + #if MICROPY_VFS + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, + { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, + #if MICROPY_VFS_FAT + { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, + #endif + #if MICROPY_VFS_LFS1 + { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, + #endif + #if MICROPY_VFS_LFS2 + { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, + #endif + #endif +}; +STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); + +const mp_obj_module_t mp_module_uos = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&os_module_globals, +}; diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 63ee5ea5cc..db1944a9b8 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -34,20 +34,26 @@ #define MICROPY_GC_ALLOC_THRESHOLD (0) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (32) #define MICROPY_ALLOC_PATH_MAX (256) -#define MICROPY_QSTR_BYTES_IN_HASH (1) // Compiler configuration #define MICROPY_COMP_CONST (0) // Python internal features +#define MICROPY_READER_VFS (1) #define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_STACK_CHECK (1) +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_ENABLE_SOURCE_LINE (1) -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) +#define MICROPY_STREAMS_NON_BLOCK (1) +#define MICROPY_MODULE_BUILTIN_INIT (1) +#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) +#define MICROPY_VFS (1) #define MICROPY_MODULE_FROZEN_MPY (1) #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool @@ -68,22 +74,39 @@ #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_COLLECTIONS (0) +#define MICROPY_PY_IO_IOBASE (1) +#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_SYS_MAXSIZE (1) +#define MICROPY_PY_SYS_PLATFORM "mimxrt" +#define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_SYS_STDIO_BUFFER (1) // Extended modules #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_MACHINE (1) +// Use VfsLfs2's types for fileio/textio +#define mp_type_fileio mp_type_vfs_lfs2_fileio +#define mp_type_textio mp_type_vfs_lfs2_textio + +// Use VFS's functions for import stat and builtin open +#define mp_import_stat mp_vfs_import_stat +#define mp_builtin_open_obj mp_vfs_open_obj + // Hooks to add builtins #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, extern const struct _mp_obj_module_t mp_module_machine; +extern const struct _mp_obj_module_t mp_module_mimxrt; +extern const struct _mp_obj_module_t mp_module_uos; extern const struct _mp_obj_module_t mp_module_utime; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \ + { MP_ROM_QSTR(MP_QSTR_mimxrt), (mp_obj_t)&mp_module_mimxrt }, \ + { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ #define MICROPY_PORT_ROOT_POINTERS \ diff --git a/ports/mimxrt/mphalport.c b/ports/mimxrt/mphalport.c index 02a61a4f2a..faecafbbcd 100644 --- a/ports/mimxrt/mphalport.c +++ b/ports/mimxrt/mphalport.c @@ -26,6 +26,7 @@ */ #include "py/runtime.h" +#include "py/stream.h" #include "py/mphal.h" #include "ticks.h" #include "tusb.h" @@ -47,6 +48,14 @@ void mp_hal_set_interrupt_char(int c) { #endif +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + if (tud_cdc_connected() && tud_cdc_available()) { + ret |= MP_STREAM_POLL_RD; + } + return ret; +} + int mp_hal_stdin_rx_chr(void) { for (;;) { // TODO diff --git a/ports/mimxrt/mphalport.h b/ports/mimxrt/mphalport.h index 78b390b4eb..fd664346dd 100644 --- a/ports/mimxrt/mphalport.h +++ b/ports/mimxrt/mphalport.h @@ -73,4 +73,9 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { return 0; } +static inline uint64_t mp_hal_time_ns(void) { + // TODO: Implement this function. + return 0UL; +} + #endif // MICROPY_INCLUDED_MIMXRT_MPHALPORT_H