当前位置:首页 期刊杂志

嵌入式平台NVMe驱动设计与应用

时间:2024-05-04

冯军波

(中航工业西安航空计算技术研究所,陕西西安,710068)

0 引言

NVMe(Non-Volatile Memory express,非易失存储器协议)是一种面向PCIe固态硬盘(SDD)的接口协议。最早于在2011年3月推出,由NVMe规范组织成员公司(如Intel、戴尔、三星、镁光等)合作开发,用于主控软件通过PCIe 链路与SSD进行高速数据传输。在最新的1.3版本中又增加了设备自检、引导分区、虚拟化、主机操控散热管理等新特点,改进了SSD的性能。在NVMe推出之前,传统的SATA硬盘大都使用AHCI协议,读写速度在500M/s以下。AHCI协议具有较强的兼容性,可支持SATA总线与PCIe总线,但是当硬盘通过PCIe总线与处理器连接时,AHCI协议无法为PCIe SDD提供最佳的性能。而NVMe的规划充分利用了PCIe SSD的低延迟与并行性,兼顾处理器平台架构,最大程度的发挥了SDD的高性能,读写速度可超过1GB/s。本文描述了一种嵌入式飞腾4核CPU平台下的NVMe固态硬盘驱动设计和固态硬盘硬件实现。实验表明,该设计相较于之前的SATA固态硬盘极大的提高了数据的读写速度,增强了存储系统的性能。

1 系统组成

本系统的硬件环境主要包含两部分,一个处理器模块加一块SSD,硬件设计的示意如图1所示。其中的处理器模块采用飞腾公司的FT2000-4,该处理器集成4个64位高性能核,最高主频3.0GHz,设计中的工作主频为1.0GHz,处理能力为16GIPS/Core@1GHz。

图1 存储系统逻辑结构示意图

该系统中的SSD是一种典型的SOC(System on Chip)单机系统,模块之间通过AXI高速和APB低速总线互联互通,完成信息和数据的通信。SSD中还有固件(Firmware),用于调度各个硬件模块,完成SSD产品所需要的功能,也包括数据从主机端到闪存端的写入和读取。SSD内部由PCIe GS9203主控制器芯片和Nand Flash阵列组成。PCIe主控芯片为28nm工艺,主控CPU具有两个 ARM Cortex R4 CP内核,支持PCIe Gen3 x4和NVMe 1.3c协议标准,有8个Flash通道, Flash芯片采用国产长江存储科技有限责任公司的TLC X1-9050 NAND FLASH,是中国首款64层3D NAND闪存。

2 NVMe驱动设计

NVMe驱动依据功能的不同,可划分为驱动接口模块,初始化模块和命令执行模块。其中命令执行模块为核心,设备初始化模块涉及控制器初始化、数据存储链表创建、命令队列的设置,驱动接口模块用于处理上层文件系统对设备的访问。驱动的架构如图2所示。

图2 NVMe驱动架构图

本系统中,主机端在上电后首先运行天脉3嵌入式实时操作系统,运行过程中调用NVMe驱动的初始化模块,完成硬件和软件的准备工作。随后在启动文件系统时将驱动接口注册到文件系统的IO函数中,最后应用软件调用文件操作函数时会调用到驱动读写接口。

■ 2.1 控制器初始化

NVMe控制器初始化的主要内容是找到控制器,通过配置其内部的寄存器使其就绪,并在主机端的内存上创建命令队列,创建数据缓冲链表,并完成MSI中断的初始化和注册。

2.1.1 NVMe寄存器配置

NVMe作为一种寄存器级别的接口连接到PCIe接口上,其寄存器配置包括PCIe寄存器配置和NVMe控制器寄存器配置。

PCIe寄存器配置主要是PCI header、和PCI Capabilities的配置。PCI header类型分为两种,type0表示设备,type1表示桥。NVMe控制器属于设备则定义为type0类型。当系统完成PCIe的初始化且设备被挂到总线上时,PCI header中的设备ID与厂商ID会有固定的值,该值是设备的唯一标识。基地址寄存器会写有地址值,该值作为访问设备其他寄存器的基址。设备各项功能的设置是通过功能指针寄存器来完成的。功能指针寄存器所指向的是位置是配置寄存器组链表的第一个条目[1]。常用的能力设置包括对NVMe控制器的电源管理、中断管理(包括MSI、MSI-X)的设置,设置完之后再配置命令寄存器使能设备。

NVMe控制器寄存器的设置主要是对表1中所列举的寄存器进行赋值,寄存器描述见表1。

表1 NVMe控制器寄存器功能描述表

2.1.2 NVMe队列创建

NVMe命令队列按照类型可以分为Admin命令队列与I/O命令队列,读写电子盘通常使用IO队列。NVMe协议针支持多达65535个IO命令队列,每一个队列可容纳64K 条命令。IO命令队列按照用途不同可分为命令提交队列SQ和命令完成队列CQ。SQ队列中一条命令的内容包括操作码、ID、要操作盘的起始块号、块数量、数据所在的缓冲等。CQ队列中的一条命令包括下一条命令位置、下一条命令ID当前命令ID、当前命令状态等。一个队列即是主机端内存上的一段连续的环形缓冲,在初始化NVMe时向系统申请内存空间,然后将空间的基地址控制器的ASQ寄存器与ACQ寄存器。每一个队列都有对应QID、虚拟地址、物理地址、长度、头指针、尾指针和相应的门铃寄存器。本驱动定义了队列信息结构如下:

命令队列在多核处理器上可采用两种设计方法,一种是一个核上安排一个SQ与一个CQ。另一种为一个核上安排一个CQ多个SQ。本驱动运行在一个核上,采用第一种方式。队列通过对应的门铃寄存器,在host与控制器间传递消息。

2.1.3 创建数据缓冲表

NVMe的数据寻址方式包括物理页表(PRP)和分散聚合表(SGL),本驱动设计采用PRP方式。PRP表中的每一项是一个64位指针,格式为页地址+页内偏移,每一项指向一个内存页,页的大小在CC寄存器中定义,通常一页的大小为4KB,因此在进行数据传输时,有时会要求数据缓冲的起始地址须4KB对齐。

命令的Dword6~Dword9定义了PRP1、PRP2两个指针,通过PRP2可以指向PRP List。PRP算法根据数据的长度有三种模式,如图3所示。

图3 数据缓冲PRP示意图

当数据小于等于4KB时只需将PRP1指向数据所在的地址即可;若数据大于4KB小于等于8KB则须将PRP1指向数据所在的地址,PRP2指向数据所在地址加上4K位置;若数据大于8K,则需将PRP1指向数据所在地址,PRP2指向PRP List。

■ 2.2 命令执行过程

NVMe命令按照类型可以分为Admin命令与I/O命令。Admin命令主要负责管理NVMe控制器,IO命令负责操作固态硬盘,常用的Admin命令包括identify、创建SQCQ、删除SQCQ。常用的IO命令包括Read 、Write、Flush。

图4为NVMe 命令执行过程。主机写命令道SQ队列,通过TailDoorbell通知NVMe控制器,控制器获得命令并执行,将命令写入CQ队列(无论命令是否执行成功),产生中断提醒主机命令已完成。主机处理CQ中的命令信息,最后更新HeadDoorbell告知控制器命令已处理。

图4 NVMe命令执行过程示意图[3]

为解决多任务对共享资源的互斥访问,在写命令到SQ后,提交命令的任务应先等待资源可用的信号量,待控制器执行完一条命令后会向主机发出MSI中断,主机在MSI中断服务函数中处理完成队列,最终释放资源信号量。

3 NVMe驱动应用

本驱动应用于某军用飞机的数据共享系统,为其中的数据库管理软件提供存储服务。操作系统为国产自主可控的天脉3多分区RTOS,使用场景如图5所示。

图5 NVMe驱动应用场景示意图

在天脉3核心OS启动过程中完成NVMe控制器的初始化、命令队列以及数据缓冲PRP表的创建工作,随后将驱动接口注册到文件系统中。当分区应用数据库管理软件中的任务使用标准IO进行文件操作时,由文件系统调用驱动的接口模块实现对NVMe电子盘的读写访问。本设计中NVMe驱动最大支持单次DMA传输512KB数据,当数据大于512KB时,驱动会将数据以512KB为单位分割,进行多次传输。在PCIe3.0接口4x下进行读写速度测试,测量数据如图6所示。

图6 NVMe驱动读写电子速度图

从实验结果可知,当数据量很小时,读写速度也较慢,在数据量接近或大于设备支持的单次最大处理的字节数512KB时,读写速度稳定在1000MB/s上下,驱动表现出良好的性能。

4 结束语

NVMe协议定义了基于PCIe的SSD的寄存器接口、命令集合与功能集合,通过PCIe接口将I/O命令和响应映射到主机中的共享内存。相较于SATA或AHCI协议,NVMe接口支持与多核处理器的并行I/O,实现高吞吐量,缓解了CPU瓶颈。NVMe电子盘带来高速的读写能力时,相比SAS和SATA电子盘在价格上就更昂贵一些,而且消耗的功率可能也会增加,同时在容量方面不及普通硬盘最大只有4TB,不过在很多高性能领成为好的选择。本文实现的国产嵌入式实时操作系统天脉3下的NVMe驱动,提升了航空装备在存储系统中的性能,对于嵌入式机载领域的数据存储有着很高的应用价值。

免责声明

我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自各大过期杂志,内容仅供学习参考,不准确地方联系删除处理!