MUC外置PSRAM-软件实现页面切换

简单介绍

对于定位在中低端的MCU(通常是某个系列48脚,64脚的型号),不会配备额外的RAM接口给用户外接SRAM,SDRAM或DRAM;这就造成了程序能使用的RAM只能是单片机内部的SRAM,通常只有几十或者100多KB,有时候就不够用了。本文介绍的方案中,使用8脚SPI接口的PSRAM芯片给单片机扩充可用内存,当然了这样的外置RAM由于没法接入ARM内核的数据/地址总线,因此也不能做任何寻址操作(无法直接用指针的方式访问),但通过软件实现的虚拟地址到物理地址映射和换页单元,在页面内可以做到随机访问使用上与单片机内置RAM无异。

硬件部分

PSRAM型号:LY68L6400SLIT
支持SPI和QSPI接口,物理页大小为1KB,容量8MB,页内访问最大时钟速率144MHz,跨页访问最大时钟速率84MHz

某宝最低价格6RMB还包邮,相对还是很划算了。

MCU只需要带SPI接口,如果想要读写性能更好,推荐使用带QSPI接口的型号,同时看下是否有给SPI的DMA通道。
这里使用的MCU为GD32F303RC,SPI0外设支持QSPI模式,最大时钟30MHz,QSPI模式下等效时钟120MHz,且TX和RX都有DMA通道可用。


PCB布线上,由于速率低,因此和传统的DRAM相比,要求低了很多。


image

软件实现

image

直接内存性能测试

这一步不使用软件换页器作为中间层,直接测试的PSRAM裸芯片的访问速度,比较能反应出外置PSRAM读写能力的上限,访问速度主要和QSPI最大时钟频率,QSPI外设位宽,QSPI-DMA位宽以及PSRAM芯片支持的最大时钟频率有关。

参考基准

MCU内部SRAM连续写:
计时时钟使用CM4内核自带的DWT(DataWatchpoint andTrace)单元,它有一个32位的向上计数器CYCCNT,时钟频率就是CPU主频,当前CPU主频为120Mhz,因此CYCCNT每自增1,时间就过去了t =(1 / f)= 1 / 120000000 = 8.33x10^-9s = 8.3ns,使用CYCCNT计时的精度非常高。

// 初始化DWT的计时器单元
static void hw_dwt_init(void) {
    // DWT timer enable
    CoreDebug->DEMCR = 0x1000000;
    // clear Cycle Count Register
    DWT->CYCCNT = 0x0;
    // enable  Data Watchpoint and Trace Register
    DWT->CTRL = 0x1;
}

SRAM起始地址4字节对齐,使用rtthread实现的rt_memset函数写内部SRAM:

uint8_t *page0_buffer = (uint8_t *)0x20004000u;

uint32_t start = DWT->CYCCNT;
rt_memset(page0_buffer, 0x0, 16384);
uint32_t end = DWT->CYCCNT;

rt_kprintf("start:%d\n", start);
rt_kprintf("end:%d\n", end);
大小(KB) CCYCNT 耗时(us) 等效速度(MB/s)
1K 691 5.75603 169.65903
4K 2611 21.74963 179.60075
8K 5171 43.07443 181.37210
16K 10291 85.72403 182.27094

SRAM起始地址4字节对齐,使用newlib c标准库memset函数写内部SRAM:
使用了--specs=nano.specs属性
image

uint8_t *page0_buffer = (uint8_t *)0x20004000u;

uint32_t start = DWT->CYCCNT;
memset(page0_buffer, 0x0, 16384);
uint32_t end = DWT->CYCCNT;

rt_kprintf("start:%d\n", start);
rt_kprintf("end:%d\n", end);
大小(KB) CCYCNT 耗时(us) 等效速度(MB/s)
1K 7181 59.81773 16.32563623
4K 28898 240.72034 16.22733667
8K 57569 479.54977 16.29132259
16K 114920 957.2836 16.32222677

不使用--specs=nano.specs属性,代码段.text增大约12.765KB。

大小(KB) CCYCNT 耗时(us) 等效速度(MB/s)
1K 883 7.35539 132.7682829
4K 3379 28.14707 138.7799867
8K 6707 55.86931 139.8352691
16K 13363 111.31379 140.3689516

PSRAM写入1

PSRAM连续写入测试:

  • PSRAM页内地址对齐,突发长度1KB
  • 8bit QSPI@30MHz,DMA 8bit
  • 使用rt_device设备框架
  • 使用rt_spi驱动框架
  • 底层驱动调用库函数
  • 异步模式,DMA完成中断(DMA_INT_FLAG_FTF)使用rt_completion(二值信号量)唤醒线程
大小(KB) CCYCNT 耗时(us) 等效速度(MB/s)
1K 24801 206.59233 4.727002692
4K 99209 826.41097 4.726764457
8K 198625 1654.54625 4.721838389
16K 397029 3307.25157 4.724466727

PSRAM写入2

  • PSRAM页内地址对齐,突发长度1KB
  • 8bit QSPI@30MHz,DMA 8bit
  • 使用rt_device设备框架
  • 不使用rt_spi驱动框架
  • 底层驱动仍调用库函数
  • 同步模式,线程中开启DMA后,while循环轮询中断标志位
大小(KB) CCYCNT 耗时(us) 等效速度(MB/s)
1K 22831 190.18223 5.134877743
4K 91337 760.83721 5.134146896
8K 182673 1521.66609 5.134175002
16K 365349 3043.35717 5.134132843

PSRAM写入3

  • PSRAM页内地址对齐,突发长度1KB
  • 8bit QSPI@30MHz,DMA 8bit
  • 使用rt_device设备框架
  • 不使用rt_spi驱动框架
  • 底层驱动直接操作寄存器
  • 使用变量记录下当前QSPI-IO状态,在重复读写操作时,避免多次配置IO工作模式(QSPI为半双工,读/写操作前需要配置IO为/输入/输出模式)
  • 同步模式,线程中开启DMA后,while循环轮询中断标志位
大小(KB) CCYCNT 耗时(us) 等效速度(MB/s)
1K 20969 174.67177 5.590843329
4K 83799 698.04567 5.595980561
8K 167575 1395.89975 5.59674862
16K 335111 2791.47463 5.597399966

PSRAM写入4

  • PSRAM页内地址对齐,突发长度1KB
  • QSPI@30MHz,DMA模式,QSPI和DMA位宽根据写入长度自动切换,2字节对齐的使用16bit,其他使用8bit
  • 使用rt_device设备框架
  • 不使用rt_spi驱动框架
  • 底层驱动直接操作寄存器
  • 使用变量记录下当前QSPI-IO状态,在重复读写操作时,避免多次配置IO工作模式(QSPI为半双工,读/写操作前需要配置IO为/输入/输出模式)
  • 同步模式,线程中开启DMA后,while循环轮询中断标志位

GD32F303 QSPI模式无法工作在16bit模式下(标准2线SPI可以工作在16位模式),即使QSPI和DMA配置成16bit位宽,当启用QSPI时,也只能输出低8bit的数据,造成输出/读取的数据丢失高8位。如果不在意数据正确性,经过测试写入速度能达到10.17MB/s,就有点可惜。

换页访问性能测试

存在空闲SRAM缓存页

存在空闲缓存页的情况下,调用page_va2pa函数,只会导致一次从PSRAM载入数据到SRAM的IO操作。
image

大小(KB) CCYCNT 耗时(us) 等效速度(MB/s)
1K 21333 177.0639 5.5153

SRAM缓存页满

当不存在空闲缓存页的情况下,调用page_va2pa函数,会先查找最近最少使用的缓存页,将其写出PSRAM,再从PSRAM指定的地址读入新的页面数据,会产生2次IO操作,因此速度也会减半。
image

大小(KB) CCYCNT 耗时(us) 等效速度(MB/s)
1K 42611 353.6713 2.76121
240K 10230656 84,914.4448 2.76014

应用示例

单片机串口接收缓存

// TODO

总结

外存和内存在本质上并没有太大区别,如果外存连到了系统总线上,只会有速度的区别,如果外存没有连到总线上,那么读写方式和速度都会有区别。
优点:在某些场合,比如一定时间内进行数据采样并保存,使用SRAM空间不够,使用Flash速度太慢,这种外挂的PSRAM可以解决数据临时存储问题。
缺点:和带PSRAM控制器的单片机相比,这种方法无法使用直接地址访问,使用上比较麻烦。

Git链接

https://github.com/Yanye0xFF/MCU_PSRAM

posted @ 2022-09-11 21:59  Yanye  阅读(1274)  评论(2编辑  收藏  举报