Wie schreibe ich in den SPI-Flash-Speicher?

Ich arbeite an einer Audioanwendung, bei der ich Audiodaten nicht auf einer SD-Karte ( Waveshield auf Arduino) speichere, sondern auf einem SPI-Flash-Speicher-IC speichere und mein eigenes Board mit MCU, DAC und Verstärker rolle.

Ich verwende einen Winbond W25Q80BVSSIG .

Ich bin mit der Programmierung von AVR mit dem AVRISP mkII oder dem USBTiny ziemlich vertraut. Wird das Schreiben von Daten auf Flash mit demselben Programmierer durchgeführt? Ich konnte nichts finden, als ich speziell nach SPI-Flash-Speicherprogrammierern suchte.

Diese Frage knüpft an diese an .

Ich weiß nicht, ob es einen Programmierer gibt, der dies von einem PC oder so einfach für Sie tun kann, aber wenn Ihre Schaltung eine CPLD enthält, können Sie diese so konfigurieren, dass Daten in den Flash-Speicher geschrieben werden.
Ich denke, Spi-Flash-Module sind heutzutage so konzipiert, dass sie Firmware / BIOS speichern, die die CPU in den meisten PCs verwendet. Nichts für robuste Speichergeräte.

Antworten (7)

Wenn Sie einfach nach einer Möglichkeit suchen, den Winbond SPI-Flash mit "vorinstallierten" Daten zu programmieren, die Ihr Mikrocontroller zur Verwendung lesen würde, wenn er läuft, dann sollten Sie sich einen Programmierer ansehen, der In-Circuit-Programmierung durchführen kann des SPI-Flash-Chips. Dies wird auch als In-System-Programming (ISP) bezeichnet.

Eine Wahl ist der Programmierer von DediProg. Dieses über USB angeschlossene Gerät kann im Schaltkreis programmieren, wenn Sie Ihr Board richtig entwerfen. Sie verkaufen sogar einen Adapterclip, der an das SOW-16-Gehäuse angeschlossen werden kann, ohne dass Sie einen separaten Programmierkopf auf Ihrem Board entwerfen müssen. DediProg stellt Bulletins mit Anwendungsinformationen zur Verfügung, um beim korrekten Design für den Einsatz in Schaltkreisen zu helfen. Die Hauptstrategie für das Design besteht darin, einen einfachen Weg zu finden, um die SPI-Schnittstellentreiber in Ihrem MCU-System zu isolieren, damit sie die Treiber im SPI-Programmier-Pod nicht stören. Der einfachste Weg, dies zu tun, besteht darin, Reihenwiderstände in die von der MCU angesteuerten Leitungen zwischen der MCU und dem SPI-Flash einzufügen. Der Programmierer würde auf der SPI-Flash-Seite der Vorwiderstände eine Verbindung herstellen. Alternative Verfahren könnten das Hinzufügen eines MUX oder analoger Schalter in den angesteuerten Schnittstellenleitungen beinhalten. Ein noch clevereres Schema besteht darin, ein "

Geben Sie hier die Bildbeschreibung ein

Eine zweite zu berücksichtigende Wahl ist der USB-Programmierer von ASIX . Der Presto ist in der Lage, verschiedene Arten von SPI- und I 2 C-Geräten zu verarbeiten, einschließlich SPI-Flash-Geräten. Ich habe eines dieser Geräte speziell für die Programmierung von Atmel-MCUs und verschiedenen Arten von SPI-Flash-Geräten. Es ist eine kostengünstigere Lösung als die obige Einheit, aber nicht ganz so flexibel. Ihr teureres Gerät namens Forte kann mehr Dinge tun, weil es mehr Zielschnittstellen-Pins hat.

Geben Sie hier die Bildbeschreibung ein

Manchmal kann es von Vorteil sein, einen Programmierer mit einer Zielplatine verbinden zu können, ohne einen Programmierkopf hinzufügen zu müssen. Eine gute Lösung dafür ist, einen kleinen Satz Pads in einem speziellen Fußabdruck zu platzieren, der von einer Firma namens TagConnect definiert wurde . Sie produzieren und verkaufen eine Reihe von Schnellverbindungs-Programmierkabeln mit Pogo-Pins, die in den speziellen Footprint auf der Platine eingreifen. Es sind 6-Pin-, 10-Pin- und 14-Pin-Versionen des Kabels für eine Reihe von Anwendungen erhältlich. Die Kosten für die Kabel sind sehr vernünftig.

Geben Sie hier die Bildbeschreibung ein

Das ist sehr hilfreich. Ich plane, den Flash-Speicher zu programmieren, bevor ich ihn auf die endgültige Platine löte. Bisher habe ich das für MCUs gemacht und es hat gut funktioniert. Ich bin mir nicht sicher, ob das Bereitstellen von ISP-Pins auf der Platine eine gute Idee ist oder nicht, da sie nach Fertigstellung nicht neu programmiert werden sollen.
@JYelton - Meiner Erfahrung nach ist es aus mehreren Gründen eine gute Idee, für ISP zu planen. ECO's (Engineering Change Orders) sind eine Tatsache des Lebens im Produktzyklus. Jemand oder etwas wird eine Änderung des Flash-Inhalts verlangen, sobald Sie mit der Produktion beginnen. Flash-Chips sind manchmal anfällig für unerwartete Rauschstörungen in der Schaltung und enden damit, dass ihr Inhalt kompromittiert wird. Ein weiterer Grund, für ISP zu sorgen.
Gibt es einen "Standard"-Header, der mit den meisten dieser Programmierer kompatibel ist, zumindest über gebündelte Adapterkabel? Ich habe 2x4- und 2x5-Pin-Header mit einer Reihe unterschiedlicher Pinbelegungen gesehen. Siehe auch flashrom.org/Supported_hardware
Jeder hat seine eigene Vorstellung von vernünftig. Die Tag-Connect-Kabel kosten 35 bis 40 US-Dollar.
@markrages - Aber für ein bestimmtes Entwicklungslabor oder eine Werksprogrammierstation müssen Sie nur ein Kabel kaufen. Sie brauchen nicht für jedes Produkt einen. Außerdem sind diese Kabel viel billiger als der Versuch, Ihre eigene Pogo-Pin-Befestigung zu rollen, um ISP ohne Stecker zu ermöglichen.

Ich wette, Sie könnten es mit einem Buspiraten machen , ohne Ihre MCU zu durchlaufen ... damit können Sie etwas willkürliche serielle Interaktionen direkt mit einem Chip unter Verwendung von SPI-, I2C- oder UART-Kommunikation durchführen. Es könnte ein wenig Arbeit erfordern, es zu "skripten", aber es würde Sie wahrscheinlich die Arbeit erledigen lassen.

Ich habe auch spezielle Tools zum direkten Laden von EEPROMs über I2C gesehen, aber nicht Flash und nicht speziell SPI.

Ich beginne mich zu fragen, ob meine Auswahl an SPI-Flash gut ist, wenn man bedenkt, wie (offenbar) obskur die Methoden sind, um auf die verdammten Dinger zu schreiben.
Das würde ernsthaftes Scripting erfordern, aber trotzdem eine gute Idee. Für meinen Geschmack etwas zu kompliziert. Vielleicht sollten Sie eine SD-Karte in Betracht ziehen? Dann müssen Sie sich nur noch um das Lesen kümmern und mit einem Computer darauf schreiben
Der aktuelle Prototyp verwendet ein Arduino und Waveshield (das über einen SD-Kartenleser verfügt). Ich möchte von der SD-Karte wegkommen, weil ich glaube, dass die Kosten geringer sein werden (kein Lesegerät und Karte) und auch manipulationssicherer.

Ich habe noch nie von anderen Tools gehört, die SPI direkt mit einem solchen Chip kommunizieren, und ich denke, es ist unmöglich, da "alle" Chips unterschiedliche Aufrufe für unterschiedliche Operationen erfordern.

Der Chip benötigt SPI-Aufrufe zum Schreiben, Lesen, Ändern des Sektors, der Datengröße usw. Unter dem Kapitel 7.2 Anweisungen im Datenblatt können Sie alle SPI-Befehle sehen, die Sie an ihn senden können. Da nicht alle externen Flash-Speicher denselben Befehlssatz haben, müssen Sie eine angepasste Anwendung für diesen schreiben.

EDIT: Als Follow-up würde ich wirklich einen von Atmels eigenen SPI-Flash-Speichern empfehlen, da die meisten von ihnen bereits offenen verfügbaren Code für sie geschrieben haben. Wenn Sie sich diesen Beitrag von AVRFreaks ansehen , erhalten Sie Code für einige der seriellen AT45xxxx-Flash-Chips von Atmels.

Wenn ich dich richtig verstehe, soll ich ein Programm für meine MCU schreiben, das dann die Daten in den Flash-Speicher schreibt? Das Problem ist, dass die MCU weniger Speicher hat als der externe Flash, also bin ich etwas ratlos.
Ja. Sie können Daten von der seriellen Leitung Ihres Computers mit UART senden, die Sie in den Flash schreiben. Sie könnten auch mehrere Programme für die MCU schreiben und den Flash einige Blöcke gleichzeitig programmieren. Es kann ein wenig zeitaufwändig sein, aber es funktioniert, da der externe Flash nicht gelöscht wird, solange Sie den Sektorwechsel korrekt verfolgen
Dies ist die richtige Antwort. Sie benötigen also ein Programm auf Ihrem PC, um Chunks auf die MCU herunterzuladen, die sie dann in den Flash schreibt. Es hilft, wenn es eine Fehlerprüfung gibt und Sie kein neues Programm auf dem PC schreiben müssen; Daher schlage ich vor, dass Sie Code für XMODEM oder ähnliches finden.
@ pjc50 ... nicht so schnell beim Deklarieren der 'richtigen Antwort' :)
Tatsächlich können viele Programmierer Flash-Speicher programmieren; und eines der gebräuchlichen Programmierschemata, die mit den Atmel-Mikros verwendet werden, ist zunächst ziemlich nah an SPI.
Können Sie dazu einige Beispiele nennen?

Etwas spät zur Diskussion, aber für alle, die es nach einer Suche lesen ...

Eine Sache, die ich nicht erwähnt habe, die beim Programmieren von SPI-Flash-Chips absolut kritisch ist, ist die Steuerung des Chip Select (CS_) Pins. Der Chip-Select-Pin wird verwendet, um Befehle an den SPI-Flash zu unterbrechen. Insbesondere muss ein Übergang von CS_high nach CS_low unmittelbar der Ausgabe eines Schreiboperations-Operationscodes (WREN, BE, SE, PP) vorausgehen. Wenn es zwischen dem CS_-Übergang (dh nachdem CS_ auf niedrig gegangen ist) und bevor der Schreib-Op-Code übertragen wird, Aktivität gibt, wird der Schreib-Op-Code normalerweise ignoriert.

Was in SPI-Flash-Datenblättern normalerweise nicht erklärt wird, weil es ein fester Bestandteil des SPI-Protokolls ist, was ebenfalls kritisch ist, ist, dass man für jedes Byte, das man auf dem SPI-Bus überträgt, ein Byte zurückerhält. Außerdem kann man keine Bytes empfangen, es sei denn, man sendet ein Byte.

Typischerweise hat der SPI-Master, den der Benutzer befehligt, einen Sendepuffer, der Bytes auf der MOSI-Leitung des SPI-Busses sendet, und einen Empfangspuffer, der Bytes von der MISO-Leitung des SPI-Busses empfängt.

Damit Daten im Empfangspuffer erscheinen, müssen einige Daten aus dem Sendepuffer gesendet worden sein. In ähnlicher Weise erscheinen jedes Mal, wenn Daten aus dem Sendepuffer gesendet werden, Daten im Empfangspuffer.

Wenn man nicht darauf achtet, Sendeschreibvorgänge und Empfangslesevorgänge auszugleichen, weiß man nicht, was im Empfangspuffer zu erwarten ist. Wenn der Empfangspuffer überläuft, werden Daten normalerweise nur verschüttet und gehen verloren.

Wenn man also einen Lesebefehl sendet, der ein Ein-Byte-Operationscode und drei Adressbytes ist, erhält man zunächst vier Bytes "Müll" im SPI-Master-Empfangspuffer. Diese vier Müllbytes entsprechen dem Operationscode und drei Adressbytes. Während diese übertragen werden, weiß der Flash noch nicht, was er lesen soll, also gibt er nur vier Worte Müll zurück.

Nachdem diese vier Wörter Müll zurückgegeben wurden, müssen Sie, um etwas anderes in den Empfangspuffer zu bekommen, eine Datenmenge übertragen, die der Menge entspricht, die Sie lesen möchten. Nach dem Operationscode und der Adresse spielt es keine Rolle, was Sie übertragen, es ist nur ein Füller, um die Lesedaten vom SPI-Flash in den Empfangspuffer zu schieben.

Wenn Sie diese ersten vier zurückgegebenen Müllwörter nicht sorgfältig verfolgt haben, denken Sie vielleicht, dass eines oder mehrere davon Teil Ihrer zurückgegebenen Lesedaten sind.

Um also zu wissen, was Sie tatsächlich aus dem Empfangspuffer erhalten, ist es wichtig, die Größe Ihres Puffers zu kennen, zu wissen, ob er leer oder voll ist (es gibt normalerweise ein Registerstatusbit, um dies zu melden) und zu verfolgen, wie wie viel Zeug Sie übertragen haben und wie viel Sie erhalten haben.

Bevor Sie einen SPI-Flash-Vorgang starten, sollten Sie den Empfangs-FIFO „leeren“. Das heißt, prüfen Sie den Status des Empfangspuffers und leeren Sie ihn (normalerweise durch „Lesen“ des Empfangspuffers), falls er nicht bereits leer ist. Normalerweise schadet das Leeren (Lesen) eines bereits leeren Empfangspuffers nicht.

Die folgenden Informationen sind aus den Timing-Diagrammen in Datenblättern von SPI-Flashes verfügbar, aber manchmal übersehen Leute Bits. Alle Befehle und Daten werden über den SPI-Bus an den SPI-Flash ausgegeben. Die Sequenz zum Lesen eines SPI-Flash ist:

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.

Beachten Sie, dass die Schritte 6 und 7 abhängig von der Größe des Lesevorgangs und der Größe Ihrer Empfangs- und Sendepuffer verschachtelt und wiederholt werden müssen. Wenn Sie eine größere Anzahl von Wörtern auf einmal übertragen, als Ihr Empfangspuffer aufnehmen kann, werden einige Daten verschüttet.

Um einen Seitenprogramm- oder Schreibbefehl auszuführen, führen Sie diese Schritte aus. Die Seitengröße (normalerweise 256 Bytes) und die Sektorgröße (normalerweise 64 KB) und die zugehörigen Grenzen sind Eigenschaften des von Ihnen verwendeten SPI-Flash. Diese Information sollte im Datenblatt für den Flash stehen. Ich werde die Einzelheiten des Ausgleichens der Sende- und Empfangspuffer weglassen.

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.

Wenn sich Ihre Schreibadresse schließlich nicht auf einer Seitengrenze befindet (normalerweise ein Vielfaches von 256 Bytes) und Sie genug Daten schreiben, um die folgende Seitengrenze zu überschreiten, werden die Daten, die die Grenze überschreiten sollten, an den Anfang der Seite geschrieben, in der Ihre Programmadresse fällt. Wenn Sie also versuchen, drei Bytes an die Adresse 0x0FE zu schreiben. Die ersten beiden Bytes werden auf 0x0fe und 0x0ff geschrieben. Das dritte Byte wird an die Adresse 0x000 geschrieben.

Wenn Sie eine Anzahl von Datenbytes übertragen, die größer als eine Seitengröße sind, werden die ersten Bytes verworfen und nur die letzten 256 (oder Seitengröße) Bytes werden zum Programmieren der Seite verwendet.

Wie immer, nicht verantwortlich für die Folgen von Fehlern, Tippfehlern, Versehen oder Störungen in den obigen Angaben oder in der Art und Weise, wie Sie sie verwenden.

„Bevor Sie einen SPI-Flash-Vorgang starten, ist es eine gute Idee, den Empfangs-FIFO zu „leeren“. Dies bedeutet, dass Sie den Status des Empfangspuffers überprüfen und ihn leeren (normalerweise durch Ausführen eines „Lesens“ des Empfangspuffers), wenn dies nicht der Fall ist bereits leer. Normalerweise schadet das Leeren (Lesen) eines bereits leeren Empfangspuffers nicht." Welche Schritte muss ich unternehmen, um den Status des Empfangspuffers zu lesen und den Empfangspuffer zu leeren?

Ich habe einen „ FlashCAT “-Programmierer von Embedded Computers für etwa 30 US-Dollar gekauft. Es war überraschend einfach, sich über USB mit dem PC zu verbinden und Dateien auf den Winbond-Flash-Speicher zu schreiben. Die Methoden und Programmierer in anderen Antworten sind wahrscheinlich genauso gut, einige teurer oder DIY, aber dies ist ein billiger und einfacher Weg, der zu dem passt, was ich gesucht habe.

Hier ein Bild von der Einrichtung:

Programmierung mit FlashCAT

Der FlashCAT-Programmierer ist links mit USB verbunden. Es führt die SPI-Programmierfirmware (im Gegensatz zu JTAG) aus und versorgt den Flash-Speicher mit Strom. Die zugeführte Leistung ist mit einem Jumper wählbar (3,3 V oder 5 V).

Ich habe eine SOIC-zu-DIP-Buchse auf dem Steckbrett, um das Programmieren mehrerer Chips zu vereinfachen. (Sie können auch einen anderen Flash-Speicher-IC sehen, der auf dem Steckbrett sitzt.)

FlashCAT-Software

Ich habe meine Audiodatei noch nicht in das richtige Binärformat konvertiert, aber ich habe nur zum Testen eine 211-KB-WAV-Datei in den Speicher geschrieben, wie oben abgebildet. Ich habe es dann zurückgelesen und als neue Datei gespeichert, in .wav umbenannt und es wird korrekt auf dem PC abgespielt.

Der nächste Schritt besteht darin, die Datei richtig zu codieren und die AVR-Software zu schreiben, um die Daten zu lesen und über einen DAC zu senden.

Haftungsausschluss: Ich bin nicht mit Embedded Computers verbunden, ich bin nur ein Kunde, der etwas Günstiges ausgewählt hat und Informationen über die Erfahrungen mit dem Produkt teilt.

Im Gegensatz zu einigen Aussagen hier gibt es zwar einige skurrile SPI-PROMs, aber auch einige Standardanweisungen, die von einer Vielzahl von SPI-PROMs verwendet werden, einschließlich des von Ihnen ausgewählten.

Wie vicatcu bereits erwähnt hat, gibt es gute 'Bit-Bash'-Kabel, die SPI direkt programmieren können. In Bezug auf das Signal sieht SPI JTAG sehr ähnlich, daher sollte jeder Bit-Bash-Kabeltyp verwendet werden können, vorausgesetzt, die Schnittstelle ist Open Source. Das interne Protokoll des Blitzes ist ziemlich einfach.

Wir verwenden den großen Bruder des Teils, den Sie sich ansehen, um unsere FPGA-Boards (256M - 2G) zu booten. Die Adressierung hat ein zusätzliches Byte, um das Speichervolumen zu handhaben, aber ansonsten sind die Befehle im Wesentlichen identisch.

Der verwendete PROM-Typ muss sektorweise gelöscht und dann seitenweise programmiert werden. Das Lesen ist erheblich schneller als das Schreiben (bei den von uns verwendeten kann das Programmieren eine halbe Stunde dauern, aber das Lesen des gesamten PROM dauert bei 108 MHz weniger als eine Sekunde).

Nun zu den Befehlen: In diesen Geräten stehen weitaus mehr Befehle zur Verfügung , als eigentlich zum Programmieren benötigt werden. Du benötigst eigentlich nur folgendes:

  • RDID (Read ID) - nur um das PROM und die Signalisierung zu überprüfen, bevor Sie etwas Komplexeres tun.
  • WREN (Write enable) – vor jedem Schreibvorgang erforderlich.
  • PP (0x02 - Seitenprogramm) - benötigt, um eine Seite zu programmieren.
  • SE (0x20 - Sektorlöschung) - setzt Bits im Sektor auf '1' zurück.
  • RDSR (0x05 - Statusregister lesen) - benötigt, um den Lösch-/Schreibzyklus zu überwachen.
  • FREAD (0x0B – schnelles Lesen) – PROM-Daten lesen und Schreiben verifizieren.

Weitere Informationen finden Sie in den Antworthinweisen zur SPI-Programmierung für Xilinx-FPGAs auf deren Website (http://www.xilinx.com). Sie implementieren eine reduzierte Teilmenge von Befehlen, damit ihre FPGAs von diesen Geräten booten können.

Ich habe meinen eigenen Programmierer dafür entworfen, basierend auf dem, was ich zur Verfügung habe, und ein Programmiererskript in Python geschrieben, aber Sie können dasselbe mit einem Kabel tun. In Ihrem Fall würde ich ernsthaft erwägen, alles indirekt über die MCU zu machen, wie Michael Karas vorschlägt. Sie müssen nicht das gesamte PROM von der MCU auf einmal programmieren - Sie können dies sektorweise tun.

Sie sollten in der Lage sein, den USBtiny neu zu verwenden, um einen Flash-Speicher anstelle einer Ziel-MCU zu programmieren, wenn Sie die Programmierung bequem ändern können. Es ist jedoch möglicherweise nicht genügend Speicher vorhanden, um ihn vielseitig genug zu machen, um sowohl die MCU als auch den Flash zu programmieren.

Irgendwo habe ich ein Board aus einem Projekt, das sowohl einen ATTINY- als auch einen SPI-Flash hat und einen Arduino als leicht verfügbaren "Programmierer" verwendet. Eine leichte Modifikation der ISP-Skizze wird verwendet, um die MCU mit avrdude zu programmieren, dann sendet ein benutzerdefiniertes Dienstprogramm eine Sequenz, die die Skizze in einen speziellen Modus versetzt und Datenblöcke in den SPI-Flash schreibt.