<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Hallo Erwin</p>
<p>Vielen Dank für die Infos. Ich brauch wohl etwas länger um das zu
begreifen.</p>
<p>Ich meld mich wieder sobald ich glaube, dass ich es verstanden
habe. Mit Sicherheit mit neuen Fragen :)<br>
</p>
<p>Gruss <br>
Sven<br>
</p>
<div class="moz-cite-prefix">On 04.01.21 13:42, Erwin Pschernig via
tiptoi-hw wrote:<br>
</div>
<blockquote type="cite"
cite="mid:trinity-24a1b83d-b016-4bbb-9b51-28a4de1f2e47-1609764156022@3c-app-gmx-bs34">
<div>
<div> </div>
<div><strong>Noch eine Ergänzung zum Verständnis von "Page",
"Block", "Row" und "Column".</strong></div>
<div> </div>
<div>
<div>Aus den bisherigen Infos gehe ich jetzt mal von der x8
Variante des Flash aus (also 8 Datenleitungen).</div>
<div> </div>
<div>Außerdem sagt ein Bild mehr als 1000 Worte, aber ein paar
gibts trotzdem:</div>
<div> </div>
<div>Jede Page hat 2k + 64 Bytes = 2048 + 64 = 2112, das ist
die "column address"</div>
<div>Da 2112 = 0x0840 erklärt sich warum bei 8 Datenleitungen
zum Flash 2 cyles zum senden der Spaltenadresse notwendig
sind.</div>
<div> </div>
<div>Der hier verwendete Chip hat 4096 Blocks à 64 Pages =
4096 * 64 = 262144 Pages<br>
Da 262144 = 0x040000 erklärt das auch die 3 cyles zum senden
der Zeilenadresse.</div>
<div> </div>
<div>Jedes 'X' steht für 64 Byte</div>
<div> </div>
<div><span> col 0 ------------>
col 2111</span></div>
<div><span> | |</span></div>
<div><span> +- Page 0: XXXX XXXX XXXX XXXX X
<-- row 0<br>
| Page 1: XXXX XXXX XXXX XXXX X
<-- row 1<br>
| Page 2: XXXX XXXX XXXX XXXX X
<-- row 2<br>
|<br>
Block 0: -+ . . .<br>
|<br>
| Page 61: XXXX XXXX XXXX XXXX X
<-- row 61<br>
| Page 62: XXXX XXXX XXXX XXXX X
<-- row 62<br>
+- Page 63: XXXX XXXX XXXX XXXX X
<-- row 63</span></div>
<div><span> +- Page 64: XXXX XXXX XXXX XXXX X
<-- row 64<br>
| Page 65: XXXX XXXX XXXX XXXX X
<-- row 65<br>
| Page 66: XXXX XXXX XXXX XXXX X
<-- row 66<br>
|<br>
Block 1: -+ . . .<br>
|<br>
| Page 125: XXXX XXXX XXXX XXXX X <--
row 125<br>
| Page 126: XXXX XXXX XXXX XXXX X <--
row 126<br>
+- Page 127: XXXX XXXX XXXX XXXX X <--
row 127</span></div>
<div><span> . . .</span></div>
<div><span> +- Page 262080: XXXX XXXX XXXX XXXX X
<-- row 262080<br>
| Page 262081: XXXX XXXX XXXX XXXX X <--
row 262081<br>
| Page 262081: XXXX XXXX XXXX XXXX X <--
row 262081<br>
|<br>
Block 4095: -+ . . .<br>
|<br>
| Page 262141: XXXX XXXX XXXX XXXX X <--
row 262143<br>
| Page 262142: XXXX XXXX XXXX XXXX X <--
row 262143<br>
+- Page 262143: XXXX XXXX XXXX XXXX X <--
row 262143</span></div>
<div> </div>
<div>Die Einteilung in Pages und Blocks ist den physikalischen
Eigenschaften von Flash Speichern geschuldet. Löschen
bedeutet normalerweise alle Bits des Speichers auf '1' zu
setzen und das geht durch anlegen einer Programmierspannung
auf großen Speicherbereichen recht schnell (da identisches
Bitmuster). Daher sind Blöcke eher für Löschoperationen
relevant.</div>
<div><br>
Schreiben des Speichers (Programmieren) bedeutet fast immer
vereinzelte Bits auf '0' zu setzen und benötigt bei Flash
Speichern meistens mehrere Programmierpulse hintereindander.
Das ist deutlich aufwändiger weil auch Spannung und Strom
bei den einzelnen Pulsen variiert wird um die Lebensdauer
der Flash Zelle zu schonen. Deswegen und auch wegen der
Performance beim lesen/Schreiben mit Caches ist für
Programmieren und Lesen meist die Page Größe interessant.</div>
<div> </div>
<div><strong>Und um nochmal auf den Beginn der Frage
zurückzukommen:</strong></div>
<div> </div>
<div> <em>- NAND-Reset (0xff, no cycles)</em></div>
<div> </div>
<div>Damit wird der Flash Controller un einen Default Zustand
versetzt und alle evlt. noch nicht beendeten
Lese-/Programmier-/Löschzyklen abgebrochen und die Status
Register auf 0xCO gesetzt.</div>
<div> </div>
<div> <em>- NAND-Read (0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30)</em></div>
<div> </div>
<div>Mit diesem Kommando (READ1 = 0x00 cc cc rr rr rr 0x30)
wird ein Lesen (Laden in den Page Cache) der Page 0<br>
angetriggert (col = 0, row = 0)</div>
<div> </div>
<div> <em>- und dann ein weiteres Command mit dem
"Continue" bit gesetzt, aber nur "ein" write ins command
register.</em></div>
<div> </div>
<div>Da passiert vermutlich ein READ CACHE (SEQUENTIAL) = 0x31
um ohne erneutes schreiben einer Adresse die nächste<br>
Page lesen zu können. Diese Kommando setzt den column index
automatisch auf 0 und durch triggern der #RE kann dann<br>
die diese Page wieder von Beginn an Byte für Byte gelesen
werden.</div>
<div> </div>
<div><strong>Wegen der "Register" ab Adresse 0x0404A000 würde
ich noch ein paar Wetten abgeben:</strong></div>
<div> </div>
<div>Ich gehe davon aus das an (min.) zwei dieser Adressen die
beiden Status Register des Flash Controllers gemapped sind:</div>
<div> </div>
<div><span>Status Register:</span></div>
<div><span> Mode / Bit: | 7 | 6 | 5 | 4 | 3
| 2 | 1 | 0 |<br>
Page Program | WP | R/B | R/B | - | - | -
| - | P/F |<br>
Blocke Erase | WP | R/B | R/B | - | - | -
| - | P/F |<br>
Read | WP | R/B | R/B | - | - | -
| - | - |<br>
Cache Read | - | R/B | P/E/R | - | - | -
| - | - |</span></div>
<div><span> WP ...... Write Protect ( '0' = protected, '1'
= not protected )<br>
R/B ..... Ready / Busy ( Bit 6: '0' = busy, '1' =
ready | Bit 5: '0' = active, '1' = idle )<br>
P/F ..... Pass / Fail ( '0' = pass, '1' = fail )<br>
P/E/R ... P/E/R Controler Bit ( '0' = active, '1' =
idle )</span></div>
<div> </div>
<div><span>EDC Status Register:</span></div>
<div><span> Mode / Bit: | 7 | 6 | 5 | 4 | 3
| 2 | 1 | 0 |<br>
Copy Back Program | WP | R/B | R/B | - | - |
EDC_V | EDC_S | P/F |</span></div>
<div><span> WP ...... Write Protect ( '0' = protected, '1'
= not protected )<br>
R/B ..... Ready / Busy ( '0' = busy, '1' = ready )<br>
EDC_V ... EDC Validity ( '0' = invalid, '1' = valid )<br>
EDC_S ... EDC status ( '0' = no error, '1' = error )<br>
P/F ..... Pass / Fail ( '0' = pass, '1' = fail )</span></div>
<div> </div>
<div>Das die restlichen 5 Register was mit den Adresszyklen zu
tun haben glaube ich eher nicht. Ich würde fast von der
folgenden Variante ausgehen, wobei die Zuordnung zu den
Adressen willkürlich ist.</div>
<div> </div>
<div><span> 0x0404A000 = COMMAND (1st cycle) <= scheint
ja verifiziert zu sein<br>
0x0404A004 = COMMAND (2nd cycle) ???<br>
0x0404A008 = COMMAND (3rd cycle) ???<br>
0x0404A00C = COMMAND (4th cycle) ???<br>
0x0404A010 = ROW ???<br>
0x0404A014 = COLUMN ???<br>
0x0404A018 = STATUS REGISTER ???<br>
0x0404A01C = EDC STATUS REGISTER ???</span></div>
<div> </div>
<div>Das ist mein Tipp, da bei allen Kommandos mit mehr als
einem Byte die Zeilen und Spalten Adressen immer zwischen
den Kommando Bytes gesendet werden.</div>
</div>
<div>
<div>
<div name="quote">
<div><b>Gesendet:</b> Montag, 04. Januar 2021 um 00:28 Uhr<br>
<b>Von:</b> "Sven A. Huerlimann via tiptoi-hw"
<a class="moz-txt-link-rfc2396E" href="mailto:tiptoi-hw@lists.nomeata.de"><tiptoi-hw@lists.nomeata.de></a><br>
<b>An:</b> <a class="moz-txt-link-abbreviated" href="mailto:tiptoi-hw@lists.nomeata.de">tiptoi-hw@lists.nomeata.de</a><br>
<b>Cc:</b> "Sven A. Huerlimann" <a class="moz-txt-link-rfc2396E" href="mailto:sh@sighup.ch"><sh@sighup.ch></a><br>
<b>Betreff:</b> Re: [Tiptoi-hw] Nochmals-Frage bez.
NAND-Access</div>
<div name="quoted-content">
<p>Sehr geil! Danke! Das hilft immens.</p>
<p>Column == Page und Row == Block? Da steh ich noch auf
dem Schlauch.</p>
<p>Gruss und vielen Dank</p>
<p>Sven</p>
<div class="moz-cite-prefix">On 03.01.21 19:27, Erwin
Pschernig via tiptoi-hw wrote:</div>
<blockquote>
<div>
<div>Hallo zusammen,</div>
<div> </div>
<div>erstmal ein gutes neues Jahr und Grüße von
einem der bisher nur mitgelesen, aber das sollte
sich in Zukunft hoffentlich ändern.</div>
<div>Für richtige Hilfe muß ich mich noch ein wenig
einlesen und selbst ein wenig rumspielen sobald
ich auch eine Bastelstift habe [ Danke @Matthias
für das Angebot :-) ].</div>
<div> </div>
<div>Aber vorab kann ich hier bei dem Thema evtl.
mit ein paar Grundlagen weiter helfen.</div>
<div> </div>
<div>Ich habe mir auch das Datenblatt mal kurz
durchgeschaut und kann folgende Erklärungen
beisteuern.</div>
<div> </div>
<div>Der hier angesprochene NAND Flash ist eine
etwas aufwändigere (schnellere) Variante und man
kann nicht direkt auf den eigentlichen Flash
zugreifen sonden wählt durch das READ1 Kommando
eine Page aus welche in den schnellen "read cache"
geladen wird. Daher kommt auch der recht große
Unterschied zwischen random access (25us max) und
sequential read (min 25ns = Faktor 1000
schneller).</div>
<div> </div>
<div>Der NAND Flash ist wie alle gängigen Flash
Bausteine in Pages und Blocks unterteilt um
gewisse Operation (z.Bsp. Löschen) performanter zu
gestalten.</div>
<div>Bei dieser Variante hat eine Page 2 kByte und
ein Block 128 kByte.</div>
<div> </div>
<div>Da Flash generell ein unsicherer Speicher ist
und immer mal wieder eine Zelle kaputt wird hat
jede Page noch ein paar (64) zusätzliche Bytes um
solche auszugleichen.</div>
<div> </div>
<div>Damit ändert sich die Größe einer Page auf 2112
Byte ( 2 * 1024 + 64 ) was exakt der Cache größe
entspricht.</div>
<div> </div>
<div>Das Kommando READ1 "00 cc cc rr rr rr 30"
braucht auch column (cc cc) und row (rr rr rr) zum
Auswählen der Speicherzelle. Hier erkennt man auch
Aufgrund der Tatsache das die Address zwischen den
beiden Kommandobytes kommt den Cache Vorgang.</div>
<div> </div>
<div>Solange kein weiteres READ1 Kommando kommt kann
man nun durch Toggeln der #RE Leitung nacheinander
die gesammten Bytes der Page sequentiell auslesen
(das von Matthias angesprochene auto increment),
denn mit jedem #RE toggeln wird die column address
im 1 oder 2 Byte incrementiert (abhängig ob x8
oder x16 Variante). Und es geht hier noch besser,
um die nächste Page zu lesen reicht es ein
Kommando READ CACHE (SEQUENTIAL) = 31h zu senden
und die nächsten 2112 Byte können gelesen werden,
ohne das erneut eine Adresse gesendet werden muß.</div>
<div> </div>
<div>Mit dieser Sequenz kann man also beginnend von
der Adresse 0 den ganzen Speicher linear auslesen
und muß dafür NUR die einmal eine Adresse angeben.</div>
<div> </div>
<div>Damit ergibt sich für diesen Chip folgende
Schlußfolgerung:</div>
<div> </div>
<div>row address = page ID</div>
<div>column addres = byte/word address inside a page</div>
<div> </div>
<div>Ich hoffe das hilft ein wenig zum Verständnis.</div>
<div>
<div>LG Erwin</div>
<div>
<div>
<div>
<div><b>Gesendet:</b> Sonntag, 03. Januar
2021 um 18:20 Uhr<br>
<b>Von:</b> "Sven A. Huerlimann via
tiptoi-hw" <a
class="moz-txt-link-rfc2396E"
href="mailto:tiptoi-hw@lists.nomeata.de"
target="_blank" moz-do-not-send="true"><tiptoi-hw@lists.nomeata.de></a><br>
<b>An:</b> <a
class="moz-txt-link-abbreviated"
href="mailto:tiptoi-hw@lists.nomeata.de"
target="_blank" moz-do-not-send="true">tiptoi-hw@lists.nomeata.de</a><br>
<b>Cc:</b> "Sven A. Huerlimann" <a
class="moz-txt-link-rfc2396E"
href="mailto:sh@sighup.ch"
target="_blank" moz-do-not-send="true"><sh@sighup.ch></a><br>
<b>Betreff:</b> Re: [Tiptoi-hw]
Nochmals-Frage bez. NAND-Access</div>
<div>
<p>Servus!</p>
<div class="moz-cite-prefix">On 03.01.21
12:35, Matthias Weber via tiptoi-hw
wrote:</div>
<blockquote>
<p>Hallo!</p>
<div class="moz-cite-prefix">Sven A.
Huerlimann via tiptoi-hw wrote:</div>
<blockquote>
<pre class="moz-quote-pre">Hallo zusammen, ein gutes Neues!
Ich hab nochmals ein Verständnisproblem beim NAND Controller, ev. kann
mir da jemand weiterhelfen:
Ich hab ein halbwegs brauchbares Fundament für die NFC-Emulation. Ein
ungefähres Gespür für die Register und den Ablauf einer Flash-Read
Operation.</pre>
</blockquote>
<p>Uh, war kurz verwirrt. NFC = NAND
Flash Controller?</p>
<p>Für mich hat sich NFC als <span>Near
Field Communication eingebrannt.</span></p>
</blockquote>
Genau.. Bei mir eigentlich auch, aber
irgendwann hab ich kapituliert und das
Anyka-Wording übernommen.
<blockquote>
<p> </p>
<blockquote>
<pre class="moz-quote-pre">Was ich jetzt sehe, ist das die FW folgendes macht:
- NAND-Reset (0xff, no cycles)
- NAND-Read (0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30)
- und dann ein weiteres Command mit dem "Continue" bit gesetzt, aber nur
"ein" write ins command register.</pre>
</blockquote>
<p>Kannst du kurz nochmal erläutern, was
du mit der Beschreibung in den
Klammern meinst? Beziehst du dich
immer auf das Kommando?</p>
</blockquote>
<p>Jup. Der NFC hat ein Register an
0x0404a000 (nennen wir es mal
NFC_COMMAND) und darüber (0ffset 0x04 -
0x1C) weitere Register im
opensource-treiber nicht explizit
benannt sind, aber offenbar die weiteren
Cycle abbilden.</p>
<p>Ein Read-Cycle mit Addresse schreibt
zum Beispiel (Sorry fürs Spamen und die
etwas infantile Formatierung):</p>
<p>nfc status write<br>
Command valid bit set<br>
Chipselect asserted<br>
NFC_CTRL_REG_CE_SAVE_BIT asserted<br>
nfc status<br>
nfc status write<br>
Start of Command Cyce
///////////////////////////////////////////////<br>
NFC_COMMAND write (cycle 0): 00000064<br>
NFC_CMD_REG_CMD_BIT write<br>
WRITE ENABLE<br>
COMMAND LATCH ENABLE<br>
ADDRESSS LATCH DISABLE<br>
NFC_CMD_REG_CMD_CONF
++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>
Commmand Cycle<br>
NFC_COMMAND write (cycle 1): 00000062<br>
NFC_CMD_REG_CMD_BIT write<br>
WRITE ENABLE<br>
COMMAND LATCH DISABLE<br>
ADDRESSS LATCH ENABLE<br>
NFC_CMD_REG_ADD_CONF
========================================================<br>
00000062<br>
NFC_COMMAND write (cycle 2): 00000062<br>
NFC_CMD_REG_CMD_BIT write<br>
WRITE ENABLE<br>
COMMAND LATCH DISABLE<br>
ADDRESSS LATCH ENABLE<br>
NFC_CMD_REG_ADD_CONF
========================================================<br>
00000062<br>
NFC_COMMAND write (cycle 3): 00000062<br>
NFC_CMD_REG_CMD_BIT write<br>
WRITE ENABLE<br>
COMMAND LATCH DISABLE<br>
ADDRESSS LATCH ENABLE<br>
NFC_CMD_REG_ADD_CONF
========================================================<br>
00000062<br>
NFC_COMMAND write (cycle 4): 00000062<br>
NFC_CMD_REG_CMD_BIT write<br>
WRITE ENABLE<br>
COMMAND LATCH DISABLE<br>
ADDRESSS LATCH ENABLE<br>
NFC_CMD_REG_ADD_CONF
========================================================<br>
00000062<br>
NFC_COMMAND write (cycle 5): 00000062<br>
NFC_CMD_REG_CMD_BIT write<br>
WRITE ENABLE<br>
COMMAND LATCH DISABLE<br>
ADDRESSS LATCH ENABLE<br>
NFC_CMD_REG_ADD_CONF
========================================================<br>
00000062<br>
NFC_COMMAND write (cycle 6): 00018064<br>
NFC_CMD_REG_INFO_POS write: 0030<br>
NFC_CMD_REG_CMD_BIT write<br>
WRITE ENABLE<br>
COMMAND LATCH ENABLE<br>
ADDRESSS LATCH DISABLE<br>
NFC_CMD_REG_CMD_CONF
++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>
NFC_COMMAND write (cycle 7): 0001dc01<br>
NFC_CMD_REG_INFO_POS write: 003b<br>
NFC_CMD_REG_DELAY_BIT write<br>
WRTIE DISABLE<br>
COMMAND LATCH DISABLE<br>
ADDRESSS LATCH DISABLE<br>
NFC_CMD_REG_DELAY_BIT
-------------------------------------------------------<br>
EEEENNNNNDDDD of TRANSACTION
oooooooooooooooooooooooooooooooooooo<br>
NFC_CMD_REG_LAST_BIT write<br>
End Cycle<br>
Got NAND command: 00, Address: 00, 00,
00, 00, 00, End: 30, Delay: 3b<br>
EEEENNNNNDDDD of TRANSACTION
oooooooooooooooooooooooooooooooooooo</p>
<blockquote>
<p> </p>
<p>Ich habe gerade das Datenblatt eines
HY27UF084G2B und <a
class="moz-txt-link-freetext"
href="https://github.com/maehw/ftdi-nand-flash-reader/blob/master/bitbang_ft2232.c"
target="_blank"
moz-do-not-send="true">https://github.com/maehw/ftdi-nand-flash-reader/blob/master/bitbang_ft2232.c</a>
befragt.</p>
<p>0x00 0x30 ist ein Page Read (READ1)
Kommando. Zwischen 0x00 und 0x30
kommen 5 Adress-Bytes (2x Spalte, 3x
Zeile).</p>
<p>Und dann werden bei einer Page
wahrscheinlich <span class="pl-c1">2112
Bytes am Stück gelesen. Vielleicht
siehst du das und ein interner
Puffer füllt sich?</span></p>
</blockquote>
<p>Ok. Hier ist das Problem, dass ich ja
den Puffer füllen muss :)</p>
<p>Ich denk ich schaufel einfach mal 2112
Bytes und sehe was passiert.</p>
<blockquote>
<p> </p>
<blockquote>
<pre class="moz-quote-pre">Meine naive Annahme: Read-Cycle setzt mal auf (Startadresse, etc. etc.)
und danach kann mit diesem "Continue" einfach die nächste
Page?Block?Sector?Huga abgefragt werden?</pre>
</blockquote>
<p>Bei SPI-Flash kenne ich das, dass man
keine weiteren Adressen explizit
angeben muss. Hier könnte ich mir
vorstellen, dass der NAND Flash
Controller einen Autoinkrement
durchführt.</p>
</blockquote>
Was wird dann inkrementiert? Zeile?
Spalte? Da magelts bei mir stark an
Durchblick.
<blockquote>
<p> </p>
Gruß<br>
Matthias</blockquote>
Gruss Sven
<blockquote>
<fieldset class="mimeAttachmentHeader"> </fieldset>
<pre class="moz-quote-pre">_______________________________________________
tiptoi-hw mailing list
<a class="moz-txt-link-abbreviated" href="mailto:tiptoi-hw@lists.nomeata.de" target="_blank" moz-do-not-send="true">tiptoi-hw@lists.nomeata.de</a>
<a class="moz-txt-link-freetext" href="https://lists.nomeata.de/mailman/listinfo/tiptoi-hw" target="_blank" moz-do-not-send="true">https://lists.nomeata.de/mailman/listinfo/tiptoi-hw</a>
</pre>
</blockquote>
_______________________________________________ tiptoi-hw mailing list <a
class="moz-txt-link-abbreviated"
href="mailto:tiptoi-hw@lists.nomeata.de"
target="_blank" moz-do-not-send="true">tiptoi-hw@lists.nomeata.de</a>
<a
href="https://lists.nomeata.de/mailman/listinfo/tiptoi-hw"
target="_blank" moz-do-not-send="true">https://lists.nomeata.de/mailman/listinfo/tiptoi-hw</a></div>
</div>
</div>
</div>
</div>
</div>
<fieldset class="mimeAttachmentHeader"> </fieldset>
<pre class="moz-quote-pre">_______________________________________________
tiptoi-hw mailing list
<a class="moz-txt-link-abbreviated" href="mailto:tiptoi-hw@lists.nomeata.de" target="_blank" moz-do-not-send="true">tiptoi-hw@lists.nomeata.de</a>
<a class="moz-txt-link-freetext" href="https://lists.nomeata.de/mailman/listinfo/tiptoi-hw" target="_blank" moz-do-not-send="true">https://lists.nomeata.de/mailman/listinfo/tiptoi-hw</a>
</pre>
</blockquote>
_______________________________________________
tiptoi-hw mailing list <a class="moz-txt-link-abbreviated" href="mailto:tiptoi-hw@lists.nomeata.de">tiptoi-hw@lists.nomeata.de</a> <a
href="https://lists.nomeata.de/mailman/listinfo/tiptoi-hw"
target="_blank" moz-do-not-send="true">https://lists.nomeata.de/mailman/listinfo/tiptoi-hw</a></div>
</div>
</div>
</div>
</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<pre class="moz-quote-pre" wrap="">_______________________________________________
tiptoi-hw mailing list
<a class="moz-txt-link-abbreviated" href="mailto:tiptoi-hw@lists.nomeata.de">tiptoi-hw@lists.nomeata.de</a>
<a class="moz-txt-link-freetext" href="https://lists.nomeata.de/mailman/listinfo/tiptoi-hw">https://lists.nomeata.de/mailman/listinfo/tiptoi-hw</a>
</pre>
</blockquote>
</body>
</html>