0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用QSPI Flash控制器开发板上的 QSPI Flash进行写读操作

FPGA之家 来源:Vuko-wxh 作者:Vuko-wxh 2021-06-10 17:08 次阅读

学习内容

本文首先介绍Flash和QSPI Flash控制器的相关内容,然后使用 QSPI Flash 控制器,开发板上的 QSPI Flash 进行写、 读操作。通过对比读出的数据是否等于写入的数据, 从而验证读写操作是否正确。

开发环境

vivado 18.3&SDK,PYNQ-Z2开发板。

Flash简介

Flash存储器,又叫做闪存,是一种非易失性存储器。具有操作方便读写速度快等优点。一般用于存储操作系统程序代码,或者用于数据存储。Flash的存储单元组织为块阵列,块是擦除操作的最小单位,擦除操作将块内的所有为置位为1,页是读写操作的基本单位。

在对页进行写操作前,要判断该页内所有位是否为1。如果全部为1可以写操作,否则要对整块进行擦除操作(Flash只能从1反转到0)。Flash在内部结构(接口)上主要分为Nor flash 和NAND flash。

Nor Flash :写入和擦除的速度低;结构复杂,成本高;存储容量较小;一般用于存储Bootloader以及操作系统或者程序代码,可以在芯片内部直接运行代码。NAND Flash :写入和擦除的速度较快;结构简单,成本低;存储容量较大;一般用于存储材料和数据。

Flash在外部接口上主要分为CFI flash 和SPI(STD/Dual/Quad) flash。CFI flash 读写速度快,需要的硬件引脚多且不同容量的硬件不兼容;而SPI(STD/Dual/Quad) flash读写速度慢,需要的硬件引脚少且不同容量的硬件兼容。

QSPI Flash简介

介绍

Quad-SPI闪存控制器是位于PS内的输入/输出外设(IOP)的一部分。它用于访问多位串行闪存设备,以实现高吞吐量和低引脚数应用。

控制器可以以三种模式运行:I / O模式,线性寻址模式和传统SPI模式。

在I / O模式下,软件与闪存设备协议紧密交互,所以在该模式下需要对协议进行详细了解。软件通过使用四个TXD寄存器将闪存命令和数据写入控制器。软件通过读取RXD寄存器。

线性寻址模式使用设备操作的子集来消除I / O模式读取闪存所需的软件开销。也就是说线性寻址模式比IO模式要快的多。线性模式采用硬件来向闪存发出命令,并控制从flash到AXI接口的数据。控制器响应AXI接口上的存储器请求,就好像闪存是ROM存储器。

在传统模式下,QSPI控制器充当普通的SPI控制器。

控制器可以与一或两个闪存设备接口。可以并行连接两个设备以实现8位性能,也可以以堆叠的4位布局连接以最大程度地减少引脚数。

系统框图

QSPI Flash 控制器的系统框图如下所示:

e69b3254-c9c7-11eb-9e57-12bb97331649.png

从上图中可知, QSPI Flash 控制器通过 MIO 与外部 Flash 器件连接,支持三种模式:单个从器件模式、双从器件并行模式和双从器件堆叠模式。双从器件并行模式把每个flash的IO进行单独连接,扩展成8位用于控制对不同flash的访问。而双从器件堆叠模式,使用SS片选信号进行区分flash的使能,所以想扩展 QSPI Flash 的存储容量,可以使用双从器件并行模式。

当使用单个设备时,直接存储器读取的地址映射从FC00_0000开始,最大为FCFF_FFFF(16 MB)。两台设备系统的地址映射取决于存储设备和I / O配置。

QSPI Flash 控制器内部框图

e6d89702-c9c7-11eb-9e57-12bb97331649.png

由上图可知,在线性地址模式下,使用的是AXI的接口进行数据交互的,首先由AXI总线读取到响应的指令,并存到Command FIFO,然后使用AXI to SPI的命令转化器传输到选择器。在IO模式下,使用的是APB接口直接把接收到的信号传输给选择器进行选择。

然后选择器进行功能选择后传输到TxFIFO,接着把Tx FIFO的数据进行串行化,然后通过MIO引脚发送。接收部分原理相反,而且可以看出在线性地址模式下,接收信号的转换使用的是数据转换器。所以在线性地址模式下,只支持读取数据,不支持发送数据。

流程控制

在数据传输期间,I / O模式具有不同的流控制模式。用户可以在自动和手动模式之间进行选择,该模式由config_reg.MANSTARTEN(Man_start_com)控制。在自动模式下,包括芯片选择控制在内的整个传输过程都在硬件中完成。

无需软件干预。在手动模式下,用户控制数据传输的开始。在这种情况下,软件要么将整个传输序列写入TxFIFO,要么直到TxFIFO已满。在手动模式下,用户除了控制传输开始之外,还可以选择控制芯片选择。从命令开始,软件再次将传输序列写入TxFIFO,直到TxFIFO已满。然后,软件拉高CS,然后手动启动进行硬件管理。

编程指南

在xilinx给出的UG585指导手册中,对QSPI Flash 控制器编程设计进行了指导开发,用户可以根据自己的设计需要参考指导手册中的编程顺序实现自己的应用功能。

启动顺序

配置时钟

配置发送/接收信号。(以上两步在vivado底层搭建中已经完成设计)

配置控制器

该步骤适用于线性寻址和I / O模式。它配置了控制器的波特率,FIFO,flash模式,时钟相位/极性和对环回延迟进行编程。

配置控制器。写入qspi.Config_reg寄存器。a. 设置波特率[BAUD_RATE_DIV]。b. 选择主模式,[MODE_SEL] = 1。C. 选择flash模式(不是传统SPI),[LEG_FLSH] = 1。d. 选择Little Endian,[endian] = 0。e. 将FIFO宽度设置为32位[FIFO_WIDTH]。F. 设置时钟相位[CLK_PH]和极性[CLK_POL]。

启用回送时钟。如果使用回送时钟,确保将qspi.Config_reg [BAUD_RATE_DIV]设置为0b00,并使用以下设置配置qspi.LPBK_DLY_ADJ(回送延迟调整)寄存器:a. 设置为选择内部时钟。qspi.LPBK_DLY_ADJ [USE_LPBK] = 1。b. 将时钟延迟设置为0。qspi.LPBK_DLY_ADJ [DLY0] = 0b00。c. 设置时钟延迟1. qspi.LPBK_DLY_ADJ [DLY1] = 0b00。

线性寻址模式

线性寻址模式下数据读取(存储器读取)的操作顺序如下:

将手动启动启用设置为自动模式。设置qspi.Config_reg [Man_start_en] = 0。

使能片选信号。设置qspi.Config_reg [PCS] = 0。

将配置寄存器编程为线性寻址模式。

启用控制器。设置qspi.En_REG [SPI_EN] = 1。

从线性地址存储区读取数据。内存范围取决于大小和设备数量。范围是从0xFC00_0000到0xFDFF_FFFF。

禁用控制器。设置qspi.En_REG [SPI_EN] = 0。

取消使能片选信号。设置qspi.Config_reg [PCS] = 1。

配置I / O模式

使用I / O模式进行读取和写入编程步骤如下:

启用手动模式。qspi.Config_reg [Man_start_en,Manual_CS] = 1。

配置flash设备。对单个闪存设备使用qspi.LQSPI_CFG寄存器的重置值。如果是并行双闪存设备,则将1写入TWO_MEM,SEP_BUS位字段。

使能片选。设置qspi.Config_reg [PCS] = 0。

启用控制器。设置qspi.En_REG [SPI_EN] = 1。

将字节序列写入闪存。使用TXD从1到4字节写入TxFIFO寄存器。

避免TxFIFO溢出。当TxFIFO为空时,可以写入252个字节。此后,软件可以通过读取qspi.Intr_status_REG [TX_FIFO_full]并等待直到它等于0之后再写入TXD寄存器,来避免TxFIFO溢出。

启用中断。写入qspi.Intrpt_en_REG。

开始数据传输。设置qspi.Config_reg [Man_start_com] = 1。

中断处理程序:在编程/读取操作期间,将所有需要的数据传输到QSPI flash,并传输到Quad-SPI flash。

如果执行了读取操作:重新排列READ数据以消除由于空循环而读取的数据。

取消使能片选信号。设置QSPI.Config_reg [PCS] = 1。

禁用控制器。设置qspi.En_REG [SPI_EN] = 0。

I/O模式中断服务程序

配置ISR以根据Quad-SPI器件类型处理中断条件。要从Quad-SPI器件读取数据,最简单的ISR从RxFIFO读取数据并将内容写入TxFIFO。控制器生成系统外设中断(SPI),IRQ ID#51。对以下两种情况进行触发中断。a. 读取传输中断。RxFIFO不为空中断b. 写传输中断。TxFIFO未完全中断

I/O模式中断

中断仅在I / O模式下使用。只要满足任何中断条件,控制器中断就被置为有效。Quad-SPI中断处理程序检查中断原因。单个中断服务程序可以管理所有中断条件。

Rx和Tx的中断处理程序

中断处理程序由IRQ ID#51触发。示例读取RxFIFO直到其为空,然后填充TxFIFO。RxFIFO非空中断状态用于确定是否可以从RxFIFO读取内容。TxFIFO未满中断指示TxFIFO中是否有空间容纳更多内容。

禁用控制器中的所有中断。将qspi.Intrpt_dis_REG [TX_FIFO_not_full,RX_FIFO_full]都设置为1。

清除中断。将1s写入中断状态寄存器qspi.Intr_status_REG。

清空RxFIFO。检查是否声明了RxFIFO非空中断。如果qspi.Intr_status_REG [RX_FIFO_not_empty] = 1,则RxFIFO中有数据。a. 如果状态为有效,则从RxFIFO读取数据。使用qspi.RX_data_REG寄存器读取数据。b. 从RxFIFO读取数据并轮询中断状态,直到RxFIFO为空。当qspi.Intr_status_REG [RX_FIFO_not_empty] = 0时,RxFIFO为空。

填充TxFIFO。检查TxFIFO未满状态是否有效。如果 qspi.Intr_status_REG [TX_FIFO_not_Full] = 1,则存在要发送到闪存设备的数据(编程和/或读取操作):a. 将数据写入qspi.TXD0寄存器。b. 轮询qspi.Intr_status_REG [TX_FIFO_full] = 1,这表明TX FIFO已满。c. 遵循步骤a和b,直到将所有数据写入TxFIFO或直到qspi.Intr_status_REG[TX_FIFO_full] = 1。

启用中断。将qspi.Intrpt_en_REG [TX_FIFO_not_full,RX_FIFO_full]都设置为1。

开始数据传输。设置qspi.Config_reg [MANSTRTEN] = 1。

在本次工程设计中,使用QSPI Flash控制器对ZYNQ的QSPI Flash进行读写操作。通过对比读取数据和写入数据是否相等验证读写功能是否正常。

硬件平台搭建

新建工程,创建 Block Design。添加ZYNQ7 ip,根据本次工程需要对IP进行配置。勾选本次工程使用的资源。完成对所用资源的勾选,在clock configuration这里可以查看对QSPI的时钟配置。这里不需要对其他资源进行配置,所以可以使用默认配置。然后我们进行generate output product 然后生成HDL封装。这里用到了仅仅用到了PS部分的资源,所以不需要进行管脚分配。点击导出硬件资源(不用包含bit流文件),接着launch SDK,进入软件部分编写。

SDK软件部分

打开SDK后,新建application project。在system.mss中可以打开相关参考文档辅助设计。可以选择qspi的例程进行参考设计,导入例程模板,根据提供的模板,主要使用的函数如下,这里对他的读写测试进行了简化,

int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)

{

int Status;

u8 *BufferPtr;

u8 UniqueValue;

int Count;

int Page;

XQspiPs_Config *QspiConfig;

//初始化QSPI

QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);

XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,QspiConfig-》BaseAddress);

//自测

Status = XQspiPs_SelfTest(QspiInstancePtr);

if (Status != XST_SUCCESS) {

return XST_FAILURE;

}

//初始化读写BUFFERfor (UniqueValue = UNIQUE_VALUE, Count = 0; Count 《 PAGE_SIZE;

Count++, UniqueValue++) {

WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);

}

memset(ReadBuffer, 0x00, sizeof(ReadBuffer));

//设置手动启动和手动片选模式

XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_MANUAL_START_OPTION |

XQSPIPS_FORCE_SSELECT_OPTION |

XQSPIPS_HOLD_B_DRIVE_OPTION);

//设置QSPI时钟的分频系数

XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);

//片选信号置为有效

XQspiPs_SetSlaveSelect(QspiInstancePtr);

//读FLASH ID

FlashReadID();

//使能FLASH Quad模式

FlashQuadEnable(QspiInstancePtr);

//擦除FLASH

FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);

//向FLASH中写入数据for (Page = 0; Page 《 PAGE_COUNT; Page++) {

FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,

PAGE_SIZE, WRITE_CMD);

}

//使用QUAD模式从FLASH中读出数据

FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, READ_CMD);

//对比写入FLASH与从FLASH中读出的数据

BufferPtr = &ReadBuffer[DATA_OFFSET];

for (UniqueValue = UNIQUE_VALUE, Count = 0; Count 《 MAX_DATA;

Count++, UniqueValue++) {

if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {

return XST_FAILURE;

}

}

return XST_SUCCESS;

}

运行效果

References

ZYNQ正点原子开发视频

UG585

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 控制器
    +关注

    关注

    112

    文章

    16159

    浏览量

    177281
  • FlaSh
    +关注

    关注

    10

    文章

    1618

    浏览量

    147705
  • STD
    STD
    +关注

    关注

    0

    文章

    36

    浏览量

    14340
  • 开发板
    +关注

    关注

    25

    文章

    4926

    浏览量

    97139

原文标题:ZYNQ-QSPI Flash读写操作

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    在mmWave SDK增加QSPI Flash驱动的示例

    电子发烧友网站提供《在mmWave SDK增加QSPI Flash驱动的示例.pdf》资料免费下载
    发表于 09-11 14:20 0次下载
    在mmWave SDK增加<b class='flag-5'>QSPI</b> <b class='flag-5'>Flash</b>驱动的示例

    基于FPGA的内存128M flash芯片控制器设计

    大概是先读出器件厂商和芯片ID,然后命令,使能打开,页操作写入数据(值得说明的是我们FLASH是新的所以没进行擦除命令,建议擦除---关
    发表于 05-23 16:07

    【GD32H757Z海棠派开发板使用手册】第四讲 FMC-片内Flash擦写实验

    FMC即Flash控制器,其提供了片Flash操作所需要的所有功能,在GD32H7XX系列MCU中,具有高达3840KB字节的片
    的头像 发表于 04-19 10:09 1152次阅读
    【GD32H757Z海棠派<b class='flag-5'>开发板</b>使用手册】第四讲 FMC-片内<b class='flag-5'>Flash</b>擦写<b class='flag-5'>读</b>实验

    STM32F746 QSPIFlash扩展后,添加到工程下载发现报错,为什么?

    使用 W25Q128 模块 ,使用的是微雪STM32F746IGT6的开发板,在QSPI进行Flash扩展了解发现需要做一个.FLM的Flash
    发表于 04-17 06:31

    使用STM32H750 QSPI W25Q64作为外部FLASH,映射后读0X90010000地址的数据读到的是0XFF的原因?

    我使用STM32H750QSPIW25Q64 作为外部FLASH,使用非映射方式读写FLASH 正常,映射后,0X90000000地址的数据也正常,但是0X90010000 地址的
    发表于 04-01 06:24

    STM32 QSPI怎么退出映射模式?

    FLASH 中,多 QSPI 进行ERASE 和 PROGRAMME, 这个时候我就需要退出映射模式,请问怎么退出映射模式
    发表于 03-29 08:15

    STM32WB55RGV6使用QSPI官方例程读写外部FLASH,读出的数据跟写入的数据不相同是为什么?

    STM32WB55RGV6 使用 QSPI 官方例程擦除、 FLASH,每一步都返回OK,但是读出的数据跟写入的数据不相同,读出的数据是 0X99 0X99 0X99 0XFF
    发表于 03-27 08:29

    STM32H750 QSPI flash重映射模式下有方法能实现读写操作吗?

    STM32H750 QSPI flash重映射模式下有方法能实现读写操作
    发表于 03-25 08:06

    STM32H7B0通过QSPI地址映射外部flash开始使用正常,出现QSPI功能异常是什么原因导致的?

    STM32H7B0 通过QSPI地址映射外部flash开始使用正常,后面出现QSPI功能异常(直接寻址和地址映射均不能访问外部flash),QSPI
    发表于 03-08 06:34

    ctt4bfqspi最大速度是多少?

    想问一下,ctt4bf qspi 最大速度是多少? 我在用户手册以及数据表没有看到相关信息,是在什么地方我忽略了吗?
    发表于 03-01 10:09

    stm32 flash数据怎么存储的

    stm32 flash数据怎么存储的  STM32是一款广泛应用于嵌入式系统开发的微控制器,它的Flash存储
    的头像 发表于 01-31 15:46 2241次阅读

    如何在PSOC 6中初始化QSPI

    我正在使用 QSPI 进行外部闪存/。 我打电话 结果 = cy_serial_flash_qspi_init ( sfdp_slave
    发表于 01-26 07:48

    在软件SDK中选择不同的下载模式时,是哪个部件更改了QSPI0中寄存的值?

    FLASH外设,但是我不知道这个寄存是在哪里被设置的,有没有大佬告诉我,在软件SDK中选择不同的下载模式时,是哪个部件更改了QSPI0中寄存的值?是系统总线上的Jtag吗?还是C
    发表于 01-10 08:10

    控制flash读写的模块做了相关修改,用NucleiStudio烧程序出现Debug interrupt didn\'t clear.的原因?

    axi2icb的桥接模块是否正确,我又一个flash_icb2axi模块,将蜂鸟E203对flash操作由icb总线,转为axi总线。大致的改动如下: 因为sirv_
    发表于 01-10 06:47

    使用 PCIE 更新 AMD ZYNQ™ 的 QSPI Flash 参考设计

    QSPI 控制器,用来更新 Flash 的启动分区。 软件方面,移植了 Embedded SW 的相关驱动代码至 xdma 平台,并提供了一个简单的上位机测试程序,用来烧启动镜像
    发表于 11-30 18:49