Zynq学习笔记之QSPI读写功能

1.版本说明

DataAuthorVersion Revision
2021/12/11abner1.0 初定版本

2. 目标

zynq PS端裸核下实现QSPI FLASH的擦除、读、写,并保存用户所需要的信息。
FPGA芯片 : ZYNQ7010
FLASH芯片 :N25Q128A
硬件连接为 :Single SS 4-bit IO => Data Mode x4

3.FLASH芯片分析

3.1 FLASH芯片 :N25Q128A

    支持协议:Extended SPI, dual I/O, and quad I/O , 分别对应数据线x1/x2/x4
    擦除大小:4KB/64KB/Full-chip
    容量/扇区:128 = 128Mbit = 16MByte 
                              = 256个sectors x 64KB(每个sectors的容量)  
                              = 256个sectors x 16个subsectors x 4KB (每个sectors包含16个subsectors,每个subsectors容量为4KB) 
                              = 4066个subsectors x 4KB (每个subsectors容量为4KB) 
                              = 65536 x 256Byte(page size)

在这里插入图片描述

需要注意,写的时候以page为单位,但是擦除的时候最小单位是4KB

3.2 FLASH操作指令

标准命令适用于不同厂家不同型号的FLASH

在这里插入图片描述
在这里插入图片描述

3.2.1 FLASH操作指令之读设备ID

接口形式 :Extended SPI
指令数据 :9Fh + Manufacturer identification (1Byte) + Device identification (2Byte)+ UID
指令格式 :TX CMD + RX DATA x N (N实际常用值为3)
以上三个输出由芯片厂家决定,当前N25Q128A 输出为:20h BAh 18h

3.2.2 FLASH操作指令之写使能

接口形式 :Extended SPI/D-SPI/Q-SPI
指令数据 :06h

3.2.3 FLASH操作指令之写失能

接口形式 :Extended SPI/D-SPI/Q-SPI
指令数据 :04h

3.2.4 FLASH操作指令之读状态寄存器

接口形式 :Extended SPI/D-SPI/Q-SPI
指令数据 :05h + Status (1Byte)
8bit映射 : 7-2bit 大部分情况下可忽略, 写使能锁定1bit,擦除/写正在进行/设备忙0bit
在这里插入图片描述

3.2.5 FLASH操作指令之擦除指令

接口形式 :Extended SPI/D-SPI/Q-SPI
指令数据 :20h/D8h/C7h
操作步骤 :

  • 写使能 06h
  • 可选1 写擦除指令“全片擦除” C7h
  • 可选2 写擦除指令“64K擦除” D8h + Addr (3Byte)
  • 可选3 写擦除指令“4K擦除” 20h + Addr (3Byte)
  • 重复查状态寄存器直到确定设备处于空闲状态
  • 重点要注意,单次擦除的最小区域是4K,所以对于不想擦除的数据需要预先读出来,然后擦除,最后同要写的数据一起更新到FLASH

3.2.6 FLASH操作指令之写指令

接口形式 :Extended SPI/D-SPI/Q-SPI
指令数据 :03h + Addr (3Byte) + TX (Max 256byte)
操作步骤 :

  • 写使能 06h
  • 写指令 03h + Addr (3Byte) + TX (Max 256byte)
  • 重复查状态寄存器直到确定设备处于空闲状态
  • 重点要注意,该写数据过程为页编程,因此单词最大可编程空间为256Byte

3.2.7 FLASH操作指令之读指令

接口形式 :Extended SPI/D-SPI/Q-SPI
指令数据 :02h + Addr (3Byte) + RX (Nbyte)
可选读指令比较多,如没有性能要求,最基本的读即可完成,若对性能有要求可以开启QSPI然后快速输出

3.2.8 FLASH操作指令之使能Q-SPI模式

暂时没有需求(但是原理一样,通过指令完成操作)

3.XILINX资料分析

XILINX的QSPI FLASH控制器支持三种模式:I/O mode, linear addressing mode, and legacy SPI mode
I/O mode : 读写QSPI FLASH时使用;支持QSPI并不是说一定要使用QSPI模式读写FLASH,仍然可以可以SPI接口操作FLASH
linear addressing mode : 只读FLASH时使用,通过地址映射后,可以像访问内存一样读数据,需要注意单个FLASH只能映射到16MB
legacy SPI mode : 传统SPI模式,此时控制器就是一个普通的SPI控制器;

3.1.XILINX QSPI接口配置流程

  • XQspiPs_LookupConfig 硬件信息
  • XQspiPs_Config 配置
  • XQspiPs_CfgInitialize 初始化
  • XQspiPs_SelfTest 自检
  • XQspiPs_SetOptions 设置操作模式
  • XQspiPs_SetClkPrescaler 设置时钟
  • XQspiPs_SetSlaveSelect 选择FLASH设备

3.2.初始化代码

    printf("----- info : Init QSPI  \r\n");

    XQspiPs_Config *QspiConfig;

    /* Initialize the QSPI driver so that it's ready to use*/
    QspiConfig = XQspiPs_LookupConfig(XPAR_XQSPIPS_0_DEVICE_ID);
    if (QspiConfig == NULL)
    {
        return false;
    }

    Status = XQspiPs_CfgInitialize(&QspiInstance, QspiConfig,
                    QspiConfig->BaseAddress);
    if (Status != XST_SUCCESS)
    {
        return false;
    }

    /* Perform a self-test to check hardware build*/
    Status = XQspiPs_SelfTest(&QspiInstance);
    if (Status != XST_SUCCESS)
    {
        return false;
    }

    /*
     * Set Manual Start and Manual Chip select options and drive HOLD_B
     * pin high.
     */
    XQspiPs_SetOptions(&QspiInstance, XQSPIPS_MANUAL_START_OPTION |
                                        XQSPIPS_FORCE_SSELECT_OPTION |
                                        XQSPIPS_HOLD_B_DRIVE_OPTION);

    XQspiPs_SetClkPrescaler(&QspiInstance, XQSPIPS_CLK_PRESCALE_8);

    XQspiPs_SetSlaveSelect(&QspiInstance);

3.3.测试代码


    uint8_t FlashWriteBuffer[10];
    uint8_t FlashReadBuffer [10];
    FlashWriteBuffer[0] = 0x9F;
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, &FlashReadBuffer, 1+3);
    if (Status != XST_SUCCESS) {
        return false;
    }
    // 读状态
    FlashWriteBuffer[0] = 0x05;
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, &FlashReadBuffer,1+1);
    if (Status != XST_SUCCESS) {
        return false;
    }

    // 写使能
    FlashWriteBuffer[0] = 0x06;
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, NULL, 1+0);
    if (Status != XST_SUCCESS) {
        return false;
    }

    // 读状态
    FlashWriteBuffer[0] = 0x05;
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, &FlashReadBuffer,1+1);
    if (Status != XST_SUCCESS) {
        return false;
    }

    // 擦除整片
    FlashWriteBuffer[0] = 0xC7;
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, NULL, 1+0);
    if (Status != XST_SUCCESS) {
        return false;
    }

    do
    {
        // 查询 设备状态
        FlashWriteBuffer[0] = 0x05;
        Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, &FlashReadBuffer, 1+1);
        if (Status != XST_SUCCESS) {
            return false;
        }
    } while (FlashReadBuffer[1] != 0x00);

    // 读数据擦除后全是FF
    FlashWriteBuffer[0] = 0x03;
    FlashWriteBuffer[1] = 0;    // Addr
    FlashWriteBuffer[2] = 0;    // Addr
    FlashWriteBuffer[3] = 0;    // Addr
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, &FlashReadBuffer, 4+6);
    if (Status != XST_SUCCESS) {
        return false;
    }


    // 写使能
    FlashWriteBuffer[0] = 0x06;
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, NULL, 1+0);
    if (Status != XST_SUCCESS) {
        return false;
    }
    // 写数据
    FlashWriteBuffer[0] = 0x02;
    FlashWriteBuffer[1] = 0;
    FlashWriteBuffer[2] = 0;
    FlashWriteBuffer[3] = 0;
    FlashWriteBuffer[4] = 4;
    FlashWriteBuffer[5] = 5;
    FlashWriteBuffer[6] = 6;
    FlashWriteBuffer[7] = 7;
    FlashWriteBuffer[8] = 8;
    FlashWriteBuffer[9] = 9;
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, NULL, 4+6);
    if (Status != XST_SUCCESS) {
        return false;
    }

    do
    {
        // 查询 设备状态
        FlashWriteBuffer[0] = 0x05;
        Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, &FlashReadBuffer,1+1);
        if (Status != XST_SUCCESS) {
            return false;
        }
    } while (FlashReadBuffer[1] != 0x00);

    // 读数据校验
    FlashWriteBuffer[0] = 0x03;
    FlashWriteBuffer[1] = 0;
    FlashWriteBuffer[2] = 0;
    FlashWriteBuffer[3] = 0;
    Status = XQspiPs_PolledTransfer(&QspiInstance, &FlashWriteBuffer, &FlashReadBuffer, 4+6);
    if (Status != XST_SUCCESS) {
        return false;
    }

4.注意事项

不同型号的FLASH,操作命令,单次擦除空间会有区别,需要根据Datasheet来更改

5.可扩展

QSPI模式下的相关操作暂未实现。

  • 4
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值