我正在开发一个音频应用程序,而不是将音频数据存储在SD卡(Arduino 上的Waveshield)上,而是将其存储在SPI闪存IC上,并使用MCU,DAC和放大器滚动自己的电路板。
我正在使用Winbond W25Q80BVSSIG。
我对使用AVRISP mkII或USBTiny编程AVR非常熟悉,是使用同一程序员将数据写入闪存吗?在专门寻找SPI闪存编程器时,我一直找不到任何东西。
这个问题是一个跟进这一个。
我正在开发一个音频应用程序,而不是将音频数据存储在SD卡(Arduino 上的Waveshield)上,而是将其存储在SPI闪存IC上,并使用MCU,DAC和放大器滚动自己的电路板。
我正在使用Winbond W25Q80BVSSIG。
我对使用AVRISP mkII或USBTiny编程AVR非常熟悉,是使用同一程序员将数据写入闪存吗?在专门寻找SPI闪存编程器时,我一直找不到任何东西。
这个问题是一个跟进这一个。
Answers:
如果您只是在寻找一种用“预加载”数据对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针版本,可适合各种应用。电缆的成本非常合理。
我敢打赌,您可以使用Bus Pirate来完成此任务,而无需通过您的MCU ...这可以让您使用SPI,I2C或UART通信直接对芯片进行任意的串行交互。“编写”脚本可能需要一些工作,但它可能会让您完成工作。
我也看到了专门的工具,可通过I2C直接加载EEPROM,但没有闪存和SPI。
我从未听说过有其他工具可以将SPI直接与这种芯片相连,而且我认为这是不可能的,因为“所有”芯片需要不同的调用来执行不同的操作。
该芯片需要SPI调用来进行写入,读取,更改扇区,数据大小等。在数据手册的7.2指令章节下,您可以看到可以发送给它的所有SPI命令。因此,由于所有外部闪存都不具有相同的指令集,因此您需要为此编写一个定制的应用程序。
编辑:作为后续工作,我真的会推荐Atmels自己的SPI闪存之一,因为其中大多数已经为它们编写了开放的可用代码。看这篇文章从AVRFreaks将为您提供一些的爱特梅尔AT45xxxx串行闪存芯片的代码。
我从嵌入式计算机公司购买了一个“ FlashCAT ”编程器,价格约为30美元。通过USB连接到PC并将文件写入Winbond闪存非常容易。其他答案中的方法和程序员可能都一样好,价格也更高,或者自己动手做,但这是一种便宜又简单的方法,适合我的需求。
这是设置的图片:
FlashCAT编程器位于左侧,已连接到USB。它正在运行SPI编程固件(与JTAG相对),并为闪存供电。可用跳线选择提供的电源(3.3V或5V)。
我在试验板上有一个SOIC到DIP插座,可以很容易地对多个芯片进行编程。(您还可以看到面包板上也有另一个闪存IC。)
我还没有将音频文件转换为正确的二进制格式,但是我将211KB WAV文件写到内存中只是为了进行测试,如上图所示。然后,我将其读回并保存为新文件,将其重命名为.wav,然后在PC上正确播放。
下一步将是正确编码文件,并编写AVR软件以读取数据并通过DAC发送。
免责声明:我不隶属于嵌入式计算机,我只是一个选择便宜东西并分享有关产品使用体验信息的客户。
讨论有点晚了,但是对于任何在搜索后阅读它的人来说都是如此。
我没有提到的一件事,对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 PROM,但各种SPI PROM(包括您选择的一个)也使用了一些标准指令。
正如vicatcu已经提到的那样,有很多可以直接对SPI进行编程的“ bit-bash”电缆。在信号方面,SPI看起来很像JTAG,因此只要接口是开源的,任何位速率类型的电缆都应该能够使用。闪存的内部协议非常简单。
我们使用您正在寻找的零件的老大哥来启动我们的FPGA板(256M-2G)。该地址有一个额外的字节来处理存储量,但其他命令基本相同。
您要使用的PROM类型必须按扇区擦除,然后按页面编程。读取比写入快得多(在我们使用的情况下,编程可能需要半小时,但在108MHz的频率下读取整个PROM则需要一秒钟)。
现在的命令:有方式更多的命令在这些设备上使用比实际需要对他们进行编程。您实际上只需要以下内容:
如果需要更多信息,请在其网站(http://www.xilinx.com)上查看有关Xilinx FPGA的SPI编程的答复说明。它们实现了减少的命令子集,因此其FPGA可以从这些设备启动。
我设计了自己的程序员,以根据自己的能力做到这一点,并用Python编写了一个程序员脚本,但是您可以使用电缆进行相同的操作。对于您的情况,我将认真考虑按照Michael Karas的建议通过MCU间接进行所有操作。您无需一口气从MCU编程整个PROM,您可以按部门进行编程。