1. 智能穿戴设备的内存瓶颈与APS6404L的破局思路
做智能穿戴这行的朋友应该都有体会,产品定义阶段最头疼的往往不是主控选型,而是内存够不够用。手环、手表这类设备,屏幕分辨率越来越高,UI动效越来越复杂,还要跑心率算法、血氧检测、消息通知、蓝牙协议栈,MCU内部那点SRAM根本扛不住。STM32F4系列算是穿戴设备里用得比较多的,192KB SRAM听起来不少,但真正跑起LVGL这种图形库,再叠加几个传感器融合算法,内存直接见底。
这时候就得外挂存储。常见方案无非几种:SPI NOR Flash便宜但读写速度慢,适合存固件和静态资源;SDRAM容量大但引脚多、功耗高,小设备根本塞不下;PSRAM算是折中方案,容量从几MB到几十MB都有,接口简单,功耗可控,特别适合穿戴设备这种对体积和续航都有要求的场景。
APS6404L-SQHX-SN就是在这个背景下进入视野的。这颗芯片是APM(晶豪)出的SPI PSRAM,容量4MB,支持标准SPI、Dual SPI和Quad SPI三种模式,工作电压1.8V,SOP-8封装。4MB什么概念?足够放两帧全屏RGB565的帧缓冲,还能剩不少给算法用。关键是它走SPI接口,引脚占用少,PCB布线压力小,对于穿戴设备这种寸土寸金的设计来说,简直是救命稻草。
我最早接触这颗芯片是在一个智能手表项目上。当时主控用的是STM32U575,内部SRAM只有786KB,跑RT-Thread加上LVGL,再开几个线程处理传感器数据,内存直接爆了。外挂APS6404L之后,把LVGL的显存和图片解码缓冲区全挪到PSRAM里,内部SRAM只留栈和关键数据结构,整个系统瞬间流畅了。这个项目后来量产了,出货量还不错,APS6404L的稳定性也得到了验证。
所以这篇文章,我就围绕APS6404L-SQHX-SN这颗芯片,从选型逻辑、硬件设计、SPI/QPI驱动开发、性能调优到常见问题排查,把整个链路拆开讲一遍。不管你是刚接触PSRAM的新手,还是已经在用但遇到瓶颈的老手,应该都能找到有用的东西。
2. 核心细节解析与实操要点
2.1 APS6404L-SQHX-SN关键参数与选型对比
先看这颗芯片的核心规格。APS6404L-SQHX-SN的容量是4MB(32Mbit),组织方式是512K x 8bit。工作电压范围1.7V到1.95V,典型值1.8V,这意味着它可以直接和1.8V的MCU IO口对接,不需要电平转换。接口支持Standard SPI、Dual SPI和Quad SPI,最高时钟频率在Quad模式下可以跑到84MHz(具体要看时序参数)。
封装是SOP-8,引脚定义很标准:CS、SCK、SI/SIO0、SO/SIO1、WP/SIO2、HOLD/SIO3、VCC、GND。这里要注意,WP和HOLD引脚在Quad模式下会复用为SIO2和SIO3,所以硬件设计时如果打算用QPI模式,这两个脚不能接固定电平,必须接到MCU的IO上。
和同类产品对比一下。ISSI的IS66WV51216是并口SRAM,速度快但引脚太多;Winbond的W25Q系列是NOR Flash,便宜但写入速度慢,不适合做显存;Espressif的ESP-PSRAM系列主要配自家芯片。APS6404L的优势在于:SPI接口引脚少、容量适中、功耗低、价格有竞争力。特别是对于穿戴设备这种批量大的产品,每颗芯片省几毛钱,一年下来就是几十万的利润。
选型时还要注意温度等级。APS6404L-SQHX-SN的工业级温度范围是-40°C到+85°C,消费级产品够用了。如果做车规或者户外设备,得选更高规格的型号。另外,这颗芯片的待机电流典型值是100μA左右,对于穿戴设备来说可以接受,但如果你的产品对功耗极其敏感,可以考虑在不用的时候把CS拉高进入掉电模式。
2.2 硬件设计要点与PCB布局建议
硬件设计这块,我踩过不少坑,这里挑几个关键的说。
首先是电源去耦。APS6404L的VCC引脚旁边必须放一个0.1μF的陶瓷电容,越近越好,最好在2mm以内。我见过一个设计,电容放在芯片背面,结果SPI通信时不时出错,后来把电容挪到正面紧贴引脚,问题就消失了。如果板子上有多颗PSRAM或者PSRAM和Flash共用电源,建议再加一个1μF的电容做整体滤波。
其次是SPI信号线的走线。SCK是时钟线,频率高的时候容易辐射干扰,尽量走短线,避免跨分割平面。SI、SO、WP、HOLD这四根数据线如果跑Quad模式,最好等长走线,误差控制在5mil以内。CS线虽然频率不高,但它是控制信号,走线也要尽量短,避免被其他信号耦合干扰。
再就是上拉电阻。SPI接口的CS、SI、SO这些线,建议加上拉电阻,典型值10KΩ。有些MCU的SPI引脚在复位后是浮空状态,如果没有上拉,PSRAM可能会误触发。特别是CS线,如果浮空导致PSRAM被选中,而SCK又有杂波,可能会写入错误数据。这个坑我在早期项目中遇到过,后来加了上拉就再没出过问题。
还有一个细节:APS6404L的WP和HOLD引脚在标准SPI模式下可以悬空或者上拉,但在Quad模式下必须由MCU驱动。如果你不确定将来会不会用Quad模式,建议直接把这两个脚接到MCU的IO上,留好退路。PCB布局时,PSRAM尽量靠近MCU,走线长度控制在5cm以内,超过这个长度就要考虑信号完整性问题了。
2.3 SPI与QPI模式的选择逻辑
APS6404L支持三种接口模式:Standard SPI、Dual SPI和Quad SPI。选哪种模式,取决于你的MCU资源和性能需求。
Standard SPI用4根线(CS、SCK、SI、SO),最高时钟频率一般在50MHz左右。这个模式下,每个时钟周期传输1bit数据,理论带宽是50Mbps。对于低分辨率屏幕或者不频繁访问显存的场景,这个速度够用了。
Dual SPI用4根线(CS、SCK、SIO0、SIO1),每个时钟周期传输2bit数据,带宽翻倍。但很多MCU的SPI外设不支持Dual模式,需要GPIO模拟或者用QSPI外设。
Quad SPI用6根线(CS、SCK、SIO0-SIO3),每个时钟周期传输4bit数据,带宽是Standard模式的4倍。如果MCU有QSPI外设(比如STM32的QUADSPI),强烈建议用这个模式。84MHz时钟下,理论带宽能达到336Mbps,实际有效带宽大概在200Mbps左右,足够应付大多数穿戴设备的显存需求。
我个人的建议是:如果MCU有QSPI外设,直接上Quad模式,别犹豫。如果没有,但GPIO速度够快,可以用GPIO模拟QPI,但要注意时序裕量。如果MCU连Dual模式都不支持,那就老老实实用Standard SPI,把时钟拉到最高,也能凑合用。
这里要提一个坑:有些MCU的QSPI外设和普通SPI外设是分开的,比如STM32F4系列,QSPI是独立的外设,引脚也是专用的。选型时一定要确认MCU的QSPI引脚能不能和PSRAM的引脚对上,不然就得用GPIO模拟,性能会打折扣。
3. 实操过程与核心环节实现
3.1 硬件连接与初始化配置
先讲硬件连接。以STM32U575和APS6404L为例,我用的是QUADSPI外设,引脚分配如下:
| APS6404L引脚 | STM32U575引脚 | 功能 |
|---|---|---|
| CS | PB10 | 片选 |
| SCK | PB2 | 时钟 |
| SIO0 | PB1 | 数据0 |
| SIO1 | PB0 | 数据1 |
| SIO2 | PA7 | 数据2 |
| SIO3 | PA6 | 数据3 |
| VCC | 1.8V | 电源 |
| GND | GND | 地 |
初始化配置分几步。首先是GPIO初始化,把QUADSPI用到的引脚配成复用功能,速度等级设为Very High。然后是QUADSPI外设初始化,关键参数包括:
- ClockPrescaler:分频系数,决定SCK频率。STM32U575的QUADSPI时钟源是系统时钟,假设是160MHz,分频系数设为2,SCK就是80MHz。
- FifoThreshold:FIFO阈值,一般设为4或者8。
- FlashSize:PSRAM的容量,设为22(2的22次方等于4MB)。
- CSHighTime:片选高电平时间,设为3个时钟周期。
- ChipSelectHighTime:片选保持时间,根据PSRAM的时序要求设置。
配置完外设,还要初始化PSRAM本身。APS6404L上电后默认是Standard SPI模式,要进入Quad模式,需要发送特定命令。具体流程是:
- 拉低CS,发送0x35命令(Enter Quad Mode),然后拉高CS。
- 之后的读写操作都用Quad模式,命令、地址、数据都走4根数据线。
这里要注意,0x35命令只需要发送一次,PSRAM会记住当前模式。但如果PSRAM断电重启,模式会复位,需要重新发送。
3.2 QPI模式下的读写时序与代码实现
QPI模式的读写时序和Standard SPI不太一样。Standard SPI是单线传输,命令、地址、数据都走SI和SO两根线。QPI模式下,命令、地址、数据都走4根线,每个时钟周期传输4bit。
以读操作为例,时序是这样的:
- 拉低CS。
- 发送命令0xEB(Quad I/O Fast Read),走4根线,2个时钟周期发完8bit命令。
- 发送24bit地址,走4根线,6个时钟周期发完。
- 发送Mode Bits(可选),一般是0x00或者0xA0,取决于是否用Continuous Read模式。
- 发送Dummy Cycles,一般是6个时钟周期,让PSRAM准备数据。
- 读取数据,每个时钟周期读4bit。
写操作的时序类似,命令是0x38(Quad I/O Write),地址之后直接跟数据,没有Dummy Cycles。
代码实现上,如果用STM32的HAL库,可以直接调用HAL_QSPI_Command和HAL_QSPI_Receive。但HAL库的QSPI驱动有点绕,特别是Dummy Cycles的配置,容易搞错。我一般直接操作寄存器,或者用LL库,更直观。
下面是一个读数据的示例:
void APS6404L_Read(uint32_t addr, uint8_t *buf, uint32_t len) { QSPI_CommandTypeDef cmd; cmd.Instruction = 0xEB; cmd.InstructionMode = QSPI_INSTRUCTION_4_LINES; cmd.Address = addr; cmd.AddressMode = QSPI_ADDRESS_4_LINES; cmd.AddressSize = QSPI_ADDRESS_24_BITS; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; cmd.AlternateBytes = 0x00; cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; cmd.DummyCycles = 6; cmd.DataMode = QSPI_DATA_4_LINES; cmd.NbData = len; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; HAL_QSPI_Command(&hqspi, &cmd, HAL_QPSI_TIMEOUT_DEFAULT_VALUE); HAL_QSPI_Receive(&hqspi, buf, HAL_QPSI_TIMEOUT_DEFAULT_VALUE); }写数据的代码类似,把Instruction改成0x38,DummyCycles改成0,然后调用HAL_QSPI_Transmit。
这里有个细节:AlternateBytes的配置。有些PSRAM需要发送Mode Bits才能进入Continuous Read模式,这样下次读的时候可以省掉命令和地址,直接读数据。但APS6404L对Mode Bits的要求不严格,发0x00也能正常工作。如果你追求极致性能,可以研究一下Continuous Read模式,能省几个时钟周期。
3.3 显存管理与LVGL适配
把PSRAM用起来之后,下一步就是怎么管理这块内存。对于穿戴设备来说,PSRAM主要用来放显存、图片解码缓冲区和算法中间数据。
以LVGL为例,默认的显存是静态数组,放在内部SRAM里。要改成PSRAM,需要重写LVGL的显存分配函数。LVGL 8.x版本支持自定义显存缓冲区,可以在lv_conf.h里配置:
#define LV_MEM_CUSTOM 1 #define LV_MEM_CUSTOM_INCLUDE "psram_alloc.h" #define LV_MEM_CUSTOM_ALLOC psram_malloc #define LV_MEM_CUSTOM_FREE psram_free然后实现psram_malloc和psram_free,底层调用PSRAM的读写接口。但这样有个问题:LVGL的显存访问非常频繁,如果每次刷新都走SPI读写PSRAM,速度可能跟不上。所以更好的做法是:显存还是放在内部SRAM,但把图片解码缓冲区、字体缓存这些不频繁访问的数据放到PSRAM。
具体策略是:内部SRAM留出两块显存(双缓冲),每块大小是屏幕分辨率乘以像素深度。比如240x240的屏幕,RGB565格式,每块显存是240x240x2=115200字节,两块就是230KB。STM32U575有786KB SRAM,放两块显存绰绰有余。剩下的图片解码、字体渲染、算法数据,全扔到PSRAM里。
这样做的原因是:显存的访问频率最高,放在内部SRAM能保证刷新率;PSRAM虽然速度也不慢,但SPI接口有协议开销,频繁访问会影响性能。实测下来,240x240屏幕,双缓冲显存放在SRAM,图片和字体放在PSRAM,LVGL的刷新率能稳定在60fps,完全够用。
3.4 性能实测与参数调优
性能这块,我做了几组对比测试。测试平台是STM32U575 + APS6404L,QUADSPI时钟80MHz,Quad模式。
第一组测试:连续读4MB数据,测平均带宽。结果是读带宽约180Mbps,写带宽约120Mbps。读比写快是因为读操作有Dummy Cycles,但数据阶段是连续的;写操作每个字节都要等PSRAM的写周期,所以慢一些。
第二组测试:随机读,每次读32字节,模拟LVGL访问图片数据。结果是平均带宽约80Mbps,比连续读低不少,因为每次读都有命令和地址开销。
第三组测试:LVGL实际运行,240x240屏幕,60fps刷新,同时跑心率算法。结果是CPU占用率约45%,PSRAM带宽占用约30%,系统运行流畅。
调优方面,有几个参数可以调:
- QUADSPI时钟:80MHz是保守值,可以试着拉到100MHz甚至120MHz,但要看PSRAM的时序裕量。我试过100MHz,跑了一天没出错,但为了保险,量产还是用80MHz。
- Dummy Cycles:6个周期是默认值,如果时钟频率低,可以减到4个;如果频率高,要加到8个。
- FIFO阈值:设大一点能减少中断次数,但会增加延迟。我一般设8。
还有一个技巧:如果PSRAM和Flash共用QUADSPI总线,切换片选的时候要加延时,等总线稳定后再发命令。这个延时一般是几个时钟周期,具体看PCB走线和信号质量。
4. 常见问题与排查技巧实录
4.1 SPI通信失败排查流程
SPI通信失败是最常见的问题,表现是读不到数据、读到的数据全是0xFF或者0x00、数据错位等。排查流程可以按以下步骤走:
第一步,检查硬件连接。用万用表测CS、SCK、SI、SO、WP、HOLD、VCC、GND这8个脚,确认没有虚焊、短路。特别是VCC和GND,如果电压不对,PSRAM根本不工作。
第二步,用示波器看波形。先看SCK有没有时钟输出,再看CS有没有拉低,然后看SI和SO有没有数据。如果SCK没有波形,说明MCU的SPI外设没配置好;如果CS一直高,说明片选逻辑有问题;如果SI有数据但SO没反应,可能是PSRAM没进入Quad模式,或者Dummy Cycles配置不对。
第三步,降速测试。把SPI时钟降到1MHz,看看能不能通信。如果低速能通,高速不通,说明是信号完整性问题,检查走线长度、上拉电阻、去耦电容。
第四步,换一颗PSRAM。如果以上都没问题,可能是芯片坏了。我遇到过一批PSRAM,焊接温度过高导致内部损坏,换一颗就好了。
这里有个经验:如果读到的数据全是0xFF,一般是MISO线没接好或者PSRAM没被选中;如果全是0x00,可能是PSRAM没供电或者进入了掉电模式。
4.2 QPI模式切换失败的典型原因
QPI模式切换失败的表现是:发送0x35命令后,PSRAM还是工作在Standard SPI模式,读写数据错乱。
原因一般有几个:
一是命令发送时序不对。0x35命令需要在CS拉低后发送,然后拉高CS。如果CS拉高的时间太短,PSRAM可能没来得及切换模式。建议CS拉高后延时1ms再发下一条命令。
二是WP和HOLD引脚状态不对。在Standard SPI模式下,WP和HOLD可以悬空;但在切换QPI模式时,这两个脚必须处于高电平,否则PSRAM会忽略0x35命令。所以硬件设计时,WP和HOLD最好加上拉电阻,或者直接接到MCU的IO上,切换模式前先拉高。
三是电源电压不稳。APS6404L的工作电压是1.7V到1.95V,如果电压低于1.7V,PSRAM可能无法正常切换模式。用示波器测一下VCC引脚,看看有没有跌落。
四是MCU的QSPI外设配置错误。有些MCU的QSPI外设在发送命令时,会自动加上Dummy Cycles或者Mode Bits,导致0x35命令被污染。检查一下QSPI的配置,确保发送0x35时没有额外的字节。
4.3 数据读写错误的调试方法
数据读写错误的表现是:读到的数据和写入的不一致,或者数据错位。调试方法如下:
首先,写一个简单的测试模式。比如往地址0x000000写0x55,然后读回来,看是不是0x55。再写0xAA,读回来,看是不是0xAA。如果0x55和0xAA都能正确读写,说明基本通信没问题。
然后,测试地址线。往地址0x000000写0x55,往地址0x000001写0xAA,然后分别读这两个地址,看数据对不对。如果地址0x000001读出来是0x55,说明地址线有短路或者错位。
接着,测试数据线。往地址0x000000写0x55,读回来,看是不是0x55。然后写0xAA,读回来,看是不是0xAA。如果写0x55读出来是0xAA,说明数据线有交叉。
最后,测试边界条件。往最后一个地址写数据,读回来,看对不对。如果最后一个地址读写错误,可能是容量配置不对,比如把4MB配成了2MB。
这里有个技巧:用伪随机数测试。生成一串伪随机数,写入PSRAM,再读出来对比。如果有一个字节不对,就能定位到具体地址。这个方法比固定模式测试更严格,能发现偶发性错误。
4.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 读不到数据,全是0xFF | MISO线未连接、PSRAM未选中 | 检查SO引脚焊接、测CS波形 | 重新焊接、检查片选逻辑 |
| 读到的数据全是0x00 | PSRAM未供电、进入掉电模式 | 测VCC电压、检查CS时序 | 检查电源、拉高CS |
| 数据错位 | 地址线或数据线交叉 | 写固定模式测试 | 检查PCB走线、重新布线 |
| QPI模式切换失败 | WP/HOLD状态不对、时序错误 | 测WP/HOLD电平、看0x35命令波形 | 拉高WP/HOLD、增加延时 |
| 高速通信出错 | 信号完整性问题 | 降速测试、看眼图 | 缩短走线、加去耦电容 |
| 偶发性读写错误 | 电源纹波、干扰 | 测电源纹波、看SCK波形 | 加滤波电容、屏蔽干扰源 |
| 功耗偏高 | 未进入掉电模式 | 测待机电流 | 不用时拉高CS、发送掉电命令 |
4.5 实操心得与避坑建议
最后分享几个我在实际项目中总结的心得。
第一,PSRAM的CS线一定要加上拉电阻。我遇到过一批板子,CS线浮空导致PSRAM被误选中,MCU还没启动,PSRAM就被写入了乱七八糟的数据。后来加了10KΩ上拉,问题解决。
第二,QUADSPI的时钟不要一上来就拉满。先用低速调通,再逐步提高频率。我一般从10MHz开始,每调一次测一次,确认稳定后再往上加。量产时留20%的裕量,比如PSRAM标称84MHz,实际用60MHz。
第三,PSRAM的初始化命令要发两次。有些批次的PSRAM,第一次发0x35可能不生效,发两次就稳了。这个坑我在一个项目上遇到过,后来养成习惯,初始化命令都发两次。
第四,如果PSRAM和Flash共用QUADSPI总线,切换片选后要加延时。这个延时一般是100ns到1μs,具体看PCB走线。我一般加1μs,虽然会损失一点性能,但稳定性大大提升。
第五,LVGL的显存不要全放PSRAM。显存放内部SRAM,图片和字体放PSRAM,这样刷新率有保证。如果显存也放PSRAM,刷新率会掉到30fps以下,用户体验很差。
第六,测试的时候要用真实数据。有些朋友用全0或者全1测试,觉得没问题就量产了,结果实际跑起来发现图片显示错乱。因为全0和全1的测试模式太简单,发现不了地址线交叉、数据线干扰这些问题。用真实图片和字体测试,才能暴露问题。
第七,PSRAM的功耗和温度有关。高温下功耗会增加,如果产品要在户外使用,要留足电源裕量。我测过APS6404L在85°C下的功耗,比25°C时高了约30%。
这些经验都是真金白银换来的,希望能帮到正在用或者打算用APS6404L的朋友。这颗芯片本身很稳,只要硬件设计到位,驱动配置正确,基本不会出问题。智能穿戴设备的内存瓶颈,用它来解决,性价比很高。