Etwas spät zur Diskussion, aber für alle, die es nach einer Suche lesen ...
Eine Sache, die ich nicht erwähnt habe und 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 setzen. Insbesondere muss ein Übergang von CS_hoch zu CS_niedrig unmittelbar vor der Ausgabe eines Schreiboperations-Operationscodes (WREN, BE, SE, PP) erfolgen. Wenn zwischen dem CS_-Übergang (dh nachdem CS_ niedrig geworden ist) und vor der Übertragung des Schreiboperationscodes eine Aktivität besteht, wird der Schreiboperationscode normalerweise ignoriert.
Was in SPI-Flash-Datenblättern nicht häufig erklärt wird, da 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 sendet, 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 befiehlt, 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 angezeigt werden, müssen einige Daten aus dem Sendepuffer gesendet worden sein. In ähnlicher Weise werden jedes Mal, wenn Daten aus dem Sendepuffer gesendet werden, Daten im Empfangspuffer angezeigt.
Wenn man beim Ausgleich von Sende- und Empfangslesungen nicht aufpasst, 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 aus einem Ein-Byte-Op-Code und drei Adressbytes besteht, empfängt man zuerst 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, und gibt nur vier Müllwörter zurück.
Nachdem diese vier Müllwörter zurückgegeben wurden, müssen Sie eine Datenmenge senden, die der Menge entspricht, die Sie lesen möchten, um etwas anderes im Empfangspuffer zu erhalten. Nach dem Operationscode und der Adresse spielt es keine Rolle, was Sie senden, es ist nur ein Füllstoff, um die Read DAta vom SPI-Flash zum Empfangspuffer zu verschieben.
Wenn Sie die ersten vier zurückgegebenen Müllwörter nicht sorgfältig nachverfolgt haben, denken Sie möglicherweise, dass eines oder mehrere davon Teil Ihrer zurückgegebenen Lesedaten sind.
Um 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 (normalerweise gibt es ein Registerstatusbit, um dies zu melden) und zu verfolgen, wie viel Zeug, das Sie gesendet haben und wie viel Sie erhalten haben.
Bevor Sie einen SPI-Flash-Vorgang starten, sollten Sie den Empfangs-FIFO "entleeren". Dies bedeutet, dass Sie den Status des Empfangspuffers überprüfen und leeren müssen (normalerweise durch Lesen des Empfangspuffers), falls dieser noch nicht leer ist. Normalerweise schadet das Entleeren (Lesen) eines bereits leeren Empfangspuffers nicht.
Die folgenden Informationen sind aus den Zeitdiagrammen in den Datenblättern von SPI-Flashs verfügbar, aber manchmal übersehen die Leute Bits. Alle Befehle und Daten werden über den SPI-Bus an den SPI-Flash ausgegeben. Die Reihenfolge zum Lesen eines SPI-Flashs lautet:
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 senden, als Ihr Empfangspuffer aufnehmen kann, werden einige Daten verschüttet.
Führen Sie diese Schritte aus, um einen Seitenprogramm- oder Schreibbefehl auszuführen. Die Seitengröße (normalerweise 256 Byte) und die Sektorgröße (normalerweise 64 KB) sowie die zugehörigen Grenzen sind Eigenschaften des von Ihnen verwendeten SPI-Flashs. Diese Informationen sollten im Datenblatt für den Flash enthalten sein. Ich werde die Details des Ausgleichs 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 nicht an einer Seitengrenze befindet (normalerweise ein Vielfaches von 256 Byte) und Sie genügend Daten schreiben, um die folgende Seitengrenze zu überschreiten, werden die Daten, die die Grenze überschreiten sollen, 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 in 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 frühen Bytes verworfen und nur die letzten 256 (oder Seitengrößen-) Bytes werden zum Programmieren der Seite verwendet.
Wie immer nicht verantwortlich für die Folgen von Fehlern, Tippfehlern, Versehen oder Störungen in den oben genannten oder in der Art und Weise, wie Sie sie verwenden.