先楫SDK组件系列-串行Nor Flash通用驱动库serial_nor

一、前言


对于有实际nor flash器件作为存储的需求,先楫除了提供更为方便、性能更优的外设-XPI外设,也可以使用SPI外设进行驱动,先楫的SPI外设不单支持单线SPI,还支持双线DSPI,四线QSPI,保证多种传输模式的应用场合。

在先楫sdk的组件中,有serial_nor这个组件,也就是支持操作SFDP标准的flash通用驱动库,包括擦除、读写操作。 支持单线SPI,双线DSPI,四线QSPI,并且支持多个flash实例。

双线DSPI跟单线SPI的硬件IO一致,双线DSPI只是把单线SPI的MISO和MOSI当作DO0和DO1使用,这样一来,同样的硬件接口,双线DSPI的传输性能是单线SPI的两倍,在保留硬件的条件下,建议使用双线DSPI。

对于SFDP标准,需要了解的可以查看以往文章-《谈谈先楫hpm_sdk的组件serial_nor--SFDP定义

对于先楫SPI驱动Nor flash为例的性能文章,可以参考本文-《[玩转先楫SPI外设系列三] 以读写串行NOR flash为例总结SPI主机性能

本文主要阐述该组件的使用,对于内部API的实现,本文不做太多阐述内容。

对于该组件的使用例子,官方提供了例程,仓库以下:
https://github.com/hpmicro/hpm_sdk_extra/tree/main/spi_nor_flash
二、使用
(一)API介绍

在hpm_sdk中,serial_nor的源码目录如下,分为硬件层spi_host和驱动层serial_nor。

image.png



1、对于硬件层,对接的先楫SPI外设,包括了SPI的所有模式(单线双线四线),支持使用了DMA保证传输性能,具体可看前言提到的SPI性能系列文章。


2、对于驱动层seri_nor,组件中提供了两种方式操作,一种非阻塞noblock方式,一种阻塞block方式。还有读取信息的API。

1)判断flash是否忙状态(hpm_serial_nor_is_busy),通常用于擦除和写操作后通过判断是否忙来判断是否操作完毕

image.png



2)使能写操作(hpm_serial_nor_write_enable),对于擦除和写操作之前使能写的API,在组件中,写和擦除操作都已经调用,用户可不需要理会该API。

image.png



3)擦除整片flash的API (hpm_serial_nor_erase_chip),该API是阻塞方式,内部判断busy。擦除时间由flash器件而定。

image.png



4)擦除块api,分为阻塞block和非阻塞noblock

image.png



5)擦除扇区api,分为阻塞block和非阻塞noblock

image.png



6)擦除指定开始地址的指定长度区域API(hpm_serial_nor_erase_blocking),该API是阻塞方式。若需要不阻塞方式可以配合sector和block的非阻塞api使用。

image.png



7) 往指定地址写入指定长度的数据API,也分为阻塞和非阻塞方式。

image.png



8)从指定地址读取指定长度的数据API

image.png



9)初始化serial_nor,该API主要是用于不同flash实例的注册

image.png



10)读取flash实例的信息API

image.png


而读取的信息结构体格式如下:主要是获取sfdp版本,扇区和块擦除指令、存储器/块/页/扇区大小。

image.png

(二) API使用

在先楫提供的例子中,使用步骤如下:


1、初始化flash实例对象


需要定义一个flash实例变量,当然实例变量可以定义多个,也就是可以支持多个flash器件。

image.png


2、初始化flash实例内的spi外设成员,需要注册spi host的flags,对于flags支持如下,包含支持SPI模式(单线、双线、四线)、DMA支持、CS硬件控制等。

image.png


例子提供双线SPI,使用DMA的flags。


另外需要注册SPI的片选信号和频率的设置API、SPI的基地址、DMA的相关参数,对此例子中提供了先楫sdk中的支持的Board的注册API。在hpm_serial_nor_host_port.c中。

image.png


根据以上API就可以注册到flash的实例成员中。

image.png


3、flash实例注册serial_nor。使用以上的api介绍的hpm_serial_nor_init,建议判断返回是否成功再后续操作。

image.png


4、获取flash器件相关信息。

image.png


5、操作flash,例子包括了阻塞操作和非阻塞操作的api性能测试。读写长度为15KB数据量

image.png

image.png

三、验证


本文使用的器件还是华邦W25Q64JV,


在数据手册中,从页编程来看,一次页编程经典是0.3ms,擦除4K sector需要45ms经典值,假设从单纯编程上看,写速度大概是625KB/S经典值.

image.png


  从读来看,主要看flash支持的SPI频率。从手册看,读取03H普通读取指令以外的指令(比如EBh 四线读取)可以到133M,那么理论上四线SPI可以到66.5MB/S最大值,单线SPI主要只能对接03H指令,那么最大50M频率,最大可以6.28MB/S。

image.png


这里使用QSPI四线模式,50M SCLK频率。结果如下:


写性能一般都能满足,从上述自身flash器件的编程性能630KB/S.在这里667KB/S 是明显达到编程性能的.


读性能,四线QSPI在50M下,理论性能是50/2=25MB/s,实际是22MB/s。从API内部需要做SPI配置、DMA配置、flash指令操作等内部时间损耗,22MB/s的性能已经很正常了。在前言所说的文章中有逻辑分析仪的波形分析,也可以查阅。

image.png


根据readme的性能测试,50Mhz双线SPI的读性能是11.9MB/s.

image.png


50Mhz单线SPI的读性能是6MB/s,理论是6.25MB/s。

image.png

四、总结


1、先楫的SPI外设不单支持单线SPI,还支持双线DSPI,四线QSPI,保证多种传输模式的应用场合。


2、双线DSPI跟单线SPI的硬件IO一致,双线DSPI只是把单线SPI的MISO和MOSI当作DO0和DO1使用,这样一来,同样的硬件接口,双线DSPI的传输性能是单线SPI的两倍,在保留硬件的条件下,如果不追求同时读写(半双工)模式,建议使用双线DSPI。


3、先楫serial_nor组件支持操作SFDP标准的flash器件,包括擦除、读写操作;硬件支持单线SPI/双线DSPI/四线QSPI,以及DMA,并且支持多个flash实例。