单XSPI实例双PSRAM集成方案与调试实战
1. 集成前的关键认知PSRAM与XSPI基础原理1.1 PSRAM是怎么回事为什么需要两颗PSRAMPseudo Static Random Access Memory伪静态随机存储器是一种很特殊的内存颗粒。它外部接口跟普通SRAM一样不需要像DRAM那样由主控持续刷新但内部实际上还是DRAM阵列只不过刷新逻辑被封装进了芯片内部。所以从用户视角看它就是一颗“不用管刷新时序”的大容量RAM读写时序简单容量又可以做到比SRAM大很多价格也低不少。这个特性在嵌入式领域非常吃香尤其当你的MCU内部SRAM只有几百KB而应用却需要几MB的帧缓冲、音频缓冲或者神经网络中间数据时外挂一颗PSRAM几乎是标准解法。但一颗PSRAM的容量往往不够用。常见PSRAM有8MB、16MB、32MB如果你跑GUI需要双缓冲或者要存多帧图像再做算法处理单颗容量就捉襟见肘了。这时候最直接的办法就是再加一颗PSRAM。不过新增一颗存储颗粒意味着主控引脚要多出一套地址线、数据线、控制线如果MCU的引脚本来就不富裕这个方案就非常痛苦。我实测过很多Cortex-M系列芯片哪怕封装做到BGA能同时引出两套并行PSRAM总线的也极少信号完整性还容易出问题。所以大家在设计上更倾向复用总线也就是把两颗PSRAM挂在同一条总线上分片选或者合并地址空间来操作。而XSPIOctal SPI / eXecute in Place SPI扩展SPI接口的出现正好把这个问题简化了一大截。它用4线、8线甚至16线的数据总线配合地址命令协议就能访问外部存储带宽虽然比并行总线低一点但胜在引脚少、时序简单、扩展灵活。很多现代SoC已经把XSPI做成一个专门的外设实例内部有独立的缓存控制器和地址映射窗口理论上你可以在一个XSPI实例下面接多颗PSRAM这就是标题里“How to Integrate 2 PSRAM in one XSPI instance”这件事的真正起点。1.2 XSPI实例与片选的逻辑关系要在一个XSPI实例上接两颗PSRAM先要搞明白XSPI控制器到底怎么“区分”这两颗芯片。XSPI本质上是一条主从总线Master是MCU里集成的XSPI控制器Slave是挂在上面的Flash、PSRAM等存储颗粒。控制器通过片选信号CS来选中某个从设备理论上一个实例可以引出多个CS线也可以只引出一个CS线但在命令层面区分设备。在MCU内部XSPI实例通常还伴随一个内存映射窗口。比如某款芯片把0x80000000到0x9FFFFFFF这段地址空间分配给了XSPI实例你可以把这段空间拆成两个区域一个区域映射到PSRAM0另一个区域映射到PSRAM1。这样CPU访问0x80000000时就选中PSRAM0访问0x81000000时就选中PSRAM1完全由地址译码逻辑决定硬件自动切换片选。这个设计思路和典型的多片NOR Flash接在同一个QUAD SPI实例上是完全一致的只是PSRAM和Flash在命令集、时序、初始化流程上有差异。如果控制器只支持一个片选那就需要在外部用额外的GPIO模拟片选或者用多路复用器但这种做法会带来额外的延迟和逻辑开销。所以我个人建议选型阶段就要确认你用的MCU的XSPI实例是否支持多个CS信号。如果支持那么引脚上就会有两根CS脚如果不支持那就得赶紧评估是否换一个封装更大、外设更多的型号免得后面做板子时骑虎难下。1.3 PSRAM与NOR Flash在XSPI上的本质差异很多人一开始会把PSRAM当成“能读能写的Flash”来用其实这是一个大坑。PSRAM和NOR Flash虽然共享XSPI接口但协议差异非常大初始化过程不同。Flash需要读JEDEC ID、配置状态寄存器、开启QPI或OPI模式PSRAM也需要读ID、配置延迟链、设置突发长度和驱动强度。写入方式不同。Flash要按页写入写之前还要擦除整个过程慢而且有寿命限制PSRAM是随机写入按字节、半字、字都行没有擦除过程寿命也远高于Flash。数据保持不同。Flash断电后数据还在PSRAM断电后数据全丢。PSRAM内部有刷新逻辑但外部必须保证供电和时钟稳定。地址空间映射方式不同。Flash通常只读映射写操作要通过命令序列完成PSRAM在XSPI实例中一般支持读和写映射CPU可以直接向映射地址写数据。这几点决定了你在把一个XSPI实例从“接Flash”切换到“接PSRAM”时不能只改器件型号还得重新配置控制器的协议模式、时序参数和地址窗口。后面我会讲到具体的寄存器配置这些都是实操中必须注意的地方。2. 整体设计方案拆解从芯片选型到拓扑选择2.1 单实例双片选拓扑 vs 单个片选双芯片堆叠在开始画原理图之前先要决定你采用哪种拓扑结构。我这边接触到的主流方案有两种方案AXSPI实例引出两个片选信号分别接两颗PSRAM的CS脚。两颗PSRAM共享CLK、数据线、地址线但CS各自独立。这种方式硬件设计最简单软件上也比较好理解一个地址区间对应一个片选互不干扰。方案BXSPI实例只引出一个片选信号两颗PSRAM都接在同一个CS上依靠软件在读写命令中附加设备地址来实现区分。这种方式要求PSRAM支持“级联”或者“双芯片选择”功能不是所有型号都支持。如果PSRAM不支这种操作那就只能把两颗PSRAM做地址空间拼接让它们的内部地址映射到同一个XSPI窗口的高低位不过这种操作要求PSRAM有地址线配合不适用于纯串行接口的PSRAM。我在实际项目里常用的是方案A。原因很简单市面上大多数PSRAM芯片特别是针对嵌入式应用的XRAM、APS256XX系列都是标准单芯片使能接口不具备级联功能。强行用方案B往往需要改芯片内部配置而且时序余量很难保证。方案A的单片机端只要XSPI实例支持两个CS、支持独立的CS片选时序配置就能非常稳定地工作。2.2 地址空间分配与映射窗口计算无论哪种方案你都需要有一个清晰的地址分配计划。假设你的MCU分配了一个连续的XSPI映射区域比如从0xC0000000开始总大小0x200000032MB。如果你接了两颗16MB的PSRAM可以简单地把区域等分成两个16MB窗口窗口00xC0000000 ~ 0xC0FFFFFF映射到PSRAM0窗口10xC1000000 ~ 0xC1FFFFFF映射到PSRAM1这里的计算很简单就是从基地址加上容量偏移。但要注意有些MCU的XSPI地址窗口存在对齐要求窗口起始地址必须按容量对齐所以你可能需要微调。如果MCU只支持固定大小的XSPI窗口不支持拆分那你就要在软件里做地址重映射用辅助函数把逻辑地址转换成物理偏移。另外还要确认地址映射的位宽。如果PSRAM是8MB但地址窗口配成了16MB那么高位地址线会悬空可能导致访问越界时读到未知数据。我建议把窗口容量设置为实际PSRAM容量即使用不到那么大的空间也避免访问出错。2.3 引脚安排与信号完整性考量XSPI的信号频率通常不低我在某些项目中跑到100MHz甚至更高。这种情况下引脚分配不能只看方便画PCB还得考虑信号质量。具体来说时钟线要保持短而直避免过孔过多。数据线尽量等长长度差尽量控制在几百mil以内。片选信号可以长一点但也要避免绕得太远。如果有DQS信号务必保持和时钟的相位关系尽量不要反相。如果你用的是双片选方案两个CS在物理上可能会离其中一颗PSRAM较近离另一颗较远。此时最好在靠近远端PSRAM的CS引脚附近加上拉电阻避免CS悬空时电平不稳定。我见过一块板子因为CS走线太长导致远端PSRAM在低温下偶发误选中最后就是加了一个10k上拉解决的。2.4 在同一个XSPI实例上混合Flash与PSRAM有些项目更复杂还希望在一个XSPI实例上同时接Flash和PSRAM。实际也是可行的只要XSPI控制器支持多个CS并且不同CS可以使用不同的协议模式。比如CS0接Quad SPI Flash用于存放代码CS1接Octal PSRAM用于数据缓冲区。这时你需要非常小心地配置每个CS的时序和指令集。Flash和PSRAM的读指令可能完全不同甚至数据线宽度都不一样。假设Flash用Quad模式4条数据线PSRAM用Octal模式8条数据线那么PCB布线时数据线数量就不一致要预留好。MCU端的XSPI控制器通常允许为每个CS独立配置指令格式、数据线宽度和时序这种灵活性非常关键。如果控制器不支持那就只能全部统一成最保守的配置比如都用Quad模式这样PSRAM的带宽会受到限制但至少能工作。3. XSPI控制器与PSRAM时序参数的匹配3.1 建立时间、保持时间与采样延迟XSPI控制器对PSRAM的访问本质上就是在时钟沿驱动数据在另一个时钟沿采样数据。PSRAM内部有同步逻辑外部数据需要在特定的采样窗口内保持稳定。你既需要看PSRAM数据手册里的setup time和hold time也需要看控制器手册里的输出延迟和输入采样延迟参数。实际操作中我一般按这样的步骤来匹配先确认PSRAM的最高工作频率以及在该频率下的tV时钟到数据输出有效延迟和tSU/tH。再看MCU的XSPI输出路径上有多少组合逻辑延迟通常可以在控制器寄存器里配置一个“采样延迟”或者“输入延迟链”。如果不能确定就直接跑读回测试。先写入一串伪随机数再读出来比较如果失败逐步调整采样延迟值。注意PSRAM不像Flash那样读操作有很长的tACC时间它的读延迟主要取决于内部流水线和突发长度一般会有一个固定的Latency Count。你在配置命令时发给PSRAM的读命令里要包含读延迟参数同时控制器端的采样点又要和这个延迟匹配两边是联动的。3.2 总线宽度与线序配置XSPI常见的有SDR和DDR两种模式。SDR模式下每个时钟沿传输1比特DDR模式下上升沿和下降沿各传输一次。PSRAM如果是HSCA系列通常支持DDR模式但控制器未必支持。如果控制器只支持SDR那么PSRAM的DDR功能也只能闲置。另一个问题是线宽。单线SPI、双线Dual SPI、四线Quad SPI、八线Octal SPI每种模式下的命令和地址阶段都不一样。一般流程是命令阶段可以用同一种线宽也可以固定为单线传输。地址阶段用窄线宽或宽线宽取决于XSPI控制器的配置。我建议在初始化和测试阶段先用单线模式把ID读出来确认连接没问题再切换到更宽的线宽这样能降低排查难度。一个常见错误是PSRAM还处于默认SPI模式但控制器已经用了Octal模式发命令结果PSRAM完全无响应。正确的顺序是先配置控制器为SPI模式用SPI命令让PSRAM进入Octal模式最后再把控制器切到Octal模式。3.3 驱动强度与终端电阻PSRAM引脚的电平翻转速度直接影响信号质量。你不能简单地把PSRAM驱动强度调到最大因为太强的驱动会导致过冲和振铃尤其在高频下更严重。需要根据PCB走线阻抗和负载电容选择合适的驱动强度。一般PSRAM芯片会提供驱动强度寄存器比如可以设置为H-Z、弱驱动、中驱动、强驱动。如果走线短负载小用弱驱动就够如果走线长负载大可能需要中驱动。实际测试时你可以用示波器看数据线的上升沿和下降沿如果边沿有明显振铃就降低驱动强度如果边沿太缓就提高驱动强度。温度影响也不能忽略。芯片在不同温度下的驱动能力会有变化建议在高温和低温环境下都做一下读写操作验证不要只在室温下测。4. 双PSRAM初始化的完整流程4.1 上电与复位时序PSRAM上电后不能立刻进行复杂的配置操作。数据手册一般会要求一个tPU时间比如150us或者更久期间电源电压要达到稳定范围CLK要保持在有效电平。有些PSRAM还需要通过Reset引脚做一次硬件复位或者通过发布Reset命令做软件复位。在MCU端你需要保证XSPI控制器在上电后处于非使能状态避免意外发送读写命令给未初始化的PSRAM。我习惯在初始化代码最前面加一个很短延时比如ngx_delay_ms(1)确保电压稳定。这虽然看起来浪费了1毫秒但能避免很多诡异的启动问题。4.2 读取ID并验证连接接下来就是读ID。每个PSRAM都有唯一的Device ID和JEDEC ID通过读ID命令可以验证SPI通信是否正常。假如你用了两个片选就需要分别配置控制器切换到CS0和CS1然后分别读ID。如果两个ID读出来不一样就要检查是不是PSRAM型号不同或者某一条数据线有问题。在读ID阶段我经常遇到的问题是总线数据线接错。比如PSRAM的DQ0接到MCU的DQ1上表面上也能读到数据但读到的是自动换位后的数据表现就是ID完全不对。遇到这种情况建议做一遍线序回环测试或者仔细对照原理图检查。4.3 配置PSRAM关键寄存器常见的PSRAM配置项有读延迟设置读命令发出后等待多少个时钟周期开始采样数据。突发长度设置为16、32、64字节等匹配控制器的缓存行大小和读写策略。驱动强度根据PCB走线调整。地址模式设置为线性地址还是突发包装地址。温度补偿有些PSRAM支持自动温度刷新调整可以开启。发布配置命令时需要按数据手册要求的格式构造命令。有些命令需要写入一个寄存器地址再写入数据。在双片选情况下需要分别对CS0和CS1配置。你可能会想两颗PSRAM配置成一样的参数不就行了理论上可以但如果两颗芯片批次不同、特性略有差异最好分别校准。尤其当你在做量产时不要假设每颗颗粒的驱动强度都一样。4.4 初始化后的自检例程初始化完成后不要急着进入业务代码。我强烈建议跑一段简单的读写自检在PSRAM0全地址空间按固定模式写入递增数据。读回并比对。对PSRAM1做同样的操作。再做一些边界地址测试比如地址0x000000、地址0xFFFFF0附近以及跨越两个片选窗口的地址。这段自检代码看起来很简单但用处非常大。它能第一时间发现地址线短路、片选错误、时序余量不足等问题。我见过不少项目跳过自检直接跑应用结果在资源紧张时才暴露问题排查起来非常痛苦。5. 双PSRAM的读写策略与Cache一致性5.1 Write Buffer和Read-Ahead的影响XSPI控制器内部一般都有缓存Cache和写缓冲Write Buffer。对于PSRAM这类可写存储器你既想利用Cache加速读又要小心Cache导致的数据不一致。如果你开启了XSPI的Cache功能CPU读PSRAM时会先查CacheCache未命中才去访问物理PSRAM。但如果你用DMA往PSRAM里写数据CPU随后去读同一地址可能读到的是Cache里旧的脏数据。解决方法是做Cache Clean和Invalidate操作或者把PSRAM映射为非Cache区域后者性能会下降但一致性容易保证。我的习惯是如果PSRAM主要被DMA和硬件加速器使用就把它配置为非Cache区域如果纯靠CPU读写可以打开Cache但别忘了在关键时刻做一致性维护。5.2 双片选下的读写仲裁当两个片选都接到同一个XSPI实例时控制器内部同一时刻只能处理一个片选的访问。如果CPU在这边读PSRAM0那边DMA又要写PSRAM1它们会争抢XSPI总线。虽然控制器会自动仲裁但仲裁策略不同可能导致某一方延迟变大。如果你有音视频流这种硬实时需求需要重点关注访问延迟。比如在双缓冲方案中一个PSRAM存采集数据另一个PSRAM存显示数据如果采集侧和显示侧共享XSPI总线且显示扫描需要周期性读取那么采集写入就可能会被卡住。这时候可以考虑提高XSPI时钟频率缩短单次访问时长。减少突发长度让总线更快释放。调整优先级给实时性要求更高的设备更高优先级。如果控制器支持多通道队列可以配置不同通道的优先级。5.3 使用DMA进行大块数据搬运很多前辈提到把2个PSRAM集成在同一个XSPI实例中时觉得“一个总线两个芯片效率一定会减半”其实不然。XSPI支持突发访问如果你用DMA一次性搬运几百字节甚至几千字节总线的利用率会非常高。两个芯片之间的切换也只发生在跨片选的边界处影响可以做得非常小。我建议把大块数据搬运设计成DMA任务而不是逐字节轮询。比如图像传感器写入数据时可以在PSRAM0中累积到一定长度再通过DMA搬移到PSRAM1或者直接在PSRAM0和PSRAM1之间用DMA相互拷贝。这样CPU就可以去干别的事系统整体吞吐量明显更高。6. 常见问题与排查技巧实录6.1 只有一颗PSRAM能被初始化这个现象很典型我在很多项目里都遇到过。排查方法检查两个CS的GPIO是否都正确配置为XSPI功能最好确认一下MUX寄存器。测量CS信号上电后两个CS是否都有轮询动作。检查XSPI控制器的片选地址映射是否重叠如果两个窗口重叠后配置的会覆盖先配置的。检查PCB焊接尤其是第二颗PSRAM的CS引脚是否有虚焊。6.2 读ID正确但读写数据不稳定多半是时序余量不足或者采样延迟配置不理想。先在低速下测试比如10MHz SDR模式确认数据正确后再逐步提高频率。每提高一档都做一轮大范围读写测试。如果低速没问题、高速有问题基本可以断定是时序问题重点调整采样延迟、驱动强度和终端电阻。6.3 读写会偶尔卡死卡死往往是因为在XSPI控制器忙时发起了新的访问或者PSRAM进入异常状态。先检查是不是写了一段跨越两个片选且恰好在这时发生上下文切换的代码。如果是可以在读写前关闭中断或加锁。还要检查PSRAM有没有进入Deep Power Down模式如果有每次访问前要唤醒或者避免使用该模式。6.4 双PSRAM之间的数据串扰原理图上正确连接后理论上不会有串扰但实测中偶尔会有。常见原因芯片间距太近走线平行过长形成耦合。地平面不完整回流路径被切断。没有串联阻尼电阻数据线振铃过大。解决方法是调整PCB布局尽量让两颗PSRAM平行排布总线走线远离其他高频信号同时考虑在数据线上串联22欧姆到33欧姆的电阻减少振铃。6.5 初始化命令超时有些PSRAM需要等待内部初始化完成比如设置好MRMode Register之后要等待tRST或者tINIT时间。如果MCU不等待直接发下一条命令PSRAM可能不响应。解决办法是在每个配置命令之间加一个几微秒的延时或者读取状态寄存器确认忙位清零后再继续。7. 经验总结与后续扩展思路7.1 我踩过的坑双PSRAM项目里我印象最深的是一次开发板上的DDR模式调试。控制器设置为DDR模式后数据错误率非常高调了很久才怀疑是PCB上DQS信号质量不行。后来把PSRAM降到SDR模式问题马上消失。这让我意识到在PCB设计不理想的情况下不要盲目追求DDR模式的高带宽可以先稳定SDR模式再逐步优化硬件。还有一次是两片PSRAM型号完全一样但某批次的芯片内部默认寄存器不同。后来我改了初始化代码不再写死参数而是在每次初始化时先读回默认值再按需覆盖解决了批次兼容性问题。7.2 性能优化建议如果你已经在单实例双PSRAM方案上跑通了基础功能可以考虑继续优化尝试把XSPI时钟频率从60MHz提高到100MHz前提是走线长度和信号质量允许。如果控制器支持multi-Die封装操作可以检查是否能把两片PSRAM当成一个连续的大地址空间来使用省去软件切片的麻烦。开启XSPI的prefetch功能提高顺序访问速度。为读和写分别分配不同的DMA通道减少上下文切换。7.3 后续扩展方向一个XSPI实例接了2颗PSRAM之后你还可以在这条总线上再接一颗型号兼容的Flash或者用同一个PSRAM分区实现不同的缓冲策略。比如一部分作为摄像头采集缓冲区一部分作为显示帧缓冲一部分作为传感器数据环形队列。在这种情况下你要做的不是重新设计硬件而是在驱动层把地址窗口做细粒度划分并根据应用场景动态调整缓存策略。如果你准备把这个经验迁移到其他MCU平台我建议你先去读目标芯片的Reference Manual中关于XSPI Controller的章节重点看三个部分External Memory Mapping区域、CS配置寄存器和Timing Register。这几部分清楚了移植基本就成功了一半。7.4 最后的实操技巧分享如果你刚接触这个方向我建议不要急着一次性上双PSRAM。可以先做一块转接板只接一颗PSRAM跑通基础的读写再扩展成两颗。这样做的好处是你在单芯片模式下可以把初始化流程、时序配置和Cache策略调校成熟减少多芯片因素带来的干扰。等单芯片稳定后再把两片都接上这时候你只需要重点关注片选切换和地址映射整个调试难度会大幅降低。另外我非常推荐在调试阶段用逻辑分析仪抓取XSPI总线上的命令序列。虽然XSPI频率高但低速调试时逻辑分析仪完全可以捕获初始化流程能帮你快速确认命令和响应是否匹配。没有逻辑分析仪的情况下也可以通过读ID命令配合串口打印来确认基本通信状态。这个方向其实并不神秘核心就是把控制器配置、时序参数和地址映射这三件事理清楚再加上耐心调试点信号质量。希望这篇内容对正在折腾双PSRAM的你有所帮助。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →