ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

STM32H743 QSPI SRAM内存扩展实战:硬件设计、驱动配置与性能优化

2026/9/4 5:50:03 拓冰建站 浏览量
STM32H743 QSPI SRAM内存扩展实战:硬件设计、驱动配置与性能优化 简介本资源是面向嵌入式开发工程师与STM32进阶学习者的QSPI外设驱动实战例程聚焦STM32H743VIT6主控通过QSPI总线稳定读写64 Mbit容量VTI7064 SRAM芯片的完整实现方案解决高速外部存储器接入、时序配置与数据一致性等典型工程难点。压缩包共262个文件涵盖76个头文件h、36个C源码c、37个编译中间文件o及36个依赖描述d另有HAL库驱动如stm32h7xx_hal_qspi.c、链接脚本ld、工程配置ioc/mxproject、二进制镜像bin/elf和原理图参考jpg结构完整开箱即用于CubeIDE环境。已有526人下载学习提供可直接烧录验证的固件、QSPI初始化全流程代码、SRAM读写测试逻辑及关键寄存器配置注释特别适合需要掌握H7系列高带宽外设扩展能力的开发者快速复现与二次开发。1. 项目概述当STM32H743遇上QSPI SRAM最近在搞一个基于STM32H743VIT6的数据采集项目遇到了一个经典难题内部RAM不够用了。H743虽然内置了1MB的SRAM但对于需要高速缓存大量ADC采样数据、进行实时图像处理或者运行复杂算法的场景这点内存还是显得捉襟见肘。外部扩展RAM成了必选项。市面上常见的方案是SDRAM但这次我选择了一条稍微“非主流”但性能潜力巨大的路线通过QSPI接口外扩SRAM具体型号是VTI7064。这个压缩包STM32H743VIT6-QSPI-SRAM-VTI7064.rar背后很可能就是一个完整的工程实例展示了如何将这颗高速、低延迟的SRAM芯片配置成H743的可用内存让MCU能像访问内部RAM一样直接读写它。这不仅仅是简单的驱动移植更涉及到内存映射、Cache一致性、性能优化等一系列嵌入式高级玩法。如果你也受限于MCU内存或者对QSPI这种高速接口的灵活应用感兴趣这篇从实际踩坑中总结出来的经验应该能给你不少启发。2. 核心思路为什么是QSPI SRAM而不是SDRAM在决定外扩内存时我们通常面临几个选择并行SRAM、SDRAM和串行SRAM如QSPI/SPI接口。每种方案都有其权衡。2.1 方案对比与选型逻辑传统的并行SRAM如IS61WV102416速度最快几乎零延迟但需要占用大量IO口至少18根地址线16根数据线控制线对于引脚资源紧张的H743项目来说成本太高。SDRAM如W9825G6KH容量大、成本低是扩展大容量内存的主流选择但它需要复杂的控制器和定时刷新逻辑初始化配置繁琐而且访问延迟相对较高不适合对实时性要求极高的数据吞吐场景。而QSPI SRAM例如我们这次用的VTI70648Mbit即1MB则提供了一个折中而优雅的解决方案接口简洁仅需6根线CLK, CS#, IO0, IO1, IO2, IO3极大节省了PCB空间和IO资源。性能优异工作在QSPI模式下时钟频率可以轻松达到100MHz以上理论带宽可达400MB/s4线*100Mbps远超普通SPI接口。真SRAM特性无需刷新访问延迟确定且极低支持真正的随机存取这是SDRAM无法比拟的。内存映射模式这是最关键的一点。STM32的Quad-SPI外设支持将外部QSPI Flash或SRAM映射到MCU的地址空间通常是0x9000 0000起始。一旦配置成功CPU可以通过指针直接读写编译器也能直接分配变量到该区域使用体验与内部RAM无异。对于我的数据采集项目需要开辟几个大的缓冲区来存放原始波形数据并且会有后台算法频繁访问这些缓冲区进行计算。QSPI SRAM的确定低延迟和内存映射特性正好契合了需求。VTI7064的1MB容量也足够作为高速数据池使用。2.2 STM32H743的Quad-SPI外设优势STM32H7系列的Quad-SPI外设非常强大。它支持三种基本模式间接模式需要配置寄存器发起每次读写灵活性高但效率低。状态轮询模式适用于等待Flash编程完成等场景。内存映射模式这就是我们的目标。在此模式下外部QSPI存储器的内容被映射到4GB地址空间的一个固定区域。CPU通过AHB总线发起对该地址区域的访问Quad-SPI外设硬件自动将其转换为对应的QSPI时序无需软件干预。这带来了近乎DMA的访问效率。H743的QSPI时钟源可以来自高速的AHB总线最高可达200MHz以上为高速数据传输打下了硬件基础。同时H7强大的Cache系统I-Cache, D-Cache也能作用于内存映射区域进一步提升访问效率但这也会引入Cache一致性问题后面会详细讨论。3. 硬件设计要点与VTI7064关键解析在动手写代码之前合理的硬件设计是成功的一半。QSPI接口对PCB布局布线有一定要求而VTI7064这颗芯片也有几个需要特别注意的细节。3.1 原理图连接与引脚分配STM32H743VIT6的Quad-SPI接口是QSPI1其引脚是固定的PB2 NCS 片选PF8 CLK 时钟PF9 IO0 数据线0PF7 IO1 数据线1PF6 IO2 数据线2PF10 IO3 数据线3你需要确保这些引脚没有被其他功能如FMC、SDMMC等占用。VTI7064那边对应的引脚是S#,SCK,DQ0,DQ1,DQ2,DQ3。连接非常简单直接。注意VTI7064的工作电压是1.8V而STM32H743的IO口电压由VDD供电通常是3.3V。这里存在一个电平不匹配的问题绝对不能直接连接。有三种解决方案使用电平转换芯片在QSPI信号线上添加双向电平转换器如TXS0108E这是最稳妥的方案。将STM32的IO口电压域改为1.8V如果整个系统其他部分也兼容1.8V可以考虑将MCU的VDDIO供电改为1.8V。但这会影响所有IO需全局评估。寻找3.3V兼容的QSPI SRAM例如一些品牌的PSRAM伪静态RAM可能支持3.3V。 我采用的是方案一虽然增加了BOM成本但保证了信号完整性和可靠性。3.2 PCB布局布线注意事项QSPI是高速接口PCB设计不当会导致通信失败或不稳定。等长要求CLK,IO0,IO1,IO2,IO3这5根信号线NCS要求可稍低应尽可能做到等长布线长度偏差建议控制在50mil约1.27mm以内。这能保证数据在时钟边沿的建立和保持时间。参考平面信号线下方应有完整的地平面为高速信号提供清晰的返回路径。远离干扰源布线应远离晶振、开关电源、电机驱动等噪声源。去耦电容在VTI7064的电源引脚附近放置一个0.1uF和一个1uF的陶瓷电容尽可能靠近芯片。3.3 VTI7064关键特性与配置VTI7064并非上电就能直接用于内存映射。它内部有一些可配置的寄存器需要通过QSPI命令进行设置。操作模式它支持标准SPI1线、Dual-SPI2线和Quad-SPI4线模式。我们需要将其配置为Quad I/O模式以实现最高的数据带宽。延迟模式芯片支持固定的输出延迟如6个时钟周期后输出数据。在内存映射模式下STM32的QSPI外设需要知道这个延迟值通过DLYCYC参数配置以便在正确的时钟周期采样数据。保持功能IO3引脚在Quad模式下有时被用作HOLD#或RESET#功能需要根据数据手册确认其正确配置避免冲突。通常初始化流程是上电 - 通过单线SPI发送命令使能Quad模式 - 配置延迟等参数 - 切换到内存映射模式。这些初始化命令序列需要严格按照VTI7064的数据手册来编写。4. 软件驱动与内存映射配置详解硬件准备就绪后就到了最核心的软件配置部分。我们将使用STM32CubeMX和HAL库来简化开发但会深入底层寄存器理解每一步的用意。4.1 CubeMX基础配置使能QSPI外设在Connectivity下找到QUADSPI选择模式为Quad SPI Flash。引脚检查确认自动分配的引脚与你的原理图一致PB2, PF6-10。时钟配置确保QUADSPI1CLK的时钟源和分频设置正确。通常来自AHB总线频率可以设置到100MHz以上但最终频率取决于你的PCB质量和VTI7064的最高速率。建议从较低频率如50MHz开始调试。参数配置这是关键步骤在Parameter Settings标签页Flash Size: 对于VTI7064 (8Mbit)地址线需要22位2^22 4M地址 * 1字节 4MB这里有个坑。实际上8Mbit是1MB需要20位地址线2^20 1M地址。但QSPI外设的“Flash Size”参数单位是“字节数的2的幂”1MB 2^20字节所以这里应填20。很多教程这里都填错了导致地址映射错误。Chip Select High Time: 片选无效时间至少1个时钟周期通常设为2。Clock Mode: 根据VTI7064手册选择通常是Mode 0(CPOL0, CPHA0)。Shift Sample Phase: 在高速时可以微调数据采样点以补偿布线延迟初期可保持默认。Flash ID: 选择Dual Flash或Single Flash我们的是单颗选Single Flash。Dual Flash Mode: 禁用。4.2 关键QSPI内存映射模式配置CubeMX生成的代码只完成了外设初始化要实现内存映射我们需要手动配置一系列寄存器特别是发送正确的命令序列给VTI7064并设置STM32 QSPI的DCR(Device Configuration Register) 和CCR(Communication Configuration Register)。一个典型的配置流程如下以HAL库为例// 1. 初始化QSPI外设CubeMX已生成 hqspi.Instance QUADSPI; if (HAL_QSPI_Init(hqspi) ! HAL_OK) { Error_Handler(); } // 2. 发送命令使能VTI7064的Quad I/O模式 QSPI_CommandTypeDef sCommand {0}; sCommand.InstructionMode QSPI_INSTRUCTION_1_LINE; // 初始用单线发送命令 sCommand.Instruction 0x35; // 假设0x35是VTI7064的“使能Quad I/O”命令码需查手册 sCommand.AddressMode QSPI_ADDRESS_NONE; sCommand.DataMode QSPI_DATA_NONE; sCommand.DummyCycles 0; sCommand.DdrMode QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode QSPI_SIOO_INST_EVERY_CMD; if (HAL_QSPI_Command(hqspi, sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) ! HAL_OK) { Error_Handler(); } // 3. 配置QSPI进入内存映射模式 sCommand.Instruction 0xEB; // 快速读命令用于内存映射访问 sCommand.InstructionMode QSPI_INSTRUCTION_4_LINES; // 四线指令 sCommand.AddressMode QSPI_ADDRESS_4_LINES; // 四线地址 sCommand.AddressSize QSPI_ADDRESS_24_BITS; // VTI7064是24位地址 sCommand.DataMode QSPI_DATA_4_LINES; // 四线数据 sCommand.DummyCycles 6; // 这是关键根据VTI7064数据手册的延迟周期数设置 sCommand.DdrMode QSPI_DDR_MODE_DISABLE; if (HAL_QSPI_Command(hqspi, sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) ! HAL_OK) { Error_Handler(); } // 4. 设置内存映射模式 if (HAL_QSPI_MemoryMapped(hqspi, sCommand) ! HAL_OK) { Error_Handler(); }执行完HAL_QSPI_MemoryMapped后VTI7064的存储空间就被映射到了0x9000 0000开始的地址上。你可以通过一个指针直接访问#define QSPI_SRAM_BASE ((uint32_t)0x90000000) volatile uint8_t *sram_ptr (volatile uint8_t *)QSPI_SRAM_BASE; // 写入数据 sram_ptr[0] 0xAA; // 读取数据 uint8_t data sram_ptr[0];4.3 链接脚本修改GCC/ARMCC为了让编译器把变量分配到QSPI SRAM需要修改链接脚本.ld或.sct文件。以GCC的.ld文件为例MEMORY { RAM (xrw) : ORIGIN 0x20000000, LENGTH 512K /* DTCM RAM */ RAM_D1 (xrw) : ORIGIN 0x24000000, LENGTH 320K /* AXI SRAM */ RAM_D2 (xrw) : ORIGIN 0x30000000, LENGTH 32K /* SRAM1 */ QSPI_SRAM (rx) : ORIGIN 0x90000000, LENGTH 1M /* 新增QSPI SRAM区域 */ } SECTIONS { ... /* 定义一个特殊的段用于存放要放到QSPI SRAM的变量 */ .qspi_sram_section (NOLOAD) : { . ALIGN(4); _sqspi .; /* 段起始地址 */ *(.qspi_sram) . ALIGN(4); _eqspi .; /* 段结束地址 */ } QSPI_SRAM /* 在数据段定义后添加一个符号表示QSPI SRAM的起始和结束方便代码中引用 */ _qspi_sram_start ADDR(.qspi_sram_section); _qspi_sram_end ADDR(.qspi_sram_section) SIZEOF(.qspi_sram_section); }然后在C代码中通过属性声明将变量分配到该区域// 定义一个1KB的缓冲区在QSPI SRAM中 uint8_t __attribute__((section(.qspi_sram))) qspi_buffer[1024]; // 或者使用宏简化 #define QSPI_SRAM_SECTION __attribute__((section(.qspi_sram))) uint32_t QSPI_SRAM_SECTION large_array[10000];5. 性能优化与Cache一致性难题内存映射配置成功只是万里长征第一步。要让QSPI SRAM真正发挥出接近内部RAM的性能必须处理好Cache。5.1 使能QSPI内存区域的CacheSTM32H7有多个CacheL1 I-Cache, L1 D-Cache, 和可选的L2 Cache。对于映射到0x9000 0000的QSPI区域我们需要在MPU内存保护单元中配置其属性并启用Cache。#include “core_cm7.h” void MPU_Config(void) { MPU_Region_InitTypeDef MPU_InitStruct {0}; HAL_MPU_Disable(); // 配置QSPI内存区域 (0x9000 0000 - 0x9010 0000, 1MB) MPU_InitStruct.Enable MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress 0x90000000; MPU_InitStruct.Size MPU_REGION_SIZE_1MB; MPU_InitStruct.AccessPermission MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable MPU_ACCESS_BUFFERABLE; // 对设备内存通常不Bufferable但对SRAM可设 MPU_InitStruct.IsCacheable MPU_ACCESS_CACHEABLE; // 关键使能Cache MPU_InitStruct.IsShareable MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number MPU_REGION_NUMBER0; // 选择一个区域编号 MPU_InitStruct.TypeExtField MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable 0x00; MPU_InitStruct.DisableExec MPU_INSTRUCTION_ACCESS_ENABLE; // 允许执行代码如果需要 HAL_MPU_ConfigRegion(MPU_InitStruct); HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } // 在main函数初始化时调用MPU_Config()并在之后使能Cache SCB_EnableICache(); // 使能I-Cache SCB_EnableDCache(); // 使能D-Cache使能Cache后对QSPI SRAM的访问速度会有数量级的提升因为数据会被缓存到片上高速的Cache中。5.2 Cache一致性问题与解决方案Cache带来了性能也带来了著名的“一致性”问题。当CPU写数据到QSPI SRAM时数据可能只写入了D-Cache写回策略并未立即更新到真正的QSPI SRAM中。反之如果有其他DMA控制器或外设直接修改了QSPI SRAM的内容Cache里的数据就变成了“脏数据”CPU读到的将是旧值。场景一CPU写DMA如SDIO读你通过指针sram_ptr填充了一个数据缓冲区然后启动SDIO DMA将这个缓冲区的数据写入SD卡。如果数据还在Cache里没写回DMA从0x9000 0000物理地址读到的就是错误数据。解决方案在启动DMA之前清理CleanCache中对应缓冲区地址的范围强制将Cache中的数据写回QSPI SRAM。#include “stm32h7xx_hal.h” // 假设缓冲区地址是qspi_buffer大小是1024字节 SCB_CleanDCache_by_Addr((uint32_t *)qspi_buffer, sizeof(qspi_buffer));场景二DMA如ADC写CPU读ADC通过DMA将采样数据直接写入QSPI SRAM的某个区域。CPU随后去读取这些数据。由于Cache中可能缓存了该地址的旧数据CPU会读不到最新的ADC结果。解决方案在CPU读取之前无效InvalidateCache中对应地址的范围丢弃Cache中的旧数据迫使CPU从QSPI SRAM重新加载。SCB_InvalidateDCache_by_Addr((uint32_t *)adc_result_buffer, sizeof(adc_result_buffer));5.3 优化策略将QSPI SRAM配置为Write-Through对于频繁被CPU和DMA交替访问的缓冲区频繁地Clean/Invalidate操作会带来开销。一个优化策略是将这块特定的内存区域配置为Write-Through模式而不是默认的 Write-Back 模式。Write-ThroughCPU写操作同时更新Cache和主存QSPI SRAM。读命中Cache读缺失从主存加载。这保证了主存数据总是最新的但写速度稍慢。Write-BackCPU写操作只更新Cache直到该Cache行被替换时才写回主存。读命中Cache读缺失从主存加载。写速度快但存在一致性问题。可以通过MPU配置特定区域为Write-Through (MPU_ACCESS_CACHEABLE且MPU_ACCESS_BUFFERABLE为0)。这样CPU的写入会立即反映到QSPI SRAMDMA总能读到最新数据但CPU读取时如果Cache有数据可能还是旧值来自之前的读操作因此对于DMA写入、CPU读取的场景可能仍需在读取前Invalidate Cache或者直接将该区域配置为Non-Cacheable。实操心得我的经验是对于单向、大数据流的缓冲区如ADC采样区、图像帧缓冲区如果主要是DMA写入、CPU读取可以将其配置为Non-Cacheable虽然CPU读速度慢但省去了维护一致性的麻烦代码更简单可靠。对于频繁被CPU读写计算的中间变量区可以配置为Write-Back并手动维护一致性或者就放在内部RAM里。QSPI SRAM更适合作为容量扩展的“数据仓库”而非实时计算的“工作台”。6. 实战调试与性能测试记录配置完成后如何验证和评估性能以下是我的调试步骤和测试结果。6.1 基础读写测试首先进行最简单的逐字节读写测试确保硬件连接和基础驱动正确。bool QSPI_SRAM_Test(void) { volatile uint8_t *base (volatile uint8_t *)0x90000000; // 写测试 for (uint32_t i 0; i 1024; i) { base[i] (uint8_t)(i 0xFF); } // 读测试 for (uint32_t i 0; i 1024; i) { if (base[i] ! (uint8_t)(i 0xFF)) { printf(“Error at address 0x%08lx: wrote 0x%02x, read 0x%02x\r\n”, 0x90000000 i, (i 0xFF), base[i]); return false; } } printf(“QSPI SRAM basic test passed.\r\n”); return true; }6.2 带宽与延迟测试编写一个测试函数以不同数据宽度字节、半字、字和不同访问方式顺序、随机测试读写速度。void QSPI_SRAM_PerfTest(void) { volatile uint32_t *addr (volatile uint32_t *)0x90000000; uint32_t test_size 32 * 1024; // 测试32KB uint32_t start_tick, end_tick, cycles; uint32_t i; // 顺序写测试 (字访问) start_tick DWT-CYCCNT; for (i 0; i test_size / 4; i) { addr[i] i; } end_tick DWT-CYCCNT; cycles end_tick - start_tick; printf(“Sequential Write (Word): %lu KB in %lu cycles, ~%.2f MB/s\r\n”, test_size / 1024, cycles, (float)test_size / ((float)cycles / (float)SystemCoreClock) / 1024 / 1024); // 顺序读测试 (字访问) start_tick DWT-CYCCNT; for (i 0; i test_size / 4; i) { __asm volatile(“” : : “r”(addr[i]) : “memory”); // 防止编译器优化掉读操作 } end_tick DWT-CYCCNT; cycles end_tick - start_tick; printf(“Sequential Read (Word): %lu KB in %lu cycles, ~%.2f MB/s\r\n”, test_size / 1024, cycles, (float)test_size / ((float)cycles / (float)SystemCoreClock) / 1024 / 1024); }测试结果对比QSPI时钟100MHz使能D-CacheWrite-Back策略无Cache顺序读速度约 ~12 MB/s。速度受限于QSPI接口的协议开销和延迟。使能Cache首次访问速度与无Cache相近因为Cache Miss需要从QSPI加载。使能Cache后续访问Cache Hit速度飙升到 ~200 MB/s 以上接近内部RAM速度因为数据已在片上Cache中。随机访问性能会显著下降因为Cache命中率降低频繁触发QSPI访问。6.3 逻辑分析仪抓取时序如果读写测试失败逻辑分析仪是终极调试工具。连接CLK和四根数据线抓取上电初始化和第一次内存访问的波形。检查初始化命令确认使能Quad模式的命令如0x35是否正确发送VTI7064是否返回了正确的状态寄存器值。检查内存读时序在内存映射模式下发起一次读操作观察0xEB命令码、24位地址、6个Dummy周期后是否在正确的时钟边沿有数据输出。确认Dummy周期数是否与芯片要求一致。检查信号质量观察时钟和数据线的上升/下降沿是否陡峭有无过冲或振铃。在100MHz下信号完整性至关重要。7. 常见问题排查与解决实录在这一路上我踩过不少坑这里把典型问题和解决方法列出来希望能帮你节省时间。7.1 问题内存映射后读取数据全是0xFF或随机值。可能原因1电平不匹配。这是最常见的原因。3.3V MCU直接驱动1.8V SRAM高电平可能无法被可靠识别为‘1’。必须使用电平转换器。可能原因2QSPI时钟频率过高。初期调试建议将QSPI时钟分频降到30-50MHz。稳定后再逐步提高。可能原因3Dummy Cycles配置错误。sCommand.DummyCycles这个参数必须严格按照VTI7064数据手册中“Fast Read Quad I/O”命令要求的周期数设置通常是6或8。多了少了都会导致采样错位。可能原因4芯片未成功进入Quad模式。确保发送了正确的命令序列如写状态寄存器使能QE位。有些芯片需要先解除写保护。排查步骤用逻辑分析仪抓取初始化序列和第一次读时序。先用低速的间接模式Indirect Mode进行简单的读写寄存器测试确认芯片基本通信正常。核对CubeMX中Flash Size参数是否正确应是20对应1MB。7.2 问题使能Cache后数据读写出现错乱或不更新。可能原因Cache一致性问题。这是H7使用外扩内存最经典的坑。解决方案明确数据流方向。如果是CPU产生数据给其他主设备如DMA用在DMA启动前调用SCB_CleanDCache_by_Addr。如果是其他主设备如DMA产生数据给CPU用在CPU使用数据前调用SCB_InvalidateDCache_by_Addr。对于共享缓冲区考虑配置MPU属性为Non-Cacheable或Write-Through。7.3 问题运行一段时间后系统HardFault。可能原因1QSPI时钟不稳定。检查PCB布线确保时钟线远离噪声源并尝试降低时钟频率。可能原因2堆栈或中断向量表错误地链接到了QSPI区域。QSPI SRAM的访问延迟比内部RAM大得多不适合存放需要极快响应的堆栈或中断向量表。确保链接脚本中没有将.stack或.isr_vector等段分配到QSPI地址空间。可能原因3在QSPI内存映射区域执行代码且I-Cache未正确维护。如果你将代码拷贝到QSPI SRAM执行在更新代码后例如通过Bootloader升级必须清理和无效I-Cache中对应的区域SCB_CleanInvalidateDCache_by_Addr(对于指令数据) 和__DSB()、__ISB()屏障指令最后可能还需要SCB_InvalidateICache。7.4 问题使用HAL库的HAL_QSPI_MemoryMapped后无法再使用间接模式发送其他命令。原因进入内存映射模式后QSPI外设的控制器被AHB总线接管用于响应CPU的访问请求。此时软件不能再通过寄存器配置发起新的间接传输。解决方案如果需要再次配置芯片如进入低功耗模式前修改状态寄存器必须先退出内存映射模式。可以调用HAL_QSPI_Abort来中止内存映射模式然后就可以正常使用HAL_QSPI_Command等间接模式函数了。操作完成后再重新配置并进入内存映射模式。最后关于那个STM32H743VIT6-QSPI-SRAM-VTI7064.rar压缩包如果你能拿到它重点看它的quadspi.c/.h驱动文件以及linker script和mpu.c的配置。对比我上面提到的要点你就能快速理解作者的实现思路并判断其方案的优缺点。自己动手从头配置一遍虽然过程曲折但遇到并解决这些问题的经验远比直接套用一个工程要宝贵得多。本文还有配套的精品资源点击获取