最近由于很少写代码感觉自己变得菜的不要不要的,心里很是内疚,姑且写篇博客安慰下自己。
将以前写的spi接口配置Flash芯片从入手到仿真详细阐述一下吧。
1、项目接手我使用的芯片为M25P16Flash芯片,该款芯片首页如下:
从首页中我标红部分可以看到:该款Flash容量为16Mbit,兼容Spi总线接口,最大时钟频率可以达到50Mhz,超过10万次的擦除写入次数,长达20年的数据保存周期。
一页里面有256个字节,一个扇区里面有512kbit。
以该款芯片为例,讲解SPI总线接口的应用。
其实到这里我刚接手也是很迷茫,到底什么是页、什么是扇区、Flash内部结构到底是怎样的呢?下面我以一张图为大家详细展示。
从上图中可以看到Flash内部分为扇区-页-字节,Flash先把整块存储器件划分为多个扇区、再把扇区分为页,再把页分为字节,根据首页介绍一页里面即一个Page里面有256个字节,根据首页一个扇区里面有512Kbit折算下来一个扇区里面有256页,具体计算过程如下:
(512kbit x1024)/(256 x8) = 256页
根据首页介绍整块Flash容量为16Mbit,对它进行扇区计算,也就是说该款Flash总共有32个扇区,具体计算过程如下:
(16bit x1024Kbit)/(512Kbit) = 32扇区
到这里我们就很清楚了,这款Flash总共有32个扇区,每个扇区里面有256页,每页里面有256字节等。
Flash内部进行数据存储都是基于字节进行存储的,也就是说它的一个地址里面存的数据其实就是一个字节,8个bit。
那么如果说想对这款Flash进行写入或者读取的话,应该怎么做呢?寻址方式应该是怎么样的呢?
应该是这样的,我们首先要确定扇区地址,再确定页地址,再确定对该页哪一个字节进行操作,也就是说寻址方式首先要确定扇区,再确定页,之后再确定字节。
那如果说对该款Flash用上述方式进行寻址,总共需要多少个数据来表示地址呢?即计数器位宽应该是多少?总共是32个扇区,理论上需要5个bit来表示32个扇区的信息,扇区里面有256页,理论上需要8个bit来表示页地址,页里面有256个字节,理论上也需要8个bit,这样算下来扇区地址5个bit,页地址8个bit,字节地址8个bit,总共需要21个bit的数据来表示地址信息。
以上便是关于该款Flash的粗略介绍,以下介绍SPI总线。
2、SPI总线介绍
以FPGA和板级Flash芯片为例,简单介绍SPI总线的连接方式。
察看芯片手册对这四根信号的具体描述:
对SDO信号描述如下:
该信号为Flash数据输出端口,数据是在串行时钟的下降沿改变。(建议先不要纠结上升沿,下降沿这些,具体看时序图)
对SDI信号描述如下:
该信号是用来向Flash器件传输数据,该信号可以为指令、地址、及写入到Flash中的数据,改管脚上的值是在串行时钟的上升沿锁存。
SCLK信号描述如下:
该信号为串行接口提供时序,在SDI管脚上出现的指令、地址、数据会在串行时钟的上升沿锁存,SDO数据输出端口会在时钟下降沿改变。
CS片选信号描述如下:
改信号当其被置高时,该款芯片没有被选中,串行数据输出端口会处于高阻状态,如果想在上电之后执行任何指令都必须把片选信号拉低。
这里使用的是四线制的SPI接口,三线制数据输入输出用一根信号传输,其它两个信号与四线制作用一致。三线制的SPI有点类似与IIC。
以上便是芯片手册对这四根信号的简单介绍。
3、下面详细阐述如何通过SPI接口来操作该款Flash芯片。
去应用Flash其实无非就是怎么样把数据写入到Flash里面,怎么从Flash里面把数据读出来。
操作Flash是通过SPI接口写入相应的指令才能让Flash按照指令代码去执行相应的操作,该款Flash指令代码表格察看芯片手册如下:
如果说现在要对该款Flash进行写操作,需要执行Page program即页编程操作指令,简称PP。
现在来看一下PP的指令介绍:
红色划出部分描述:PP指令允许字节写入到存储器件中,写操作在Flash内部bit跳转其实是从1变到0。当该指令被执行之前,一个写使能指令必须要被提前执行。通过以上描述我们知道页写指令可以把Flash内部数据从1变到0,但是如果现在有这样一种场景,即字节地址里面原来的数据全为0,但是现在需要向该字节地址写入一个0F的数据,是否可以正确写入呢?
分析:因为写入的时候只能从1变到0,如果内部的数据本来已经是0,但是现在需要写入一个1,那么该数据是不会被正确写入的!!
还有一个是在执行页写指令之前还需要执行一个写使能指令,那还是刚才的问题,如果内部的数据为0,还需要向其写入1,怎么把数据正确写入到里面呢?其实很简单,需要首先执行一个擦除指令,擦除指令的目的会把Flash内部的数据全部都变成1,也就是会把0也变成1。
说到擦除,下来看一下芯片手册的擦除指令。
扇区擦除指令会把所选择扇区里面的所有Bit都设置为1,在该指令执行之前,一个写使能指令必须被提前执行,也就说在扇区擦除指令之前,还需要执行写使能指令。
既然在PP页写指令介绍时,也提到了写使能指令,那么我们详细看一下写使能指令。
在写使能指令介绍里面提到,在执行Page Progam(页写指令) 及SE(扇区擦除指令)之前需要执行写使能指令。
那么写使能指令是通过什么方式操作的呢?有这样一段详细描述:
即写使能指令执行的具体操作是先把片选信号拉低,再发送写使能指令代码,然后再把片选信号拉高,从下面时序图也可以看出。
该时序图第一个信号为片选,在执行写使能指令的整个周期里面是把片选信号拉低的,第二个信号为串行时钟,第三个信号为数据输入管脚,即SDI,简单看一下,从时钟0开始数,在第五第六这两个时钟周期是为高,其余时钟沿为低。所以可以看出写使能指令码为:8‘b00000_0110即06h对比上面的指令码表验证理解正确。第四个信号为Flash芯片数据输出端口,可以看到,在执行写使能指令器件,该管脚处于高阻态。
至此,我们已经明白要对Flash执行写操作需要四个阶段:
1:执行写使能指令
2:执行扇区擦除指令
3:执行写使能指令
4:执行页写指令
那么现在看一下扇区擦除指令的详细描述:
有了经验之后,我们也没必要每次都看描述了,我们来具体看看时序,在执行扇区擦除指令也是相应的先把片选信号拉低,相应的提供时钟,然后再执行相应的指令,从图中可以看出,执行擦除指令其实分为了两个部分,第一部分先给出相应的擦除指令代码:D8h,之后再提供24bit的地址信号,哪这里面出现一个问题,为什么扇区擦除需要24bit的地址,我们之前计算出的寻址仅仅用到21位啊,问题很简单,在上图左下角有一个注释,该注释说的是,A23到A21为不关心,即我们只需要保证低21个bit是有效的就行了。
下面将写使能和扇区擦除为一个例子来说明,在FPGA里面怎么去实现对Flash的擦除操作。
使用Time Gen 软件我绘制了一个时序图。
在该时序图中,我提供了一个Se_trig即擦除的触发信号,当该触发信号到来时,FPGA内部会把work_flag拉高,拉高之后计数器会相应的进行计数,相应的SPI总线信号会根据计数器进行工作,在扇区擦除指令之前会先给出写使能指令,即前八个时钟周期是先给出写使能指令,即对应图中片选拉低的第一阶段先执行写使能指令06h,在计数器计数到8时,拉高片选,代表写使能指令执行完毕。
当计数器为9时把片选信号保持一个时钟周期的高电平,之后在计数器从9变到10把片选信号拉低,目的是为了执行扇区擦除指令D8h,进接着24bit地址,以6'h000_000即第零个扇区擦除为例。
由于时间问题,暂且写到这里,后续补上根据时序图实现的代码,及仿真截图。