summaryrefslogtreecommitdiff
path: root/bsp
diff options
context:
space:
mode:
Diffstat (limited to 'bsp')
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/README_zh.md2
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/.ci/attachconfig/ci.attachconfig.yml11
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/applications/mnt.c100
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/Kconfig10
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/SConscript3
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/linker_scripts/link.scf1
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/drv_flexspi_nor_flash.c521
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/drv_flexspi_nor_flash.h59
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/fal_cfg.h37
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/fal_flash_port.c57
-rw-r--r--bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/flexspi_port.h62
-rw-r--r--bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.c132
-rw-r--r--bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.h46
13 files changed, 1036 insertions, 5 deletions
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/README_zh.md b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/README_zh.md
index f010af0ef6..f0e0365b28 100644
--- a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/README_zh.md
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/README_zh.md
@@ -27,7 +27,7 @@ CM33对CM7的kick off将在后续版本中支持。
| **板载外设** | **支持情况** | **备注** |
| :----------------- | :----------: | :------------------------------------|
| USB 转串口 | 暂不支持 | |
-| SPI Flash | 暂不支持 | |
+| SPI Flash | 支持 | |
| 以太网 | 暂不支持 | |
| **片上外设** | **支持情况** | **备注** |
| GPIO | 暂不支持 | |
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/.ci/attachconfig/ci.attachconfig.yml b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/.ci/attachconfig/ci.attachconfig.yml
new file mode 100644
index 0000000000..8648a70a2c
--- /dev/null
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/.ci/attachconfig/ci.attachconfig.yml
@@ -0,0 +1,11 @@
+scons.args: &scons
+ scons_arg:
+ - '--strict'
+
+# ------ component CI ------
+
+# ------ Peripheral CI ------
+Peripheral.flash_fs:
+ <<: *scons
+ kconfig:
+ - CONFIG_BSP_USING_QSPI_FLASH_FS=y \ No newline at end of file
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/applications/mnt.c b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/applications/mnt.c
new file mode 100644
index 0000000000..854f9aa21f
--- /dev/null
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/applications/mnt.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2019-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-02 CoreBoxer add LittleFS on QSPI NOR Flash (IMXRT1180-EVK)
+ */
+
+#include <rtthread.h>
+
+/* ====================================================================
+ * QSPI NOR Flash LittleFS (controlled by BSP_USING_QSPI_FLASH_FS)
+ *
+ * Dependencies:
+ * - drv_flash.c (Flash read/write/erase driver via ROM API)
+ * - FAL framework (partition management)
+ * - LittleFS component (RT-Thread package)
+ *
+ * FAL partition configuration (fal_cfg.h):
+ * "filesystem" partition → filesystem area of norflash0
+ *
+ * Mount procedure:
+ * 1. Find FAL partition to confirm correct configuration
+ * 2. Create MTD NOR block device
+ * 3. Try direct mount (for already formatted filesystem)
+ * 4. If failed, perform mkfs then remount (first use or format scenario)
+ * ==================================================================== */
+#ifdef BSP_USING_QSPI_FLASH_FS
+#include <dfs_fs.h>
+#include <fal.h>
+
+#define FS_PARTITION_NAME "filesystem"
+#define FS_TYPE_NAME "lfs"
+#define FS_MOUNT_POINT "/"
+
+static int _qspi_flash_fs_mount(void)
+{
+ struct fal_mtd_nor_device *mtd_dev;
+ int ret;
+
+ /* Find FAL partition to confirm configuration is correct */
+ if (fal_partition_find(FS_PARTITION_NAME) == RT_NULL)
+ {
+ rt_kprintf("[qspi_fs] partition '%s' not found, check fal_cfg.h\n",
+ FS_PARTITION_NAME);
+ return -RT_ERROR;
+ }
+
+ /* Create MTD NOR block device for filesystem partition */
+ mtd_dev = (struct fal_mtd_nor_device *)fal_mtd_nor_device_create(FS_PARTITION_NAME);
+ if (mtd_dev == RT_NULL)
+ {
+ rt_kprintf("[qspi_fs] failed to create MTD NOR device for '%s'\n",
+ FS_PARTITION_NAME);
+ return -RT_ERROR;
+ }
+
+ /* Try direct mount (for already formatted flash) */
+ ret = dfs_mount(FS_PARTITION_NAME, FS_MOUNT_POINT, FS_TYPE_NAME, 0, 0);
+ if (ret == 0)
+ {
+ rt_kprintf("[qspi_fs] '%s' mounted at '%s'\n",
+ FS_PARTITION_NAME, FS_MOUNT_POINT);
+ return RT_EOK;
+ }
+
+ /* Mount failed, indicating flash is not formatted (first use scenario), perform mkfs */
+ rt_kprintf("[qspi_fs] mount failed (ret=%d), formatting '%s'...\n",
+ ret, FS_PARTITION_NAME);
+
+ ret = dfs_mkfs(FS_TYPE_NAME, FS_PARTITION_NAME);
+ if (ret != 0)
+ {
+ rt_kprintf("[qspi_fs] mkfs failed (ret=%d)\n", ret);
+ return -RT_ERROR;
+ }
+
+ /* Remount after successful mkfs */
+ ret = dfs_mount(FS_PARTITION_NAME, FS_MOUNT_POINT, FS_TYPE_NAME, 0, 0);
+ if (ret != 0)
+ {
+ rt_kprintf("[qspi_fs] mount failed after mkfs (ret=%d)\n", ret);
+ return -RT_ERROR;
+ }
+
+ rt_kprintf("[qspi_fs] '%s' formatted and mounted at '%s'\n",
+ FS_PARTITION_NAME, FS_MOUNT_POINT);
+ return RT_EOK;
+}
+INIT_APP_EXPORT(_qspi_flash_fs_mount);
+/*
+ * FAL initialization registered as INIT_COMPONENT_EXPORT:
+ * after Flash driver (INIT_DEVICE_EXPORT)
+ * before filesystem mount (INIT_APP_EXPORT)
+ */
+INIT_COMPONENT_EXPORT(fal_init);
+
+#endif /* BSP_USING_QSPI_FLASH_FS */ \ No newline at end of file
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/Kconfig b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/Kconfig
index 12d8078d8c..699499cf04 100644
--- a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/Kconfig
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/Kconfig
@@ -229,6 +229,16 @@ menu "Onboard Peripheral Drivers"
select BSP_USING_SDIO
select RT_USING_DFS_ELMFAT
default n
+
+ config BSP_USING_QSPI_FLASH_FS
+ bool "Enable QSPI Flash (LittleFS)"
+ select BSP_USING_FLEXSPI
+ select BSP_USING_FLEXSPI1
+ select RT_USING_FAL
+ select FAL_PART_HAS_TABLE_CFG
+ select RT_USING_MTD_NOR
+ select PKG_USING_LITTLEFS
+ default n
endif
endmenu
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/SConscript b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/SConscript
index 0cfbe5a55b..ad731bbaf2 100644
--- a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/SConscript
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/SConscript
@@ -12,6 +12,9 @@ MCUX_Config/clock_config.c
MCUX_Config/pin_mux.c
""")
+if GetDepend(['BSP_USING_QSPI_FLASH_FS']):
+ src += ['ports/drv_flexspi_nor_flash.c', 'ports/fal_flash_port.c']
+
CPPPATH = [cwd,cwd + '/MCUX_Config',cwd + '/ports']
CPPDEFINES = ['CPU_MIMXRT1189CVM8C_cm33', 'MCUXPRESSO_SDK', 'MCUX_META_BUILD', 'MIMXRT1189_cm33_SERIES', 'XIP_BOOT_HEADER_ENABLE=1', 'XIP_BOOT_HEADER_DCD_ENABLE=1', 'XIP_EXTERNAL_FLASH=1', 'ARM_MATH_CM33']
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/linker_scripts/link.scf b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/linker_scripts/link.scf
index 9ee6de8571..08a0efca76 100644
--- a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/linker_scripts/link.scf
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/linker_scripts/link.scf
@@ -173,6 +173,7 @@ LR_m_text m_text_start m_text_size
ER_m_QuickAccessCode m_qacode_start m_qacode_size
{
+ fsl_flexspi.o (+RO-CODE)
.ANY (CodeQuickAccess)
}
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/drv_flexspi_nor_flash.c b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/drv_flexspi_nor_flash.c
new file mode 100644
index 0000000000..2132bd4d26
--- /dev/null
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/drv_flexspi_nor_flash.c
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-03 CoreBoxer support IMXRT1180-EVK
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+
+#include "drv_flexspi_nor_flash.h"
+#include "drv_flexspi.h"
+#include "flexspi_port.h"
+#include "fsl_flexspi.h"
+#include "fsl_cache.h"
+
+/*
+ * Logging configuration
+ */
+#define LOG_TAG "drv.flash"
+#define LOG_LVL LOG_LVL_INFO
+#include <rtdbg.h>
+
+/*
+ * FLASH_BUSY_STATUS_POL = 1 : SR[bit] = 1 means busy
+ * FLASH_BUSY_STATUS_OFFSET = 0 : WIP bit is SR[0]
+ * FLASH_QUAD_ENABLE = 0x40 : write to SR to enable Quad mode
+ */
+#define FLASH_QUAD_ENABLE_VAL 0x40U
+
+/* WIP polling upper limit to prevent infinite loop on Flash failure */
+#define WIP_TIMEOUT_COUNT 2000000UL
+
+/*
+ * Internal write buffer (must reside in SRAM)
+ *
+ * Reason: src data may come from const sections in XIP Flash.
+ * During FLEXSPI IP write commands, AHB access is suspended.
+ * If CPU tries to read src via AHB at that moment, bus hang or
+ * corrupted data may occur. Pre-copying to SRAM avoids this.
+ */
+static uint8_t SDK_ALIGN(s_write_buf[QSPI_PAGE_SIZE], 4);
+
+/* Internal state */
+static imxrt_flexspi_handle_t *s_handle = RT_NULL;
+static struct rt_mutex s_mutex;
+static int s_inited = 0;
+
+/*
+ * _range_valid - check whether [offset, offset+size) is within Flash
+ */
+rt_inline int _range_valid(rt_uint32_t offset, rt_size_t size)
+{
+ if (size == 0U)
+ {
+ return 1;
+ }
+ if ((offset + (rt_uint32_t)size) < offset)
+ {
+ return 0; /* overflow */
+ }
+ if ((offset + (rt_uint32_t)size) > QSPI_FLASH_SIZE)
+ {
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * _addr_safe - check whether [offset, offset+size) is within the FS partition
+ */
+rt_inline int _addr_safe(rt_uint32_t offset, rt_size_t size)
+{
+ if (size == 0U)
+ {
+ return 1;
+ }
+ if ((offset + (rt_uint32_t)size) < offset)
+ {
+ return 0;
+ }
+ if (offset < QSPI_FS_OFFSET)
+ {
+ return 0;
+ }
+ if ((offset + (rt_uint32_t)size) > (QSPI_FS_OFFSET + QSPI_FS_SIZE))
+ {
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Low-level NOR Flash operations (mapped from SDK flexspi_nor_flash_ops.c)
+ *
+ * All functions are marked QSPI_RAM_CODE (placed in ITCM) because they are
+ * called while a FLEXSPI IP command is in progress, during which AHB access
+ * is suspended and the CPU must fetch instructions from ITCM.
+ */
+
+/*
+ * _nor_write_enable - send WREN command (SDK: flexspi_nor_write_enable)
+ */
+QSPI_RAM_CODE static status_t _nor_write_enable(rt_uint32_t base_addr)
+{
+ flexspi_transfer_t xfer;
+
+ xfer.deviceAddress = base_addr;
+ xfer.port = FLASH_PORT;
+ xfer.cmdType = kFLEXSPI_Command;
+ xfer.SeqNumber = 1;
+ xfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE;
+
+ return FLEXSPI_TransferBlocking(s_handle->base, &xfer);
+}
+
+/*
+ * _nor_wait_busy - poll WIP bit until Flash is idle (SDK: flexspi_nor_wait_bus_busy)
+ *
+ * W25Q128JWSIQ SR1[0] = WIP (Write In Progress)
+ * FLASH_BUSY_STATUS_POL = 1: bit set means busy
+ */
+QSPI_RAM_CODE static status_t _nor_wait_busy(void)
+{
+ rt_uint32_t read_val = 0;
+ rt_uint32_t timeout = 0;
+ status_t status;
+ rt_bool_t is_busy;
+ flexspi_transfer_t xfer;
+
+ xfer.deviceAddress = 0;
+ xfer.port = FLASH_PORT;
+ xfer.cmdType = kFLEXSPI_Read;
+ xfer.SeqNumber = 1;
+ xfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READSTATUSREG;
+ xfer.data = &read_val;
+ xfer.dataSize = 1;
+
+ do
+ {
+ status = FLEXSPI_TransferBlocking(s_handle->base, &xfer);
+ if (status != kStatus_Success)
+ {
+ return status;
+ }
+
+ /* Busy detection logic identical to SDK example */
+ if (FLASH_BUSY_STATUS_POL)
+ {
+ is_busy = (read_val & (1U << FLASH_BUSY_STATUS_OFFSET)) != 0U;
+ }
+ else
+ {
+ is_busy = (read_val & (1U << FLASH_BUSY_STATUS_OFFSET)) == 0U;
+ }
+
+ if (++timeout > WIP_TIMEOUT_COUNT)
+ {
+ return kStatus_Timeout;
+ }
+ }
+ while (is_busy);
+
+ return kStatus_Success;
+}
+
+/*
+ * _nor_erase_sector - erase one 4KB sector (SDK: flexspi_nor_flash_erase_sector)
+ *
+ * @addr: Flash internal offset (not AHB address)
+ */
+QSPI_RAM_CODE static status_t _nor_erase_sector(rt_uint32_t addr)
+{
+ rt_base_t level;
+ status_t status;
+ flexspi_transfer_t xfer;
+
+ level = rt_hw_interrupt_disable();
+
+ xfer.deviceAddress = addr;
+ xfer.port = FLASH_PORT;
+ xfer.cmdType = kFLEXSPI_Command;
+ xfer.SeqNumber = 1;
+ xfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE;
+
+ status = FLEXSPI_TransferBlocking(s_handle->base, &xfer);
+ if (status != kStatus_Success)
+ {
+ rt_hw_interrupt_enable(level);
+ return status;
+ }
+
+ xfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASESECTOR;
+ status = FLEXSPI_TransferBlocking(s_handle->base, &xfer);
+ if (status != kStatus_Success)
+ {
+ rt_hw_interrupt_enable(level);
+ return status;
+ }
+
+ status = _nor_wait_busy();
+ if (status == kStatus_Success)
+ {
+ FLEXSPI_SoftwareReset(s_handle->base);
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ return status;
+}
+
+/*
+ * _nor_page_program - program one page (SDK: flexspi_nor_flash_page_program)
+ *
+ * Uses PAGEPROGRAM_QUAD (0x32, 1-1-4 mode) for faster write speed,
+ * consistent with the SDK example. src must be a 4-byte aligned SRAM buffer.
+ */
+QSPI_RAM_CODE static status_t _nor_page_program(rt_uint32_t addr, const rt_uint32_t *src)
+{
+ rt_base_t level;
+ status_t status;
+ flexspi_transfer_t xfer;
+
+ level = rt_hw_interrupt_disable();
+
+ status = _nor_wait_busy();
+ if (status != kStatus_Success)
+ {
+ rt_hw_interrupt_enable(level);
+ return status;
+ }
+
+ status = _nor_write_enable(addr);
+ if (status != kStatus_Success)
+ {
+ rt_hw_interrupt_enable(level);
+ return status;
+ }
+
+ xfer.deviceAddress = addr;
+ xfer.port = FLASH_PORT;
+ xfer.cmdType = kFLEXSPI_Write;
+ xfer.SeqNumber = 1;
+ xfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD;
+ xfer.data = (rt_uint32_t *)src;
+ xfer.dataSize = QSPI_PAGE_SIZE;
+
+ status = FLEXSPI_TransferBlocking(s_handle->base, &xfer);
+ if (status != kStatus_Success)
+ {
+ rt_hw_interrupt_enable(level);
+ return status;
+ }
+
+ status = _nor_wait_busy();
+ if (status == kStatus_Success)
+ {
+ FLEXSPI_SoftwareReset(s_handle->base);
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ return status;
+}
+
+/*
+ * rt_qspi_flash_init - initialize the QSPI NOR Flash driver
+ *
+ * Note: drv_flexspi.c has already performed the following via INIT_DEVICE_EXPORT:
+ * - flexspi_clock_init
+ * - FLEXSPI_Init
+ * - FLEXSPI_SetFlashConfig
+ * - FLEXSPI_UpdateLUT
+ * - FLEXSPI_SoftwareReset
+ * This function only acquires the handle and verifies Flash connectivity.
+ */
+int rt_qspi_flash_init(void)
+{
+ rt_uint8_t vendor_id = 0;
+ rt_uint32_t temp = 0;
+ status_t status;
+ flexspi_transfer_t xfer;
+
+ if (s_inited)
+ {
+ return RT_EOK;
+ }
+
+ /* Acquire the controller handle already initialized by drv_flexspi.c */
+ s_handle = imxrt_flexspi_get_handle();
+ if ((s_handle == RT_NULL) || (s_handle->base == RT_NULL))
+ {
+ LOG_E("FlexSPI handle not ready, check INIT order");
+ return -RT_ERROR;
+ }
+
+ /* Read Vendor ID to verify Flash connectivity (SDK: flexspi_nor_get_vendor_id) */
+ xfer.deviceAddress = 0;
+ xfer.port = FLASH_PORT;
+ xfer.cmdType = kFLEXSPI_Read;
+ xfer.SeqNumber = 1;
+ xfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READID;
+ xfer.data = &temp;
+ xfer.dataSize = 1;
+
+ status = FLEXSPI_TransferBlocking(s_handle->base, &xfer);
+ if (status != kStatus_Success)
+ {
+ LOG_E("read vendor ID failed, status=0x%X", (unsigned)status);
+ return -RT_ERROR;
+ }
+
+ vendor_id = (rt_uint8_t)(temp & 0xFFU);
+ if ((vendor_id == 0x00U) || (vendor_id == 0xFFU))
+ {
+ LOG_E("Flash not detected (vendor=0x%02X)", vendor_id);
+ return -RT_ERROR;
+ }
+
+ LOG_I("Vendor ID: 0x%02X", vendor_id);
+
+ /*
+ * W25Q128JWSIQ: QE bit is set by default from factory, no Quad Enable
+ * sequence is needed. For other Flash models, refer to SDK example
+ * flexspi_nor_enable_quad_mode() to add this step.
+ */
+
+ if (rt_mutex_init(&s_mutex, "flashmtx", RT_IPC_FLAG_PRIO) != RT_EOK)
+ {
+ LOG_E("mutex init failed");
+ return -RT_ERROR;
+ }
+
+ s_inited = 1;
+
+ LOG_I("init OK, base=0x%08X total=%uKB sector=%uB page=%uB",
+ (unsigned)QSPI_FLASH_BASE,
+ (unsigned)(QSPI_FLASH_SIZE / 1024U),
+ (unsigned)QSPI_SECTOR_SIZE,
+ (unsigned)QSPI_PAGE_SIZE);
+ LOG_I("fs partition: 0x%08X~0x%08X (%uKB)",
+ (unsigned)(QSPI_FLASH_BASE + QSPI_FS_OFFSET),
+ (unsigned)(QSPI_FLASH_BASE + QSPI_FS_OFFSET + QSPI_FS_SIZE - 1U),
+ (unsigned)(QSPI_FS_SIZE / 1024U));
+
+ return RT_EOK;
+}
+INIT_COMPONENT_EXPORT(rt_qspi_flash_init);
+
+/*
+ * rt_qspi_flash_read - read data via AHB direct memcpy (XIP mapping)
+ *
+ * Read operations do not interfere with FlexSPI IP commands, so this
+ * function does not need to be placed in ITCM.
+ */
+int rt_qspi_flash_read(rt_uint32_t offset, rt_uint8_t *buf, rt_size_t size)
+{
+ if (!s_inited)
+ {
+ return -RT_ERROR;
+ }
+ if (size == 0U)
+ {
+ return 0;
+ }
+ if (buf == RT_NULL)
+ {
+ return -RT_EINVAL;
+ }
+ if (!_range_valid(offset, size))
+ {
+ return -RT_EINVAL;
+ }
+
+ rt_memcpy(buf, (const void *)(QSPI_FLASH_BASE + offset), size);
+
+ return (int)size;
+}
+
+/*
+ * rt_qspi_flash_mmap - zero-copy read by returning AHB mapping pointer
+ */
+void *rt_qspi_flash_mmap(rt_uint32_t offset, rt_size_t size)
+{
+ if (!s_inited)
+ {
+ return RT_NULL;
+ }
+ if (!_range_valid(offset, size))
+ {
+ return RT_NULL;
+ }
+ return (void *)(QSPI_FLASH_BASE + offset);
+}
+
+/*
+ * rt_qspi_flash_write - write data to Flash (page-granular)
+ *
+ * This function is placed in ITCM (QSPI_RAM_CODE).
+ *
+ * Constraints (aligned with LittleFS prog_size = 256):
+ * - offset must be page-aligned (256B)
+ * - size must be a multiple of page size (256B)
+ *
+ * Data path: src -> s_write_buf (SRAM) -> Flash
+ */
+QSPI_RAM_CODE int rt_qspi_flash_write(rt_uint32_t offset, const rt_uint8_t *buf, rt_size_t size)
+{
+ rt_size_t written = 0;
+ status_t status;
+
+ if (!s_inited)
+ {
+ return -RT_ERROR;
+ }
+ if (size == 0U)
+ {
+ return 0;
+ }
+ if (buf == RT_NULL)
+ {
+ return -RT_EINVAL;
+ }
+ if (!_addr_safe(offset, size))
+ {
+ return -RT_EINVAL;
+ }
+ if ((offset % QSPI_PAGE_SIZE != 0U) || (size % QSPI_PAGE_SIZE != 0U))
+ {
+ return -RT_EINVAL;
+ }
+
+ rt_mutex_take(&s_mutex, RT_WAITING_FOREVER);
+
+ while (written < size)
+ {
+ /*
+ * Data must be relayed through an SRAM buffer.
+ * SDK example declares s_nor_program_buffer as SDK_ALIGN(static uint8_t, 4).
+ * s_write_buf is equivalently 4-byte aligned and resides in SRAM.
+ */
+ rt_memcpy(s_write_buf, buf + written, QSPI_PAGE_SIZE);
+
+ status = _nor_page_program(offset + written, (const rt_uint32_t *)s_write_buf);
+ if (status != kStatus_Success)
+ {
+ rt_mutex_release(&s_mutex);
+ return -RT_ERROR;
+ }
+
+ /*
+ * Cache maintenance (consistent with SDK DCACHE_InvalidateByRange):
+ * Invalidate the AHB-mapped cache region after write completes to
+ * ensure subsequent memcpy/mmap reads return newly written data.
+ */
+ DCACHE_InvalidateByRange(QSPI_FLASH_BASE + offset + written, QSPI_PAGE_SIZE);
+
+ written += QSPI_PAGE_SIZE;
+ }
+
+ rt_mutex_release(&s_mutex);
+ return (int)size;
+}
+
+/*
+ * rt_qspi_flash_erase - erase Flash sectors
+ *
+ * This function is placed in ITCM (QSPI_RAM_CODE).
+ *
+ * offset and size must be sector-aligned (4KB).
+ * Only the filesystem partition is allowed to be erased (_addr_safe guard).
+ */
+QSPI_RAM_CODE int rt_qspi_flash_erase(rt_uint32_t offset, rt_size_t size)
+{
+ rt_uint32_t addr;
+ rt_uint32_t addr_end;
+ status_t status;
+
+ if (!s_inited)
+ {
+ return -RT_ERROR;
+ }
+ if (size == 0U)
+ {
+ return 0;
+ }
+ if (!_addr_safe(offset, size))
+ {
+ return -RT_EINVAL;
+ }
+ if ((offset % QSPI_SECTOR_SIZE != 0U) || (size % QSPI_SECTOR_SIZE != 0U))
+ {
+ return -RT_EINVAL;
+ }
+
+ addr = offset;
+ addr_end = offset + (rt_uint32_t)size;
+
+ rt_mutex_take(&s_mutex, RT_WAITING_FOREVER);
+
+ while (addr < addr_end)
+ {
+ status = _nor_erase_sector(addr);
+ if (status != kStatus_Success)
+ {
+ rt_mutex_release(&s_mutex);
+ return -RT_ERROR;
+ }
+
+ /* Invalidate D-Cache for the erased AHB region */
+ DCACHE_InvalidateByRange(QSPI_FLASH_BASE + addr, QSPI_SECTOR_SIZE);
+
+ addr += QSPI_SECTOR_SIZE;
+ }
+
+ rt_mutex_release(&s_mutex);
+ return (int)size;
+}
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/drv_flexspi_nor_flash.h b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/drv_flexspi_nor_flash.h
new file mode 100644
index 0000000000..aceb7680a6
--- /dev/null
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/drv_flexspi_nor_flash.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2024-06-03 CoreBoxer support IMXRT1180-EVK
+ */
+
+#ifndef __DRV_FLEXSPI_NOR_FLASH_H__
+#define __DRV_FLEXSPI_NOR_FLASH_H__
+
+#include <rtthread.h>
+
+/* ============================================================
+ * Flash Physical Parameters
+ * Source: SDK example app.h
+ * FLASH_SIZE = 0x4000 (Unit: KB) = 16MB
+ * FlexSPI1_AMBA_BASE = 0x28000000
+ * ============================================================ */
+#define QSPI_FLASH_BASE FlexSPI1_AMBA_BASE /* 0x28000000 */
+#define QSPI_FLASH_SIZE (0x4000U * 1024U) /* 16MB (0x4000 KB) */
+#define QSPI_SECTOR_SIZE 0x00001000U /* 4KB */
+#define QSPI_PAGE_SIZE 256U /* 256B */
+
+/*
+ * Partition Plan (Total 16MB):
+ * 0x00000000 ~ 0x007FFFFF: Application Code Area (8MB, limited by Scatter)
+ * 0x00800000 ~ 0x00FFFFFF: File System Area (8MB, LittleFS)
+ */
+#define QSPI_FS_OFFSET 0x00800000U
+#define QSPI_FS_SIZE 0x00800000U
+
+/* ============================================================
+ * RAM Code Section Attributes
+ * Write/Erase functions placed in CodeQuickAccess (ITCM),
+ * CPU can safely fetch instructions during FlexSPI IP command execution.
+ * ============================================================ */
+#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
+ #define QSPI_RAM_CODE __attribute__((section("CodeQuickAccess"), noinline))
+#elif defined(__GNUC__)
+ #define QSPI_RAM_CODE __attribute__((section(".itcm.text"), noinline))
+#elif defined(__ICCARM__)
+ #define QSPI_RAM_CODE __ramfunc
+#else
+ #define QSPI_RAM_CODE
+#endif
+
+/* ============================================================
+ * External APIs
+ * ============================================================ */
+int rt_qspi_flash_init(void);
+int rt_qspi_flash_read(uint32_t offset, uint8_t *buf, size_t size);
+int rt_qspi_flash_write(uint32_t offset, const uint8_t *buf, size_t size);
+int rt_qspi_flash_erase(uint32_t offset, size_t size);
+void *rt_qspi_flash_mmap(uint32_t offset, size_t size);
+
+#endif /* __DRV_FLEXSPI_NOR_FLASH_H__ */ \ No newline at end of file
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/fal_cfg.h b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/fal_cfg.h
new file mode 100644
index 0000000000..7572542830
--- /dev/null
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/fal_cfg.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2024-01-01 RT-Thread first version
+ */
+
+#ifndef __FAL_CFG_H__
+#define __FAL_CFG_H__
+
+#include <rtthread.h>
+#include <board.h>
+
+extern const struct fal_flash_dev imxrt1180_nor_flash;
+
+/* flash device table */
+#define FAL_FLASH_DEV_TABLE \
+{ \
+ &imxrt1180_nor_flash, \
+}
+
+/* ====================== Partition Configuration ========================== */
+#ifdef FAL_PART_HAS_TABLE_CFG
+
+/* partition table */
+#define FAL_PART_TABLE \
+{ \
+ {FAL_PART_MAGIC_WROD, "app", "norflash0", 0, 8*1024*1024, 0}, \
+ {FAL_PART_MAGIC_WROD, "filesystem", "norflash0", 8*1024*1024, 8*1024*1024, 0}, \
+}
+
+#endif /* FAL_PART_HAS_TABLE_CFG */
+
+#endif /* __FAL_CFG_H__ */
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/fal_flash_port.c b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/fal_flash_port.c
new file mode 100644
index 0000000000..6e31c51c91
--- /dev/null
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/fal_flash_port.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-03 CoreBoxer support IMXRT1180-EVK
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <fal.h>
+
+#include "drv_flexspi_nor_flash.h"
+
+/*
+ * Logging configuration
+ */
+#define LOG_TAG "fal.flash"
+#define LOG_LVL LOG_LVL_INFO
+#include <rtdbg.h>
+
+/* FAL ops bridge */
+#ifdef RT_USING_FAL
+
+static int _fal_init(void)
+{
+ return rt_qspi_flash_init();
+}
+
+static int _fal_read(long offset, rt_uint8_t *buf, size_t size)
+{
+ return rt_qspi_flash_read((rt_uint32_t)offset, buf, size);
+}
+
+QSPI_RAM_CODE static int _fal_write(long offset, const rt_uint8_t *buf, size_t size)
+{
+ return rt_qspi_flash_write((rt_uint32_t)offset, buf, size);
+}
+
+QSPI_RAM_CODE static int _fal_erase(long offset, size_t size)
+{
+ return rt_qspi_flash_erase((rt_uint32_t)offset, size);
+}
+
+const struct fal_flash_dev imxrt1180_nor_flash =
+{
+ .name = "norflash0",
+ .addr = QSPI_FLASH_BASE,
+ .len = QSPI_FLASH_SIZE,
+ .blk_size = QSPI_SECTOR_SIZE,
+ .ops = { _fal_init, _fal_read, _fal_write, _fal_erase },
+ .write_gran = QSPI_PAGE_SIZE,
+};
+
+#endif /* RT_USING_FAL */
diff --git a/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/flexspi_port.h b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/flexspi_port.h
new file mode 100644
index 0000000000..dc7cb6c69e
--- /dev/null
+++ b/bsp/nxp/imx/imxrt/imxrt1180-nxp-evk/cm33/board/ports/flexspi_port.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-15 xjy198903 The first version for rt1170
+ * 2026-06-03 CoreBoxer support IMXRT1180-EVK
+ */
+
+#ifndef FLEXSPI_PORT_H__
+#define FLEXSPI_PORT_H__
+
+/* parameters for flexpsi peripheral */
+#define FLEXSPI1_CONTROL_BASE FLEXSPI1
+#define FLEXSPI2_CONTROL_BASE FLEXSPI2
+#define FLEXSPI_ROOT_CLK (12000000U) /* serial root clk: 12MHz*/
+#define FLASH_SIZE (16 * 1024) /* device size 16*1024(KB) = 16MB */
+#define ARD_SEQ_NUMBER 1 /* Sequence number for AHB read command */
+#define ARD_SEQ_INDEX 0 /* Sequence ID for AHB read command */
+#define AWR_SEQ_NUMBER 0 /* Sequence number for AHB write command */
+#define AWR_SEQ_INDEX 0 /* Sequence ID for AHB write command */
+#define ARD_SEQ_CMD 0xBB /* cmd for read */
+#define AWR_SEQ_CMD 0xAA /* cmd for write */
+#define FLEXSPI_RX_SAMPLE_CLOCK kFLEXSPI_ReadSampleClkLoopbackFromDqsPad
+#define FLASH_PORT kFLEXSPI_PortA1
+#define CLOCK_SRC kCLOCK_FLEXSPI1_ClockRoot_MuxOscRc24M
+#define CLOCK_DIV 2U
+#define CUSTOM_LUT_LENGTH 60U
+#define FLEXSPI1_AHB_DATA_ADDRESS (0x28000000U)
+#define FLEXSPI2_AHB_DATA_ADDRESS (0x60000000U)
+
+#define COMBINATION_MODE 0U
+#define FREE_RUNNING_MODE 0U
+
+#define EXAMPLE_FLEXSPI_AMBA_BASE FlexSPI1_AMBA_BASE
+#define FLASH_PAGE_SIZE 256
+#define SECTOR_SIZE 0x1000 /* 4K */
+#define EXAMPLE_FLEXSPI_CLOCK kCLOCK_Flexspi1
+#define FLASH_PORT kFLEXSPI_PortA1
+
+#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 7
+#define NOR_CMD_LUT_SEQ_IDX_READ_FAST 13
+#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD 0
+#define NOR_CMD_LUT_SEQ_IDX_READSTATUS 1
+#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE 2
+#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 3
+#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE 6
+#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD 4
+#define NOR_CMD_LUT_SEQ_IDX_READID 8
+#define NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG 9
+#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10
+#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 11
+#define NOR_CMD_LUT_SEQ_IDX_READSTATUSREG 12
+#define NOR_CMD_LUT_SEQ_IDX_ERASECHIP 5
+
+#define FLASH_QUAD_ENABLE 0x40
+#define FLASH_BUSY_STATUS_POL 1
+#define FLASH_BUSY_STATUS_OFFSET 0
+
+#endif /* FLEXSPI_PORT_H__ */
diff --git a/bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.c b/bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.c
index 0cacdc75f0..2fe2f2dced 100644
--- a/bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.c
+++ b/bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.c
@@ -6,10 +6,12 @@
* Change Logs:
* Date Author Notes
* 2022-09-14 xjy198903 the first version for 1170
+ * 2026-06-03 CoreBoxer support IMXRT1180-EVK
*/
#include <rtthread.h>
-#ifdef BSP_USING_FLEXSPI
+#if defined(BSP_USING_FLEXSPI) && \
+ (defined(SOC_IMXRT1170_SERIES) || defined(SOC_IMXRT1180_SERIES))
#include "board.h"
#include <rtdevice.h>
@@ -17,16 +19,23 @@
#include <finsh.h>
#endif
+#include "drv_flexspi.h"
#include "flexspi_port.h"
#include "fsl_flexspi.h"
+#ifndef COMBINATION_MODE
#define COMBINATION_MODE 1U
+#endif
+
+#ifndef FREE_RUNNING_MODE
#define FREE_RUNNING_MODE 1U
+#endif
#define FLEXSPI_DEBUG
#define LOG_TAG "drv.flexspi"
#include <drv_log.h>
+#if defined(SOC_IMXRT1170_SERIES)
static flexspi_device_config_t deviceconfig = {
.flexspiRootClk = 12000000,
.flashSize = FLASH_SIZE,
@@ -50,6 +59,114 @@ const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
[4 * ARD_SEQ_INDEX] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_8PAD, 0),
};
+#elif defined(SOC_IMXRT1180_SERIES)
+static flexspi_device_config_t deviceconfig = {
+ .flexspiRootClk = 12000000,
+ .flashSize = FLASH_SIZE,
+ .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
+ .CSInterval = 2,
+ .CSHoldTime = 3,
+ .CSSetupTime = 3,
+ .dataValidTime = 0,
+ .columnspace = 0,
+ .enableWordAddress = 0,
+ .AWRSeqIndex = AWR_SEQ_INDEX,
+ .AWRSeqNumber = AWR_SEQ_NUMBER,
+ .ARDSeqIndex = ARD_SEQ_INDEX,
+ .ARDSeqNumber = ARD_SEQ_NUMBER,
+ .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
+ .AHBWriteWaitInterval = 0,
+};
+
+const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
+ /* Normal read mode - SDR */
+ [4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x03,
+ kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
+ [4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 1] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04,
+ kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
+
+ /* Fast read mode - SDR */
+ [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0B,
+ kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
+ [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST + 1] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08,
+ kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
+
+ /* Fast read quad mode - SDR */
+ [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB,
+ kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),
+ [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x06,
+ kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),
+
+ /* Write Enable */
+ [4 * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06,
+ kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
+
+ /* Erase Sector */
+ [4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x20,
+ kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
+
+ /* Page Program - single mode */
+ [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02,
+ kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
+ [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04,
+ kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
+
+ /* Page Program - quad mode */
+ [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32,
+ kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
+ [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04,
+ kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
+
+ /* Read ID */
+ [4 * NOR_CMD_LUT_SEQ_IDX_READID] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F,
+ kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
+
+ /* Write Status Register */
+ [4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01,
+ kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),
+
+ /* Read status register */
+ [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05,
+ kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
+
+ /* Erase whole chip */
+ [4 * NOR_CMD_LUT_SEQ_IDX_ERASECHIP] =
+ FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC7,
+ kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
+};
+#else
+#error "Unsupported SOC for drv_flexspi"
+#endif
+
+/* --------------------------------------------------------------------------
+ * Internal handle
+ * -------------------------------------------------------------------------- */
+static imxrt_flexspi_handle_t s_flexspi_handle =
+{
+ .base = FLEXSPI1_CONTROL_BASE,
+ .port = FLASH_PORT,
+ .ahb_base = FLEXSPI1_AHB_DATA_ADDRESS
+};
+
+imxrt_flexspi_handle_t *imxrt_flexspi_get_handle(void)
+{
+ return &s_flexspi_handle;
+}
static void flexspi_clock_init(clock_root_t root, uint8_t src, uint8_t div)
{
@@ -58,19 +175,26 @@ static void flexspi_clock_init(clock_root_t root, uint8_t src, uint8_t div)
CLOCK_SetRootClockMux(root, src);
}
-static int rt_hw_imxrt_flexspi_init(void)
+FLEXSPI_RAM_CODE static int rt_hw_imxrt_flexspi_init(void)
{
flexspi_config_t config;
FLEXSPI_Type *base;
#ifdef BSP_USING_FLEXSPI1
base = FLEXSPI1_CONTROL_BASE;
+ s_flexspi_handle.base = FLEXSPI1_CONTROL_BASE;
+ s_flexspi_handle.port = FLASH_PORT;
+ s_flexspi_handle.ahb_base = FLEXSPI1_AHB_DATA_ADDRESS;
+ //Set root clk 80MHz
+ flexspi_clock_init(kCLOCK_Root_Flexspi1, CLOCK_SRC, CLOCK_DIV);
#else
base = FLEXSPI2_CONTROL_BASE;
+ s_flexspi_handle.base = FLEXSPI2_CONTROL_BASE;
+ s_flexspi_handle.port = FLASH_PORT;
+ s_flexspi_handle.ahb_base = FLEXSPI2_AHB_DATA_ADDRESS;
+ flexspi_clock_init(kCLOCK_Root_Flexspi2, CLOCK_SRC, CLOCK_DIV);
#endif
- //Set root clk 80MHz
- flexspi_clock_init(kCLOCK_Root_Flexspi1, CLOCK_SRC, CLOCK_DIV);
/*Get FLEXSPI default settings and configure the flexspi. */
FLEXSPI_GetDefaultConfig(&config);
diff --git a/bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.h b/bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.h
new file mode 100644
index 0000000000..d72df3481a
--- /dev/null
+++ b/bsp/nxp/imx/imxrt/libraries/drivers/drv_flexspi.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-03 CoreBoxer support IMXRT1180-EVK
+ */
+
+#ifndef __DRV_FLEXSPI_H__
+#define __DRV_FLEXSPI_H__
+
+#include <rtthread.h>
+#include "fsl_flexspi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Put critical transfer code into ITCM (Code TCM) */
+#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
+#define FLEXSPI_RAM_CODE __attribute__((section("CodeQuickAccess"), noinline))
+#elif defined(__GNUC__)
+#define FLEXSPI_RAM_CODE __attribute__((section("CodeQuickAccess"), noinline))
+#elif defined(__ICCARM__)
+#define FLEXSPI_RAM_CODE __ramfunc
+#else
+#define FLEXSPI_RAM_CODE
+#endif
+
+typedef struct
+{
+ FLEXSPI_Type *base;
+ flexspi_port_t port;
+ uint32_t ahb_base;
+} imxrt_flexspi_handle_t;
+
+/* Get initialized FlexSPI handle (FlexSPI1 or FlexSPI2 decided by BSP config) */
+imxrt_flexspi_handle_t *imxrt_flexspi_get_handle(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRV_FLEXSPI_H__ */