总体概述
随着嵌入式AI、机器视觉与语音识别等应用逐渐向边缘侧迁移,MCU正在承载越来越复杂的算法和模型。这一趋势对存储资源提出了前所未有的挑战——算力或许够用,但Flash往往成为最先触顶的瓶。
NXP MCXN947是一款性能强劲的Cortex‑M33微控制器,片上集成了容量可观的内部Flash,足以应对大多数传统控制与通信场景。然而,在使用eIQ工具链部署深度神经网络模型(如TFLM推理、图像分类等)时,模型权重与常量数据的体积很容易超过内部Flash的承载能力,使得“全部放在内部Flash”这一方案难以为继。
MCXN947同时支持外部Flash启动与XIP(Execute In Place),但在常规使用中,系统往往只能选择一种启动介质,执行入口也随之固定。那么,是否存在一种更加灵活的方式?
系统仍然从内部Flash启动,保证启动速度和稳定性;
但将体积庞大的模型或部分代码放入外部Flash,并直接XIP执行?
答案是肯定的。
本文将基于FRDM‑MCXN947开发板,详细介绍我实现的一个 “内部Flash启动 + 外部Octal Flash XIP执行” 的混合存储Demo。从硬件原理、FlexSPI配置、MCUXpresso工程设置,到链接脚本与模型段的放置策略,完整拆解这一方案的设计思路与实现细节,为在MCU上部署大模型提供一种切实可行、可复用的解决路径。
硬件环境:
开发板:FRDM-MCXN947
软件环境:
IDE:MCUXpresso IDE v11.9.0
SDK:SDK Builder | MCUXpresso SDK Builder (nxp.com)
基础工程: frdmmcxn947_tflm_cifar10
一、外部Flash硬件配置与管脚配置
以下是官方FRDM-MCXN947中的八线Flash的原理图:

根据以上原理图,置与FlexSPI连接的外部Octal Flash相关的引脚。你需要启用以下管脚功能:

配置代码例如:
/* Enables the clock for PORT3: Enables clock */
CLOCK_EnableClock(kCLOCK_Port3);
constport_pin_config_tport3_0_pinB17_config = {/* Internal pull-up/down resistor is disabled */
kPORT_PullDisable,
/* Low internal pull resistor value is selected. */
kPORT_LowPullResistor,
/* Fast slew rate is configured */
kPORT_FastSlewRate,
/* Passive input filter is disabled */
kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
kPORT_OpenDrainDisable,
/* Low drive strength is configured */
kPORT_LowDriveStrength,
/* Pin is configured as FLEXSPI0_A_SS0_b */
kPORT_MuxAlt8,
/* Digital input enabled */
kPORT_InputBufferEnable,
/* Digital input is not inverted */
kPORT_InputNormal,
/* Pin Control Register fields [15:0] are not locked */
kPORT_UnlockRegister};
/* PORT3_0 (pin B17) is configured as FLEXSPI0_A_SS0_b */
PORT_SetPinConfig(PORT3, 0U, &port3_0_pinB17_config);
// ...依次配置其他FLEXSPI管脚...
二、FlexSPI模块初始化
为了使用FlexSPI进行XIP,需正确配置时钟并初始化FlexSPI模块。以下是关键步骤:
2.1 配置FlexSPI时钟
/* Flexspi frequency 150MHz / 2 = 75MHz */ CLOCK_SetClkDiv(kCLOCK_DivFlexspiClk, 2U); CLOCK_AttachClk(kPLL0_to_FLEXSPI); /*!< Switch FLEXSPI to PLL0 */
2.2 添加FlexSPI驱动并初始化
在工程中引入FlexSPI驱动(SDK中已有),然后在主程序中添加初始化代码:
/*Get FLEXSPI default settings and configure the flexspi. */ FLEXSPI_GetDefaultConfig(&config); /*Set AHB buffer size for reading data through AHB bus. */ config.ahbConfig.enableAHBPrefetch = true; config.rxSampleClock = EXAMPLE_FLEXSPI_RX_SAMPLE_CLOCK; config.ahbConfig.enableAHBBufferable = true; config.ahbConfig.enableAHBCachable = true; FLEXSPI_Init(base, &config); /* Configure flash settings according to serial flash feature. */ FLEXSPI_SetFlashConfig(base, &deviceconfig, FLASH_PORT); #ifdefined(EXAMPLE_FLASH_RESET_CONFIG) uint32_t TempFastReadSDRLUTCommandSeq[4]; memcpy(TempFastReadSDRLUTCommandSeq, FastReadSDRLUTCommandSeq, sizeof(FastReadSDRLUTCommandSeq)); #endif
三、配置MCUXpresso工程支持Octal Flash
在MCUXpresso IDE中,进入MCU Settings > Memory,添加一个新的memory区域:
名称:OSPI_FLASH(或 OCTAL_FLASH)
起始地址:根据你芯片连接的外部flash地址设置,

根据用户手册,FLEXSPI起始地址为0x80000000
大小:例如128MB
然后,选择NXP提供的对应外部flash驱动,FRDM_MCXN947连接flash为mt35xu512aba,该flash支持SFDP,故我们可以选择MCXN9xx_SFDP_FlexSPI.cfx添加后,可以看到Memory details如下:

四、添加链接脚本和模型数据迁移
4.1 创建链接脚本片段
在工程的linkscripts/文件夹中添加两个文件:
text.ldt(用于代码段)
rodata.ldt(用于模型只读数据)
内容如下:
<#if memory.name=="OSPI_FLASH">KEEP (*(.model_data*))
KEEP (*(model.o*))
KEEP(*(.text.OSPI_FLASH*))
*(.text.QSPI_FLASH*)
*(.text.${memory.alias}*)
*(.text.${memory.name}*)
</#if>确保模型数据(如 .model_data 段)被正确保留并放入XIP区域。
4.2 模型数据放入XIP区域
将模型通过如下方式放置到 .model_data 段中(C代码):
__attribute__((section(".model_data")))
const unsigned char model_data[] = {
#include "model_data.inc" // 从模型文件导出的原始数据
};
五、编译与验证
在构建项目后,MCUXpresso IDE的映像映射报告将显示部分 .text 和 .rodata 段已成功放置至 Octal Flash(OSPI_FLASH)区域:
OSPI_FLASH: 100144B 262140KB 0.04%

下载运行后,系统从内部Flash启动,并成功从外部Flash中直接读取模型数据,完成AI推理任务。

结语
通过本文所介绍的配置与实践,MCXN947成功实现了一种“内部启动 + 外部XIP执行”的混合存储架构:
系统仍然从内部Flash启动,确保启动链路简洁、可靠且快速;而体量庞大的模型权重与只读资源,则被无缝迁移至外部Octal Flash,并通过FlexSPI以XIP的方式直接访问和执行。这一方案无需复杂的二级引导或运行期拷贝,不仅显著扩展了可用的程序与数据空间,也保持了系统结构的清晰和维护友好性。在实际的AI推理任务中,模型可以被像普通只读数据一样访问,应用层逻辑几乎无需感知其物理存放位置。
对于Flash资源受限但又希望在MCU平台上运行复杂AI模型的开发者而言,这种架构提供了一条非常现实且工程化可落地的路径。可以预见,随着边缘AI的进一步普及,“内部小而快+外部大而灵活”的存储组织方式,将成为越来越多高端MCU项目的标准设计思路之一。
希望本文的实践经验,能够为你在MCXN947或其他支持XIP的MCU平台上,构建更大规模、更高复杂度的应用提供参考与启发。
作者:Harry Zhang
来源:恩智浦MCU加油站
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。