• 1.1 SST25VF080B简介

1.1.1 主要特性

关键点:容量、速度(时钟速度、读写速度)、功耗。

容量:8MBit;

最高SPI时钟频率:50MHz;

低功耗模式下电流消耗:5uA,正常读模式电流:15mA;低功耗!采用不同的制造技术功耗要低很多。

整片擦除:35ms;扇区/块擦除:18ms;字节编程:7us;整片擦除的速度要快很多!

  • 1.2 系统框图与电路1.2.1 系统框图

关于内部存储矩阵的访问和存储结构同并行NorFlash的一致,只不过多了个串行接口,用于实现对串行数据的解码。

1.2.2 存储组织

扇区大小4KB,块大小:32/64KB;页大小为字节或字。

1.2.3 引脚及封装

引脚说明:

SCK、SI、SO、CE – SPI接口控制线

WP# -- 用于使能状态寄存器中的BPL位,有效时只允许锁定BPL,而不允许解锁BPL。不是说明使能保护!BPL位用于锁定控制扇区保护的相应位。

HOLD# -- 用于暂停与SPI的通信,而不需要复位器件;

1.2.4 典型电路

使用STM32F103驱动该器件时,典型的电路如图所示。

注意,WP为低,判定寄存器的锁定功能将启用。但不会太影响片内块的保护。

  • 1.3 保护机制

软件写保护:状态寄存器中的BP3—BP0、BPL提供片内块、状态寄存器的写保护。

硬件保护:WP#引脚—低电平,用于锁定状态寄存位7—BPL。由表2,WP#为高时,可以执行状态寄存器写命令,可随时更改状态寄存器。为低时,只能将BPL置为1,而不能从1置为0,即置1后,状态寄存器将锁定不变。

WP# àBPL、BP3—BP0

BPLàBP3、BP0

  • 1.4 编程接口

1.4.1 状态寄存器

状态寄存器用于用于获取FLASH的当前工作状态。

BUSY位:指示是否正在编程或擦除操作;

WEL位:指示器件是否处理可写的状态。RESET状态(0)指示不可写,默认在上电、完成写操作后,器件自行返回到不可写状态,以保护器件不受意外的擦写。因而每次写FLASH前,都必须先清除(写1),以使能器件的写。软件可控写。

AAI位:指示器件是否处理地址自动增加模式或者是字节编程模式。

BPL位:用于控制BPX是否可写。

BPX位:用于控制保护块的范围,属于软件保护,扇区保护如下。

这里的扇区保护比较简单,更为复杂的扇区保护机制可针对每个扇区进行保护。

1.4.2 命令接口

通信过程中,仅仅只有读ID、读数据、读状态寄存器需要在可保护CS不变而继续写数据。其它的则需要写完后接CS线。

  • 1.5 通信时序

1.单字SPI通信时序

无论SPI总线空闲时SCK为高或为低,保证在上升沿采样数据,下降沿输出数据。先传送高位,每次传送8位。

2. 读命令

3. 快速读模式

有可能内部使用了缓冲模式,可在更高的时钟速度(50MHz)下读数据。

4. 写使能

该命令可设置状态寄存器中的WEL位,使得可执行擦除和编程命令。

5. 写禁能

6. 字节编程

7. AAI编程

即自动地址增量的字编程,每个周期写1个字。

在最后,通过WRDI返回来正常模式。在每写完两个字后,需查询害怕状态。

在写字的过程中,有三种方式检测是否完成字编程。其中硬件检测:读SO的状态。可在写AAI命令之前,通过命令配置SO口为RD/BY#状态。或者也可通过读取状态寄存器来检测是否完成写操作。

8. 4KB的扇区擦除

9. 32K块擦除

10. 64K块擦除

11. 整片擦除

12. 读状态寄存器

13. 使能写状态寄存器和写状态寄存器

两条命令必须连续写,不允许被打断?以避免意外写状态寄存器。

l 当WP#为低电平时,BPL只能写1,不可写0.;此时若BPL位为高时,写状态寄存器命令将被忽略。即此时,状态寄存器只能被锁定(写1),而不能再解锁(写0)!锁定后将不能再任意改高保护方式,相当于将当前的保护方式给固定下来!

l 而若WP#为高电平,BPL位失效,状态寄存器不再被锁定,此时BPL、BPX可被更改。BPL位可设置为1,也可设置为0。可任意更改保护方式。

WP#的作用,锁定BPL为1。一旦BPL锁定为1,则BPX将不可再更改,即软件保护将被锁定。当WP#无效时,BPL可随时、任意更改,同时更改软件保护。

14. JEDEC Read-ID

获取SST制造商的ID和SST FLASH器件的ID。

  • 1.6 驱动设计

驱动框架如下图:

算法编写原则:

(1) 可以为每一种SPI Flash针对性的写一份驱动源码,但是当更换Flash时,需要修改的地方很多;当系统中有多个设备时,显示这不够用,因而最好的方法是实现面向对像的封装,将与Flash设备相关的信息封装在一个结构体内,具体的算法根据结构体中相关的数据来决定如何访问硬件,做到过程可以不依赖于实际的硬件;

(2) 尽量按标准的初始化、读写、关闭、控制接口设计API,这样可统一抽像出相应的结构,也易于使用和理解。留给最终用户调用的API应该尽量的少和易于理解;

(3) SPI Flash接口为SPI,操作方法与并行接口一致,但其扇区组织类似,从最大到最小区域分为芯片-块-扇区-页。编程算法则也是通过写命令序列的方式,如发送命令字-发送字节-发送数据-查询状态寄存器。保护方式是通过存储器中的一些非易失性的位置0或置1选择性地以扇区或块为保护单位。

  • 1.7 驱动代码
// SST25VF080B驱动接口
// By:lstzixing At ZLG
// Date: 2011-1
#include "STM32Lib\\stm32f10x.h"
#include "hal.h"

typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;

#define SPI_FLASH_SIZE (1024*1024*2) // SPI Flash容量
#define SPI_FLASH_OK 0
#define SPI_FLASH_ERR_PARA 3 // SPI Flash参数错误

// SPI Flash擦除操作码
#define SPI_FLASH_ERASE_CHIP 0 // 整片擦除
#define SPI_FLASH_ERASE_SECTOR 1 // 扇区擦除
#define SPI_FLASH_ERASE_BLOCK 2 // 块擦除

// SPI状态寄存器和位
#define SPI_FLASH_REG_BIT_BUSY (1 << 0)
#define SPI_FLASH_REG_BIT_WEL (1 << 1)
#define SPI_FLASH_REG_BIT_BPX (0xF << 2)
#define SPI_FLASH_REG_BIT_AAI (1 << 6)
#define SPI_FLASH_REG_BIT_BPL (1 << 7)

#define SPIFlashSelect()         GPIO_ResetBits(GPIOC, GPIO_Pin_13) /* SST CS = L */
#define SPIFlashDeSelect()         GPIO_SetBits(GPIOC, GPIO_Pin_13) /* SST CS = H */

/*********************************************************************************************************
** Function name: SPIFlashInit
** Descriptions: 初始化SPI硬件,设置相关的GPIO口、SPI控制器
** Input parameters: none
** Output parameters: None
** Returned value: none
*********************************************************************************************************/
void SPIFlashInit(void)
{
    // 打开SPI1和GPIO时钟
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN |
                    RCC_APB2ENR_IOPAEN |
                    RCC_APB2ENR_IOPBEN |
                    RCC_APB2ENR_IOPCEN |
                    RCC_APB2ENR_IOPDEN |
                    RCC_APB2ENR_IOPEEN |
                    RCC_APB2ENR_IOPFEN;

    // PA5/6/7为复用模式, 50MHZ
    GPIOA->CRL &= ~(GPIO_CRL_CNF5 | GPIO_CRL_CNF6 | GPIO_CRL_CNF7 |
                    GPIO_CRL_MODE5 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7);
    GPIOA->CRL |= GPIO_CRL_MODE5 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7 |
                  GPIO_CRL_CNF5_1 | GPIO_CRL_CNF6_1 | GPIO_CRL_CNF7_1;

    // 配置PC.13为输出片选线
    GPIOC->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13);
    GPIOC->CRH |= GPIO_CRH_MODE13;

    // 配置SPI1,第一个时钟沿采样、主机、分频最大、使能、软件从机管理
    SPI1->CR1 = //SPI_CR1_CPHA |
                SPI_CR1_MSTR |
                //SPI_CR1_BR |
                SPI_CR1_SSI |
                SPI_CR1_SPE |
                SPI_CR1_SSM; 

    SPI1->CR2 = ;

    SPIFlashDeSelect();
}

/*********************************************************************************************************
** Function name: SPIWriteReadByte
** Descriptions: 向SPI发送并读取一数据
** Input parameters: data 要发送的数据
** Output parameters: None
** Returned value: uint16 读取的数据
*********************************************************************************************************/
static uint16 SPIWriteReadByte(uint16 data)
{
    // 发送一字节
    while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);
    SPI1->DR = data;

    // 接收一字节
    while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
    return(SPI1->DR);
}

/*********************************************************************************************************
** Function name: SPIFlashReadstatusReg
** Descriptions: 读状态寄存器
** Input parameters: none
** Output parameters: 当前状态寄存器的值
** BIT0 -- BUSY位,写忙标志
** BIT1 -- WEL位,FLASH处于写保护状态
** BIT6[5..2]--BP [3..0],扇区保护位
** BIT6 -- 指示正在自动自境编程中
** BIT7 -- BPL,BPX的保护位
** Returned value: none
*********************************************************************************************************/
static uint8 SPIFlashReadstatusReg (void)
{
    uint8 uByte;

    // 发送读状态寄存器命令
    SPIFlashSelect();
    {
        SPIWriteReadByte(0x5);
        uByte = SPIWriteReadByte(0xFF);
    }
    SPIFlashDeSelect();

    return uByte;
}

/*********************************************************************************************************
** Function name: SPIFlashWritestatusReg
** Descriptions: 写状态寄存器
** Input parameters: status 要写入的值
** Output parameters: none
** Returned value: none
*********************************************************************************************************/
static void SPIFlashWritestatusReg (uint8 status)
{
    // 发送使能状态寄存器写命令
    SPIFlashSelect();
    {
        SPIWriteReadByte(0x50);
    }
    SPIFlashDeSelect();

    // 写命令和状态值
    SPIFlashSelect();
    {
        SPIWriteReadByte(0x1);
        SPIWriteReadByte(status);
    }
    SPIFlashDeSelect();
}

/*********************************************************************************************************
** Function name: SPIFlashReadID
** Descriptions: 读SPI FLASH的JEDEC ID
** Input parameters: none
** Output parameters: 读的ID,从最高字节到最低字节:制造商ID(1B)-存储类型(1B)-存储容量(1B)
** Returned value: none
*********************************************************************************************************/
uint32 SPIFlashReadID (void)
{
    uint32 spiID;

    // 发送低速读命令0x9F,3字节地址,写入的字节
    SPIFlashSelect();
    {
        SPIWriteReadByte(0x9F);
        spiID = SPIWriteReadByte(;
        spiID |= SPIWriteReadByte(;
        spiID |= SPIWriteReadByte(0xff);
    }
    SPIFlashDeSelect();

    return spiID;
}

/*********************************************************************************************************
** Function name: SPIFlashRead
** Descriptions: 以低速方式(<=25MHZ)从SPI FLASH读数据
** Input parameters: readBuf 读数据存储的缓冲区首址
** readCnt 要读取的数据量
** Output parameters: uint32 实际读得的数据量。当读地址超出芯片容量时,将只读在芯片地址范围内
** 的数据
** Returned value: none
*********************************************************************************************************/
uint32 SPIFlashRead (uint32 readAddr, uint8 * readBuf, uint32 readCnt)
{
    uint32 i;
    uint8 addr[];

    // 检查参数
    if (readAddr >= SPI_FLASH_SIZE ||
        readBuf ==  ||
        readCnt == ) {
        return SPI_FLASH_ERR_PARA;
    }

    // 校正要读的数据总量
    if (readAddr + readCnt >= SPI_FLASH_SIZE) {
        readCnt = SPI_FLASH_SIZE - readAddr;
    }

    // 将地址转换为字节数组
    addr[] = (uint8)(readAddr >> );
    addr[] = (uint8)(readAddr >> );
    addr[] = (uint8)(readAddr & 0xff);

    // 等待SPI Flash完成写操作
    while (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BUSY );

    SPIFlashSelect();
    {
        // 发送低速读命令0x3,3字节地址
        SPIWriteReadByte(0x3);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(addr[]);

        // 依次读readCnt个数据
        ; i < readCnt; i++) {
            readBuf[i] = SPIWriteReadByte(0xff);
        }
    }
    SPIFlashDeSelect();

    return i;
}

/*********************************************************************************************************
** Function name: SPIFlashFastRead
** Descriptions: 以高速方式(<=50MHZ)从SPI FLASH读数据
** Input parameters: readBuf 读数据存储的缓冲区首址
** readCnt 要读取的数据量
** Output parameters: uint32 实际读得的数据量。当读地址超出芯片容量时,将只读在芯片地址范围内
** 的数据
** Returned value: none
*********************************************************************************************************/
uint32 SPIFlashFastRead (uint32 readAddr, uint8 * readBuf, uint32 readCnt)
{
    uint32 i;
    uint8 addr[];

    // 检查参数
    if (readAddr >= SPI_FLASH_SIZE ||
        readBuf ==  ||
        readCnt == ) {
        return SPI_FLASH_ERR_PARA;
    }

    // 校正要读的数据总量
    if (readAddr + readCnt >= SPI_FLASH_SIZE) {
        readCnt = SPI_FLASH_SIZE - readAddr;
    }

    // 将地址转换为字节数组
    addr[] = (uint8)(readAddr >> );
    addr[] = (uint8)(readAddr >> );
    addr[] = (uint8)(readAddr & 0xff);

    // 等待SPI Flash完成写操作
    while (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BUSY );

    SPIFlashSelect();
    {
        // 发送低速读命令0x3,3字节地址,dummy字节
        SPIWriteReadByte(0xB);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(0xff);

        // 依次读readCnt个数据
        ; i < readCnt; i++) {
            readBuf[i] = SPIWriteReadByte(0xff);
        }
    }
    SPIFlashDeSelect();

    return i;
}

/*********************************************************************************************************
** Function name: SPIFlashWriteByte
** Descriptions: 向SPI Flash指定地址处写一字节数据
** Input parameters: writeAddr 写入的地址
** udata 写入的值
** Output parameters: none
** Returned value: none
** Notes: 写之前必须注意到写保护的存储影响
*********************************************************************************************************/
uint32 SPIFlashWriteByte (uint32 writeAddr, uint8 uByte)
{
    uint8 addr[];

    // 检查写地址是否越界
    if (writeAddr >= SPI_FLASH_SIZE) {
        return SPI_FLASH_ERR_PARA;
    }

    // 将地址转换为字节数组
    addr[] = (uint8)(writeAddr >> );
    addr[] = (uint8)(writeAddr >> );
    addr[] = (uint8)(writeAddr & 0xff);

    // 等待SPI Flash完成写操作
    while (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BUSY );

    // 发送写使能命令
    SPIFlashSelect();
    {
        SPIWriteReadByte(0x06);
    }
    SPIFlashDeSelect();

    // 写入实际要写入的数据
    SPIFlashSelect();
    {
        // 发送低速读命令0x3,3字节地址,写入的字节
        SPIWriteReadByte(0x2);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(uByte);
    }
    SPIFlashDeSelect();

    return SPI_FLASH_OK;
}

/*********************************************************************************************************
** Function name: SPIFlashFastWrite
** Descriptions: 以地址自增方式向指定FLASH地址处连续写字数据
** Input parameters: writeAddr 写入的起始地址
** writeBuferr 写数据存储的缓冲区
** uWord 写入的数据量,以字为单位
** Output parameters: none
** Returned value: none
** Notes: 写之前必须注意到写保护的存储影响
*********************************************************************************************************/
uint32 SPIFlashFastWrite (uint32 writeAddr, uint16 * writeBuferr, uint16 uWord)
{
    uint16 i;
    uint8 addr[];

     // 检查参数
    if (writeAddr >= SPI_FLASH_SIZE ||
        writeBuferr ==  ||
        uWord == ) {
        return SPI_FLASH_ERR_PARA;
    }

    // 检查写地址是否越界
    ) >= SPI_FLASH_SIZE) {
        uWord = (SPI_FLASH_SIZE - writeAddr) >> ;
    }

    // 将地址转换为字节数组
    addr[] = (uint8)(writeAddr >> );
    addr[] = (uint8)(writeAddr >> );
    addr[] = (uint8)(writeAddr & 0xff);

    // 等待SPI Flash完成写操作
    while (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BUSY );

    // 发送写使能命令
    SPIFlashSelect();
    {
        SPIWriteReadByte(0x06);
    }
    SPIFlashDeSelect();

    // 发送低速读命令0xAD,3字节地址,写入的字节
    SPIFlashSelect();
    {
        SPIWriteReadByte(0xAD);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(addr[]);
        SPIWriteReadByte(writeBuferr[] >> 0x08);
        SPIWriteReadByte(writeBuferr[] & 0xFF);
    }
    SPIFlashDeSelect();

    // 发送其它字节
    ; i < uWord; i++) {
        // 等待SPI Flash完成写操作
        while (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BUSY );

        SPIFlashSelect();
        {
           // 发送引导命令和编程字数据
            SPIWriteReadByte(0xAD);
            SPIWriteReadByte(writeBuferr[i] >> 0x08);
            SPIWriteReadByte(writeBuferr[i] & 0xFF);
        }
        SPIFlashDeSelect();
   } 

    // 等待SPI Flash完成写操作
    while (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BUSY );

    // 发送写禁能命令,退出该模式
    SPIFlashSelect();
    {
        SPIWriteReadByte(0x04);
    }
    SPIFlashDeSelect();

    return SPI_FLASH_OK;
}

/*********************************************************************************************************
** Function name: SPIFlashChipErase
** Descriptions: 擦除整块芯片
** Input parameters: none
** Output parameters: none
** Returned value: none
** Note: 如果sectorAaddr
*********************************************************************************************************/
void SPIFlashErase (uint8 eraseType, uint32 eraseAddr)
{
    uint8 addr[];

    // 等待SPI Flash完成写操作
    while (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BUSY );

    // 发送写使能命令
    SPIFlashSelect();
    {
        SPIWriteReadByte(0x06);
    }
    SPIFlashDeSelect();

    // 根据类型选择擦除方式
    switch (eraseType) {
        // 选择整片擦除方式
        case SPI_FLASH_ERASE_CHIP:
            SPIFlashSelect();
            {
                SPIWriteReadByte(0x60);
            }
            SPIFlashDeSelect();
            break;

        // 扇区擦除方式
        case SPI_FLASH_ERASE_SECTOR:
            if (eraseAddr < SPI_FLASH_SIZE) {
                // 将地址转换为字节数组
                addr[] = (uint8)(eraseAddr >> );
                addr[] = (uint8)(eraseAddr >> );
                addr[] = (uint8)(eraseAddr & 0xff);

                // 发送扇区擦除命令,擦除的扇区地址
                SPIFlashSelect();
                {
                    SPIWriteReadByte(0x20);
                    SPIWriteReadByte(addr[]);
                    SPIWriteReadByte(addr[]);
                    SPIWriteReadByte(addr[]);
                }
                SPIFlashDeSelect();
            }
            break;

        // 32K块擦除方式
        case SPI_FLASH_ERASE_BLOCK:
            if (eraseAddr < SPI_FLASH_SIZE) {
                // 将地址转换为字节数组
                addr[] = (uint8)(eraseAddr >> );
                addr[] = (uint8)(eraseAddr >> );
                addr[] = (uint8)(eraseAddr & 0xff);

                // 发送块擦除命令,擦除的块地址
                SPIFlashSelect();
                {
                    SPIWriteReadByte(0x52);
                    SPIWriteReadByte(addr[]);
                    SPIWriteReadByte(addr[]);
                    SPIWriteReadByte(addr[]);
                }
                SPIFlashDeSelect();
            }
            break;

        default:
            break;
    }

}

/*********************************************************************************************************
** Function name: SPIFlashSetProtection
** Descriptions: 设定SPI存储器的保护模式,加保护或解保护
** Input parameters: isProtect 保护的模式,1--加保护, 0 -- 解保护
** startAddr 保护区域的起始地址
** stopAddr 保护区域的结束地址
** Output parameters: 0 -- 操作成功, 1 -- 操作失败(当为解保护时,硬件保护阻止了解保护)
** Returned value: none
*********************************************************************************************************/
uint32 SPIFlashSetProtection (uint8 isProtect, uint32 startAddr, uint32 stopAddr)
{
    uint8 BPXMask;
    uint8 status;

    // 等待SPI Flash完成写操作
    while (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BUSY );

    if (isProtect) {
        // 清除所有的保护位
        SPIFlashWritestatusReg();

        // 如果BPL只读,即不可更改BPX位
        if (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BPL) {

            // 当该区域已经加保护时,正确返回
            if ((status & SPI_FLASH_REG_BIT_BPX) > BPXMask) {
                ;
            } else {
                // 当未加保护时,返回错误,不可更改保护模式
                ;
            }

        } else {
            // 计算保护模式位
            if (startAddr > SPI_FLASH_SIZE) {
                ;
            } else if (startAddr >= 0xF0000) {
                BPXMask = ;
            } else if (startAddr >= 0xE0000) {
                BPXMask = ;
            } else if (startAddr >= 0xC0000) {
                BPXMask = ;
            } else if (startAddr >= 0x80000) {
                BPXMask = ;
            } else {
                BPXMask = ;
            }

            // BPL写读写,此时加上保护位即可,但不锁定BPL,以妨不可恢复
            SPIFlashWritestatusReg(BPXMask);

            ;
        }
    } else {
        // 解除保护,写BPL位为0,解除保护
        SPIFlashWritestatusReg();

        // 读保护位,如果值不为全0,则可能硬件加保护,解保护失败
        if (SPIFlashReadstatusReg() & SPI_FLASH_REG_BIT_BPX) {
            ;
        } else {
            ;
        }
    }
}

/* -------------------------------------------------- 测试代码 ---------------------------------------*/
uint32 id;
uint8 writeBuffer[];
uint8 readBuffer[];
uint8 status;

#define SPI_FLASH_SECTOR_SIZE (1024*4)
#define SPI_FLASH_BLOCK_SIZE (1024*32)

void SPIFlashTest (void)
{
    uint32 i, j;

    // 初始化SPI控制器
    SPIFlashInit();

    // 读ID测试,值应为0x00BF258E
    id = SPIFlashReadID();
    if (id != 0x00BF258E) {
        return;
    }

    // 先解除保护才可写
    SPIFlashSetProtection(, 0xF0000, 0xFFFFF);

    // 整片擦除测试
    SPIFlashErase(SPI_FLASH_ERASE_CHIP, );
    ; i < SPI_FLASH_SIZE / sizeof(readBuffer); i++) {
        SPIFlashRead(i * sizeof(readBuffer), readBuffer, sizeof(readBuffer));
        ; j < sizeof(readBuffer); j++) {
            if (readBuffer[j] != 0xff) {
                return;
            }
        }
    }

    // 字节写和读测试
    ; i < SPI_FLASH_SIZE; i++) {
        SPIFlashWriteByte(i, i);
        SPIFlashRead (i, readBuffer, );
        ] != (i & 0xff)) {
            return;
        }
    }

    // 扇区擦除测试
    ; i < SPI_FLASH_SIZE / (*); i++) {
        SPIFlashErase(SPI_FLASH_ERASE_SECTOR, i * (*));
    }
    ; i < SPI_FLASH_SIZE / sizeof(readBuffer); i++) {
        SPIFlashRead(i * sizeof(readBuffer), readBuffer, sizeof(readBuffer));
        ; j < sizeof(readBuffer); j++) {
            if (readBuffer[j] != 0xff) {
                return;
            }
        }
    }

    // 快速写测试
    ; i < SPI_FLASH_SIZE / sizeof(writeBuffer); i++) {
        ; j < sizeof(writeBuffer); j++) {
            writeBuffer[j] = j;
        }
        SPIFlashFastWrite( i * );
        SPIFlashFastRead ( i * sizeof(writeBuffer), (uint8 *)readBuffer, sizeof(readBuffer));

        // 交换字节顺序再比较
        ; j < ; j++) {
            uint16 * ptr = (uint16 *)&readBuffer[j << ];
            *ptr = ((*ptr & ) | (*ptr >> );
        }
        ) {
            return;
        }
    }

    // 扇区擦除测试
    ; i < SPI_FLASH_SIZE / (*); i++) {
        SPIFlashErase(SPI_FLASH_ERASE_BLOCK, i * (*));
    }
    ; i < SPI_FLASH_SIZE / sizeof(readBuffer); i++) {
        SPIFlashRead(i * sizeof(readBuffer), readBuffer, sizeof(readBuffer));
        ; j < sizeof(readBuffer); j++) {
            if (readBuffer[j] != 0xff) {
                return;
            }
        }
    }

    // 保护测试
    SPIFlashSetProtection(, 0xF0000, 0xFFFFF);
    SPIFlashSetProtection(, 0x80000, 0xFFFFF);
    SPIFlashSetProtection(, 0xF0000, 0xFFFFF);
}

FLASH 存储学习-串行SPI nor的更多相关文章

  1. FLASH 存储学习-串行SPI NOR FLASH

    1.1 SST25VF080B简介1.1.1 主要特性 关键点:容量.速度(时钟速度.读写速度).功耗. l 容量:8MBit: l 最高SPI时钟频率:50MHz: l 低功耗模式下电流消耗:5uA ...

  2. flash读写学习笔记与spi接口及简单测试验证(三)

    FPGA中的视频图像资源,以及想要永久存储的程序都是要存储在flash中,flash是FPGA一个不可缺少的部分,flash的种类有很多,根据winbond公司的128Mbit Qual SPI接口的 ...

  3. STM32-串行SPI nor

    源:FLASH 存储学习-串行SPI nor 1.1 SST25VF080B简介1.1.1 主要特性 关键点:容量.速度(时钟速度.读写速度).功耗. l 容量:8MBit: l 最高SPI时钟频率: ...

  4. 痞子衡嵌入式:串行NOR Flash的DQS信号功能简介

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是串行NOR Flash的DQS信号功能. 串行NOR Flash在嵌入式里的应用相当广泛,既可用作数据存储也可以用作代码(XiP)存储, ...

  5. 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU硬件那些事(2.2)- 在串行NOR Flash XIP调试原理

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列EVK在串行NOR Flash调试的原理. 本文是i.MXRT硬件那些事系列第二篇的续集,在第二篇首集 ...

  6. 玩转X-CTR100 l STM32F4 l W25Q64 SPI串行FLASH存储

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]      本文介绍X-CTR100控制器 板载FLA ...

  7. 第24章 SPI—读写串行FLASH—零死角玩转STM32-F429系列

    第24章     SPI—读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...

  8. STM32学习笔记——SPI串行通讯(向原子哥学习)

    一.SPI  简介 SPI是 Serial Peripheral interface 的缩写,就是串行外围设备接口.SPI 接口主要应用在  EEPROM, FLASH,实时时钟,AD 转换器,还有数 ...

  9. SPI—读写串行 FLASH

    SPI协议简介SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC. LCD ...

随机推荐

  1. poj2409 Let it Bead

                                                                      Let it Bead Time Limit: 1000MS   M ...

  2. 一键安装IIS的点点滴滴——For所有Microsoft的操作系统(下)

    原文 http://www.cnblogs.com/cdts_change/archive/2010/03/09/1681392.html 接着上一篇的讲,下面我们将讨论Windows7.Window ...

  3. jQuery.trim(str)

    描述: 去掉字符串起始和结尾的空格. jQuery 代码: $.trim(" hello, how are you? "); 结果: "hello, how are yo ...

  4. 【转】Android下编译jni库的二种方法(含示例)

    原文网址:http://blog.sina.com.cn/s/blog_3e3fcadd01011384.html 总结如下:两种方法是:1)使用Android源码中的Make系统2)使用NDK(从N ...

  5. thinkjs初试

    背景          什么是thinkjs?thinkjs是奇舞团开源的一款NodejsMVC框架,该框架底层基于Promise来实现,很好的解决了Nodejs里异步回调的问题.我为什么会使用thi ...

  6. JS中简单的this学习

        我在学习JS初期,在使用this的时候经常出现问题,当然就是在现在,也有一些场景不能很好的明白this到底指代的是什么?看下面一个例子:   var x = 10; var foo = { x ...

  7. Eclipse使用之杂七杂八

    使用Eclipse的Marketplace安装1.12x版本的Subclipse插件(SVN)后,新建SVN资源库时出现如下报错: “Can't create session svn: Unable ...

  8. Linux如何生成列表

    如何生成列表: 方法一:{1..100} 方法二:`seq [起始数 [步进长度]] 结束数` 1,...,100 declare -i SUM=0    integer    -x

  9. Live555 分析(二):服务端

    live555支持单播和组播,我们先分析单播的流媒体服务端,后面分析组播的流媒体服务端. 一.单播的流媒体服务端: // Create the RTSP server: RTSPServer* rts ...

  10. ssh登录失败处理步骤

    如果登录失败而又找不到显示的原因,优先使用ssh -vT name@ip -p port 进行调试,查看所使用的key文件.ip.端口是否正确.然后再检查下面步骤:1.检查在对应用户名下是否有iden ...