如何写入SPI闪存?


9

我正在开发一个音频应用程序,而不是将音频数据存储在SD卡(Arduino 上的Waveshield)上,而是将其存储在SPI闪存IC上,并使用MCU,DAC和放大器滚动自己的电路板。

我正在使用Winbond W25Q80BVSSIG

我对使用AVRISP mkIIUSBTiny编程AVR非常熟悉,是使用同一程序员将数据写入闪存吗?在专门寻找SPI闪存编程器时,我一直找不到任何东西。

这个问题是一个跟进这一个


我不知道是否有一个程序员可以专门从PC或其他设备上轻松地为您完成此任务,但是如果电路中包含CPLD,则可以配置为将数据写入闪存。
deed02392

我认为spi闪存模块现在已经设计用于存储大多数PC上cpu使用的固件/ BIOS。不适用于健壮的存储设备。
元帅飞行器

Answers:


12

如果您只是在寻找一种用“预加载”数据对Winbond SPI闪存进行编程的方法,您的微控制器将在运行时读取这些数据以供使用,那么您需要考虑的是可以进行在线编程的程序员SPI Flash芯片。这也称为系统内编程(ISP)。

一种选择是DediProg程序员。如果正确设计电路板,则此USB连接的设备可以在电路中编程。他们甚至出售可插入SOW-16封装的适配器夹,而无需在板上的单独编程头中进行设计。DediProg提供了应用信息公告,可帮助您正确设计电路中使用的产品。设计的主要策略是找到一种隔离MCU系统中SPI接口驱动程序的简单方法,以使它们不干扰SPI编程容器中的驱动程序。最简单的方法是在MCU和SPI Flash之间的MCU驱动线路中放置串联电阻。编程器将连接在串联电阻的SPI闪存侧。替代方法可以包括在驱动接口线中添加MUX或模拟开关。一个更聪明的方案是添加一个“

在此处输入图片说明

还需要考虑的第二个选择是ASIX的USB编程器。Presto能够执行各种类型的SPI和I 2 C设备,包括SPI Flash设备。我拥有这些设备之一,专门用于对Atmel MCU和各种类型的SPI Flash设备进行编程。与上述单元相比,它是一种更具成本效益的解决方案,但不够灵活。他们更昂贵的设备Forte可以执行更多操作,因为它具有更多目标接口引脚。

在此处输入图片说明

有时将编程器连接到目标板而不需要添加编程头可能是有益的。一个不错的解决方案是将一小组焊盘放在一个名为TagConnect的公司定义的特殊尺寸上。他们制造和销售一系列快速连接编程电缆,这些电缆具有弹簧针,这些弹簧针与电路板上的特殊引脚接合。该电缆有6针,10针和14针版本,可适合各种应用。电缆的成本非常合理。

在此处输入图片说明


这非常有帮助。我计划在将闪存焊接到最终PCB之前对闪存进行编程。到目前为止,我已经为MCU做到了这一点,并且效果很好。我不确定在PCB上提供ISP引脚是否是一个好主意,因为一旦完成,就不应该对其进行重新编程。
JYelton

1
@JYelton-根据我的经验,为ISP计划是一个好主意,原因有几个。ECO(工程变更单)是产品周期中不可或缺的事实。投入生产后,某些人或某些人将要求更改Flash内容。闪存芯片有时容易受到电路中意外噪声干扰的影响,并最终损害其内容。提供ISP的另一个原因。
Michael Karas

1
是否有至少通过捆绑的适配器电缆与大多数这些编程器兼容的“标准”接头连接器?我见过2x4和2x5引脚接头连接器以及许多不同的引脚分配。另请参见flashrom.org/Supported_hardware
kert 2014年

每个人都有自己合理的想法。Tag连接电缆为$ 35〜$ 40。
markrages

1
@markrages-但是对于给定的开发实验室或工厂编程站,您只需购买一根电缆。您不需要为每个产品都装一个。另外,这些电缆要便宜得多,以至于尝试使用自己的pogo-pin夹具来允许ISP不使用连接器。
Michael Karas 2015年

8

我敢打赌,您可以使用Bus Pirate来完成此任务,而无需通过您的MCU ...这可以让您使用SPI,I2C或UART通信直接对芯片进行任意的串行交互。“编写”脚本可能需要一些工作,但它可能会让您完成工作。

我也看到了专门的工具,可通过I2C直接加载EEPROM,但没有闪存和SPI。


我开始怀疑我选择的SPI闪存是否是一个好的选择,考虑到(显然)这些方法对被炸的东西的写法是多么的晦涩。
JYelton

1
那将需要一些认真的脚本编写,但是无论如何都是个好主意。我的口味有点复杂。也许您应该考虑使用SD卡?然后,您只需要在乎阅读,用电脑写就可以了
chwi 2012年

当前的原型使用Arduino和Waveshield(具有SD卡读取器)。我想摆脱SD卡的困扰,因为我相信这样做的费用会更少(没有读卡器和存储卡),并且可以防止篡改。
耶尔顿

7

我从未听说过有其他工具可以将SPI直接与这种芯片相连,而且我认为这是不可能的,因为“所有”芯片需要不同的调用来执行不同的操作。

该芯片需要SPI调用来进行写入,读取,更改扇区,数据大小等。在数据手册的7.2指令章节下,您可以看到可以发送给它的所有SPI命令。因此,由于所有外部闪存都不具有相同的指令集,因此您需要为此编写一个定制的应用程序。

编辑:作为后续工作,我真的会推荐Atmels自己的SPI闪存之一,因为其中大多数已经为它们编写了开放的可用代码。看这篇文章AVRFreaks将为您提供一些的爱特梅尔AT45xxxx串行闪存芯片的代码。


如果我理解正确,我应该为我的MCU编写程序,然后将数据写入闪存吗?问题是MCU的内存少于外部闪存,因此我有些茫然。
JYelton

是。您可以使用UART从计算机串行线发送数据,并将其写入闪存。另外,您可以为MCU编写多个程序,一次对闪存进行一些编程。这可能会花费一些时间,但它会起作用,因为只要您正确地跟踪更改的扇区,外部闪存就不会被擦除
chwi 2012年

2
这是正确的答案。因此,您需要在PC上有一个程序将块下载到MCU,然后将其写入闪存。如果存在错误检查并且您不必在PC上编写新程序,则它会有所帮助。所以我建议您找到一些XMODEM或类似代码。
pjc50

@ pjc50 ...声明“正确答案”不是那么快:)
vicatcu 2012年

实际上,许多程序员都可以对闪存进行编程。atmel micros常用的一种编程方案与SPI十分接近。
克里斯·斯特拉顿

4

我从嵌入式计算机公司购买了一个“ FlashCAT ”编程器,价格约为30美元。通过USB连接到PC并将文件写入Winbond闪存非常容易。其他答案中的方法和程序员可能都一样好,价格也更高,或者自己动手做,但这是一种便宜又简单的方法,适合我的需求。

这是设置的图片:

使用FlashCAT编程

FlashCAT编程器位于左侧,已连接到USB。它正在运行SPI编程固件(与JTAG相对),并为闪存供电。可用跳线选择提供的电源(3.3V或5V)。

我在试验板上有一个SOIC到DIP插座,可以很容易地对多个芯片进行编程。(您还可以看到面包板上也有另一个闪存IC。)

FlashCAT软件

我还没有将音频文件转换为正确的二进制格式,但是我将211KB WAV文件写到内存中只是为了进行测试,如上图所示。然后,我将其读回并保存为新文件,将其重命名为.wav,然后在PC上正确播放。

下一步将是正确编码文件,并编写AVR软件以读取数据并通过DAC发送。

免责声明:我不隶属于嵌入式计算机,我只是一个选择便宜东西并分享有关产品使用体验信息的客户。


4

讨论有点晚了,但是对于任何在搜索后阅读它的人来说都是如此。

我没有提到的一件事,对SPI Flash芯片进行编程绝对关键是控制片选(CS_)引脚。片选引脚用于将命令标点到SPI Flash。特别是,从CS_高到CS_低的过渡必须紧接在任何写操作操作码(WREN,BE,SE,PP)发布之前。如果在CS_转换之间(即CS_变低之后)到发送写操作码之前有活动,通常将忽略写操作码。

另外,由于它是SPI协议的固有组成部分(也是至关重要的),因此在SPI Flash数据表中通常没有解释的是,在SPI总线上传输的每个字节中,每个字节都会返回一个字节。同样,除非发送一个字节,否则不能接收任何字节。

通常,用户命令的SPI主控器具有一个发送缓冲区和一个接收缓冲区,该缓冲区在SPI总线的MOSI线上发送字节,而接收缓冲区从SPI总线的MISO线接收字节。

为了使任何数据出现在接收缓冲区中,必须已将某些数据发送出发送缓冲区。同样,每当有人从发送缓冲区发送数据时,数据就会出现在接收缓冲区中。

如果不小心平衡发送写入和接收读取,则不会知道在接收缓冲区中会发生什么。如果接收缓冲区溢出,通常只会溢出和丢失数据。

因此,当一个人发送一个读命令(即一个字节的操作码和三个地址字节)时,将首先在SPI主接收缓冲区中接收四个字节的“垃圾”。这四个垃圾字节对应于操作码和三个地址字节。在传输这些内容时,Flash尚不知道要读取什么,因此它仅返回四个字的垃圾。

返回这四个垃圾字后,为了在接收缓冲区中获得其他内容,您必须发送等于您要读取的数据量。在操作码和地址之后,传输什么都无所谓,只是将Read DAta从SPI Flash推送到接收缓冲区就可以了。

如果您不仔细跟踪返回的前四个垃圾字,您可能会认为其中一个或多个是您返回的读取数据的一部分。

因此,为了知道您实际上从接收缓冲区中获取了什么,了解缓冲区的大小,知道如何判断它是空还是已满(通常通过注册状态位来报告此值)并跟踪如何您传送了多少东西,您收到了多少。

开始任何SPI Flash操作之前,最好先“清空”接收FIFO。这意味着检查接收缓冲区的状态并将其清空(通常通过执行“读取”接收缓冲区来完成)(如果尚未清空)。通常,清空(读取)已经为空的接收缓冲区不会造成任何危害。

SPI闪存数据表中的时序图提供了以下信息,但有时人们会忽略一些位。使用SPI总线将所有命令和数据发布到SPI闪存。读取SPI Flash的顺序为:

1) Start with CS_ high.
2) Bring CS_ low.
3) Issue "Read" op code to SPI Flash.
4) Issue three address bytes to SPI Flash.
5) "Receive" four garbage words in Receive Buffer.
6) Transmit as many arbitrary bytes (don't cares) as you wish to receive. 
Number of transmitted bytes after address equals size of desired read.
7) Receive read data in the Receive Buffer.
8) When you've read the desired amount of data, set CS_ high to end the Read command.
If you skip this step, any additional transmissions will be interpreted as 
request for more data from (a continuation of) this Read.

请注意,必须根据读取的大小以及接收和发送缓冲区的大小来交错并重复执行步骤6和7。如果您一次发送的字数超出了接收缓冲区的容纳量,则会溢出一些数据。

为了执行页面编程或写入命令,请执行以下步骤。页面大小(通常为256个字节)和扇区大小(通常为64K)以及相关的边界是所使用的SPI Flash的属性。此信息应在Flash的数据表中。我将省略平衡发送和接收缓冲区的详细信息。

1) Start with CS_ high.
2) Change CS_ to low.
3) Transmit the Write Enable (WREN) op code.
4) Switch CS_ to high for at least one SPI Bus clock cycle.  This may be tens or
hundreds of host clock cycles.  All write operations do not start until CS_ goes high.  
The preceding two notes apply to all the following 'CS_ to high' steps.
5) Switch CS_ to low.
6) Gadfly loop:   Transmit the 'Read from Status Register' (RDSR) op code and 
one more byte.   Receive two bytes.  First byte is garbage.  Second byte is status.
Check status byte.  If 'Write in Progress' (WIP) bit is set, repeat loop. 
(NOTE:  May also check 'Write Enable Latch' bit is set (WEL) after WIP is clear.)
7) Switch CS_ to high.
8) Switch CS_ to low.
9) Transmit Sector Erase (SE) or Bulk Erase (BE) op code.  If sending SE, then follow
it with three byte address.
10) Switch CS_ to high.
11) Switch CS_ to low.
12) Gadfly loop:  Spin on WIP in Status Register as above in step 6.  WEL will
be unset at end.
13) Switch CS_ to high.
14) Switch CS_ to low.
15) Transmit Write Enable op code (again).
16) Switch CS_ to high.
17) Switch CS_ to low.
18) Gadfly loop:  Wait on WIP bit in Status Register to clear. (WEL will be set.)
19) Transmit Page Program (PP = Write) op code followed by three address bytes.
20) Transmit up to Page Size (typically 256 bytes) of data to write.  (You may allow
Receive data to simply spill over during this operation, unless your host hardware
has a problem with that.)
21) Switch CS_ to high.  
22) SWitch CS_ to low.
23) Gadfly loop:  Spin on WIP in the Status Register.
24) Drain Receive FIFO so that it's ready for the next user.
25)  Optional:  Repeat steps 13 to 24 as needed to write additional pages or
page segments.

最后,如果您的写入地址不在页面边界上(通常为256字节的倍数),并且您写入了足够的数据以跨越下一个页面边界,则应越过边界的数据将被写入页面的开头,您的程序地址不正确。因此,如果您尝试将三个字节写入地址0x0FE。前两个字节将被写入0x0fe和0x0ff。第三个字节将被写入地址0x000。

如果传输的数据字节数大于页面大小,则早期字节将被丢弃,仅最后的256(或页面大小)字节将用于对页面进行编程。

与往常一样,对于上述任何错误,错别字,疏忽或混乱造成的后果,以及如何使用,概不负责。


“在开始任何SPI Flash操作之前,最好先清空接收FIFO。这意味着检查接收缓冲区的状态并将其清空(通常通过对接收缓冲区进行'读取'来完成)”通常,清空(读取)已经为空的接收缓冲区不会造成任何危害。” 我需要采取什么步骤来读取接收缓冲区的状态并清空接收缓冲区?

3

与这里的某些陈述相反,尽管那里有一些古怪的SPI PROM,但各种SPI PROM(包括您选择的一个)也使用了一些标准指令。

正如vicatcu已经提到的那样,有很多可以直接对SPI进行编程的“ bit-bash”电缆。在信号方面,SPI看起来很像JTAG,因此只要接口是开源的,任何位速率类型的电缆都应该能够使用。闪存的内部协议非常简单。

我们使用您正在寻找的零件的老大哥来启动我们的FPGA板(256M-2G)。该地址有一个额外的字节来处理存储量,但其他命令基本相同。

您要使用的PROM类型必须按扇区擦除,然后按页面编程。读取比写入快得多(在我们使用的情况下,编程可能需要半小时,但在108MHz的频率下读取整个PROM则需要一秒钟)。

现在的命令:有方式更多的命令在这些设备上使用比实际需要对他们进行编程。您实际上只需要以下内容:

  • RDID(读取ID)-在执行更复杂的操作之前只是为了验证PROM和信令。
  • WREN(写使能)-每次写之前需要。
  • PP(0x02-页面编程)-对页面进行编程需要。
  • SE(0x20-扇区擦除)-将扇区中的位返回为“ 1”。
  • RDSR(0x05-读取状态寄存器)-监视擦除/写入周期所需。
  • FREAD(0x0B-快速读取)-读取PROM数据并验证写入。

如果需要更多信息,请在其网站(http://www.xilinx.com)上查看有关Xilinx FPGA的SPI编程的答复说明。它们实现了减少的命令子集,因此其FPGA可以从这些设备启动。

我设计了自己的程序员,以根据自己的能力做到这一点,并用Python编写了一个程序员脚本,但是您可以使用电缆进行相同的操作。对于您的情况,我将认真考虑按照Michael Karas的建议通过MCU间接进行所有操作。您无需一口气从MCU编程整个PROM,您可以按部门进行编程。


2

如果您愿意更改USB的编程方式,则应该能够将USBtiny重新用于编程闪存而不是目标MCU。但是,可能没有足够的内存来使其具有足够的通用性以对MCU和闪存进行编程。

在某个地方,我有一个项目的电路板,该电路板同时具有ATTINY和SPI闪存,并用作Arduino,是一个随时可用的“编程器”。略微修改了ISP草图,即可使用avrdude对MCU进行编程,然后一个自定义实用程序发送一个序列,该序列将草图置于特殊模式,并将数据块写入SPI闪存。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.