AT45DB161D
《SPI Flash兼容性小结》
小结一下SPIFlash,以便更好地兼容更多的SPIFlash
首先从命令上:
常用的,SPIFlash都支持的,并且不同厂家都共有的命令有:
01 写状态寄存器
02 写
03 读
05 读状态寄存器
06 写使能
D8 擦除
在读FlashID上,不同厂家支持的命令略有不同,但一般可以通过以下四条命令进行尝试,来确定Flash的厂家及型号:
9F AB 90 15
在处理兼容性的过程中,最多的就是处理写命令。对于Flash来说,有Page-Program,有Byte-Program等。不同厂家对此的支持不同,有一些Page-Program还要求必须以2Byte的整数倍来进行编程。
其次,就是去除写保护了。有些Flash在上电的时候是写保护的,如果需要进行写操作,则需要对状态寄存器进行操作。
在写完状态寄存器后,最后能够WaitBusy,并且读取状态寄存器以确保顺利写入。
再次,就是写状态寄存器之前是否需要写状态寄存器使能了。部分Flash需要,写状态寄存器使能的命令为50。
总之,仔细阅读好厂家给的,或网上下载的SPIFlash的SPEC,SPIFLASH的兼容性应该是没有太大的问题的。
——————————————————————————————————————————————
《读写SPI接口Flash(AT45DB161D)》
这个任务是读写SPI接口FM1702的前续任务,因为读写FM1702相对复杂,所以先从读写Flash开始,刚刚接到这个任务以为很简单,至少没有FM1702那么复杂,结果发现我错了,其实读写FLASH并没有那么简单,主要的难处在于:没有可行的参考程序资料,在买来的开发板的例程中的SPI接口Flash程序是错误的,首先接口不对应,其次程序读写完全不对,像以前那样的调试办法变得不可行,我不能依赖于别人的基本正确的程序,然后加上适合自己的程序的代码,所以我只能上网查程序,开始我还是寄望于能够找到一个可以基本一直的程序,后来发现我错了,其实我根本都还没有了解Flash的内部结构,就想移植别人的读写程序是很不现实的,即使移植了也只是移植了一个躯壳,完全不明白其中的道理,因为急于移植导致的问题是:浪费宝贵的调试时间,只是一味的复制黏贴一些代码,但是对调试进程毫无帮助。不过一个造成这个局面的主要原因是:flash的资料很少,而且都是英文,虽然找了大量的资料但是对flash的了解没有上升到一个层次,直到后来看了一篇资料才决定自己来看英文资料,从中寻找突破口,再后来出现了一篇关于AT45DB642的中文资料,都是flash而且一些操作也大相径庭,根据这两份资料的配合,我慢慢了解了flash的内部接口和一些操作方法,主要是一些读写的时序!然后结合网上下载的程序,我开始着手修改成适用于Arm7的flash读写程序。注意:程序修改中时序的配合很重要很重要!时序正确以后一般读写的就没有问题了,最开始我先判断了标志寄存器,这个的正常是全部程序的突破口,是我找到成就感的关键,标志寄存器正常表示程序的读写子程序没有问题,接着读写了buff1,这个不是掉电保护的,在上电的情况下正常通过了读写,后来我把buff1的值存入主存,然后断电后上电连续读,结果也正常,这样说明我已经可以正常的操作flash了。不过现在的操作只是一个模拟IO口的过程,但是这个通过后说明已经完成了一大半,毕竟SPI的时序我已经测试正常了,flash的SPI读写只是个时间问题,下面就去完成SPI的操作。
经过一个小时左右的努力,SPI接口的FLASH读写通过了,主要要注意的东西:一个是SPI接口的初始化,设置时钟频率以及设置SPCR寄存器的主机模式以及SCK的有效电平、还有要注意的是时序上的配合,CS的高低电平控制数据有有效和无效(这个是IO口转换过来最重要的)除了读写的子程序其他程序不需要修改,在调试整个读写过程中先从简单的开始:我是先读标志寄存器,如果这个读出来没有问题的话说明读写子程序没有问题,只要确定了读写子程序没有问题,其他程序只要调用就可以了,也就是从IO口过来,我只改了下读写的子程序以及SPI的初始化(设置一个时钟频率和一个SPI的开启寄存器)。
(12月9日)在自己设计的ARM7核心板上,我调试了FLASH读写,发现FLASH的内存大小的正确含义,所谓AT45DB16中的16不是16Mbyte的意思,而是16Mbit,也就是只有2Mbyte,有点欺骗人的意思,他内存的组织结构是由4096页*528byte组成,(12月10日)写FLASH的时候有一点需要知道:比如你要写满整个FLASH,那么你写的是0—4095页,如果你写的是第0和第1页,那么读出的时候页0的地址和页4096的地址是同一个,同理页1的地址和页4097是同一个地址,具体看程序的实现。
《AT45DB系列SPI FLASH介绍》
说到SPI接口的存储芯片,一般不得不说到ATMEL的AT45DB,这个系列的Flash芯片比较全面。
从AT45DB011D(1Mbit)、AT45DB021D(2Mbit)、AT45DB041D(4Mbit)、AT45DB081D(8Mbit)、AT45DB161D(16Mbit)、AT45DB321D(32Mbit)、AT45DB642D(64Mbit)全系列都有,从供货情况来看,041D、161D、321C、641D这几款的供货情况不错,而041D的千片价格可以做到5~7元,161D的千片价格在8元左右。其中011D~041D都是264字节Page的,161D和321D是528字节Page,642D是1056字节Page的。
-
写数据,因为是SPI口操作,所以难免偶尔出现低概率的干扰,但是还是出影响数据,若是关键性的数据,那就完蛋了。所以俺先将要写入的页面数据写入BUF1,然后写入将BUF1写入Flash的命令。在Flash编程的同时,我将同样的数据写入BUF2,等待BUF1编程完毕,将BUF2的数据与Flash页面中的数据进行比较,如出错,则重新写入,若无误,说明SPI线传输正确。
-
读数据,因为我在附加字节中加入了ECC,所以每入读入系统内部RAM之后,都对ECC进行校验,如出错,说明Flash页面损坏或SPI读过程中出现外部干扰,此时可再读一次,如连续读入三次均出错,说明页面损坏,不过我还没有遇到这样的情况。
AT45DB652D内部是分页的,您可以按页来读取,该Flash芯片是SPI接口的,建议读取Flash时,使用DMA读取,否则这高速DataFlash就看不出高速了。
通过串口发出的时候,也是按包来封装,可以1页分成若干个若,我们建议串口单次连续发送的数据不要超过256字节,加上辅助字节,最好不要超过300字节。而且需要加上校验和重发机制。
建议读流程如下:
1. 上位机将需要的页号或多个页号发给STM32
2. STM32启动SPI操作,逐页读取,并采取先进先出的方式保存在一个FIFO缓冲区中,该缓冲区以页大小为单位
3. 通过串口拼包发出。
DMA是怎么进行操作的?DMA控制器直接从外部flash里读取数据,传送给串口?
STM32官方网站上是有DMA操作例程的。
其实就是SPI的单次操作完成的中断信号不用于引起中断程序的运行,而是直接去驱动DMA的一次操作;多个这样的操作,就形成了一个块的DMA操作了
就是通过DMA控制器来对SPI flash进行读取操作,从SPI读到的数据存放到一个FIFO缓冲区(这个缓冲区是STM32的RAM吧?)然后再拼包发送到串口