Hallo, ich möchte die Programmiersequenz für ein Flash-ROM in C realisieren. Es müssen laut Datenblatt nacheinander in bestimmte Adressen bestimmte Werte geschrieben werden, um das Flash zu "entriegeln". Dann werden die eigentlichen Daten erst programmiert. Die ganze Operation benötigt laut Datenblatt 4 Buszyklen (es sind 4 Schreibvorgänge auszuführen). Wie kann ich in C realisieren, dass die Schreiboperationen jeweils nur einen Zyklus lang dauern? Lässt sich das über Pointer realisieren? Im Anhang befindet sich eine Tabelle mit den entsprechenden Kommandos. Das Datenblatt zum Flash findet sich hier: http://www.datasheetarchive.com/datasheet.php?article=780262 Könnte mir jemand vielleicht eine Beispielfunktion posten? Weiß im Moment nicht wie ich das Problem angehen soll. Gruß TechInfo
Woher weiss denn dein Flash, wie lange ein 'Buszyklus' auf deinem Atmel dauert? Eben. Hast du schon mal probiert einfach die Signale in der richtigen Reihenfolge, wie im Datenblatt beschrieben, an den IC anzulegen?
Erstens benutze ich keinen Atmel, sondern einen MicroBlaze-Softcore auf einem Xilinx FPGA. Zweitens: Die Hardware ist mir vorgegeben, die Platine fertig "verdrahtet". Experimentieren kann ich da nicht mehr. Ich kann quasi nur über den Prozessor irgendetwas erreichen. Welche Signale meinst du denn?
Meiner Meinung nach richtet sich die Länge des Buszyklus auch nicht nach dem Controller sondern nach den Angaben im Datenblatt des Flash-Bausteins, oder nicht?
Hallo, der Flash muß ja letztlich irgendwo angeschlossen sein... Hängt er am Prozessor-Bus bestimmt der Prozessor den Ablauf des Zyklus und das Flash muß mit seinen Wünschen dazu passen, sonst kann man es eben nicht an diesen Prozessorbus anschließen. Hängt es an irgendwelchen Ports bestimmst Du "zu Fuß" das Timing, denn Du setzt per Programm die Leitungen auf L oder H. Auch bei einer fertig verdrahteten Platine trifft das so zu. Du muß also wissen, wie der Flash angeschlossen ist und wie Du mit der gegeben Hardware das Verhalten erreichen kannst. Dann kommt kann erst die Frage geklärt werden, wie das in C umzusetzen geht. Gruß aus Berlin Michael
TechInfo wrote: > Erstens benutze ich keinen Atmel, sondern einen MicroBlaze-Softcore auf > einem Xilinx FPGA. Richtig. Vergess ich immer wieder. > > Zweitens: Die Hardware ist mir vorgegeben, die Platine fertig > "verdrahtet". Experimentieren kann ich da nicht mehr. Ich kann quasi nur > über den Prozessor irgendetwas erreichen. > > Welche Signale meinst du denn? Na die ganze WE (Write Enable), CE (Chip Enable) und sonstige Steuersignale. Aber wie Michael schon richtig sagte: Wie ist das Teil angeschlossen? Da ich von einem Atmel ausgegangen bin, war es für mich klar, dass der an einem Port hängt. Aber das muss ja nicht so sein.
TechInfo wrote: > Meiner Meinung nach richtet sich die Länge des Buszyklus auch nicht nach > dem Controller sondern nach den Angaben im Datenblatt des > Flash-Bausteins, oder nicht? Richtig. Und im Datenblatt hab ich beim schnellen drüberscrollen nur Mindest-Timings gesehen, keine Maximalzeiten. Also wird das so gehen, wie sonst auch: Daten anlegen mit den Steuersignalen wackeln (WE/CE und was es sonst noch gibt) Woraufhin der Baustein die Daten übernimmt und einen Zyklus für abgeschlossen erklärt. Dann kommt der nächste Zyklus dran: Daten des nächsten Zyklus anlegen und mit den Control Leitungen wackeln etc. etc.
Der Flash hängt über einen Softcore-Memory-Controller am On-Chip-Peripheral-Bus des Prozessors. Da ich Daten aus dem Flash über die Debug-Schnittstelle auslesen kann, gehe ich davon aus dass beides zueinander passt. Auf die Bus-Leitungen habe ich als Programmierer gar keinen Zugriff. Wie müßte die C-Routine in diesem Fall aussehen?
Laut Hardware-Designer, der den Microblaze konfiguriert hat, muss ich mich auch nicht um die Signalleitungen kümmern sondern mein Weg muss sein, über die Kommandosequenzen auf das Flash zuzugreifen. Er könne mir aber nicht sagen, ob ich noch waitstates oder ähnliches einfügen muss, da das Flash sicher langsamer reagiert als der Prozessor. Hoffe das sind jetzt genug Infos ;)
TechInfo wrote: > Der Flash hängt über einen Softcore-Memory-Controller am > On-Chip-Peripheral-Bus des Prozessors. Da ich Daten aus dem Flash über > die Debug-Schnittstelle auslesen kann, gehe ich davon aus dass beides > zueinander passt. Auf die Bus-Leitungen habe ich als Programmierer gar > keinen Zugriff. Alles klar. Dann bin ich draussen. > muss ich mich auch nicht um die Signalleitungen kümmern > sondern mein Weg muss sein, über die Kommandosequenzen > auf das Flash zuzugreifen Die wirst du wahrscheinlich über den Memory Controller zum Flash schicken. Oder macht man das, indem man auf bestimmte Adressen zugreift? Sprich: Stellt der Memory Controller irgendwelche Register bereit, in die du die zu übertragenden Daten heineinschreibst und der Memory Controller handelt dann den Bus? > Er könne mir aber nicht sagen, ob ich noch waitstates oder > ähnliches einfügen muss, da das Flash sicher langsamer > reagiert als der Prozessor Da würde ich sagen: Ausprobieren. Auf jeden Fall steht aber eines fest: Dein Problem sind (noch) nicht die C Routinen, sondern: Wie funktioniert das eigentlich auf Hardware (M-Controller) Ebene. Wenn du das weist, ist auch eine C Funktion kein Problem mehr.
So wie ich das im Datenblatt verstehe, muss ich bestimmte Werte in bestimmte Adressen des Flash-ROMs schreiben. Dadurch wird der "embedded program algorithm" des Flash-ROMs aktiv und ich schicke die eigentlich zu schreibenden Daten hinterher. Der Memory Controller sollte das eigentlich ohne mein Zutun managen können. Falls es hilft, im Anhang das Datenblatt des MCs.
Der Memory Controller mappt Dir das Flash an einen bestimmte Basis-Adresse. Diese Basis-Adress muß dir der HW-Programmierer, der den Softcore konfiguriert hat sagen. Von dieser Basis-Adresse weg zählen die Adressen des Flash-ROMs. Für den Prozessor ist also Adresse 0x100 des Flashs = Basis-Adresse + 0x100. Aufpassen muß man auf die Busbreite, der Microblaze zählt glaube ich Bytes, die Adresse für das Flash könnten 16-Bit Adressen sein. Der Memory Controller macht eine Konvertierung der Busbreiten, dazu soll der HW-Designer genaueres wissen. uint16 *baseptr = BASE_FLASH; Lesen Adresse 0x100 des Flash in C : val = *(baseptr + 0x100); Schreiben Adresse 0x100 des Flash : *(baseptr+ 0x100) = val; Vielleicht hilfts. Klaus
Vielen Dank. Die Basisadresse ist mir bekannt (0xC00000). Ich habe jetzt folgendes probiert:
1 | *((short*)0xC00555)=0xAA; |
2 | *((short*)0xC002AA)=0x55; |
3 | *((short*)0xC00555)=0xA0; |
4 | *((short*)0xC0F000)=150; |
ich setze dann einen breakpoint und lese danach 0xC0F000 aus. Die Adresse enthält allerdings nicht den Wert 150 sondern 32. Die Flash-Adressen sind tatsächlich 16 Bit breit. Zu der Umsetzung konnte mir der HW-Entwickler aber auch nichts sagen und verwies darauf, dass es beim externen SRAM ja auch richtig umgesetzt wird.
Schnellschuß : Wenn die Flash-Adressen in 16 Bit zählen, dann muß man vielleicht die Adresse 0xC00000 + 2 * 555 ansprechen.
Und noch eine Frage: Wenn man den Wert von Adresse 0xC00000 ausliest und dann 0x0000FFFF ausgegeben wird, hat 0xC00000 bei 16 Bit doch den Wert FF, 0xC00001 den Wert FF, 0xC00002 den Wert 00 usw., oder?
Nicht unbedingt. Ersteres scheint ein 32-Bit-Zugriff zu sein - kann das Dein Controller, Dein Speichercontroller und das Flash-ROM? Zweitens ist die Reihenfolge der vier Bytes, aus denen sich ein 32-Bit-Wort zusammensetzt, vom jeweiligen Controller abhängig - Stichwort "Endian-ness". "Big-Endian" (Motorola): Das 32-Bit-Wort 0x12345678 wird als Bytefolge 0x12, 0x34, 0x56, 0x78 an aufeinanderfolgenden Speicheradressen abgelegt - so, wie Du es eingangs vermutet hast. "Little-Endian" (Intel): Das 32-Bit-Wort 0x12345678 wird als Bytefolge 0x78, 0x56, 0x34, 0x12 an aufeinanderfolgenden Speicheradressen abgelegt - also ganz anders.
Wie der Zugriff erfolgt, weiß ich nicht. Der Speicher ist jedenfalls in 16-Bit-Worten organisiert.
Müßte nicht, wenn der Speicher 16-bittig organisiert ist, jede Adresse 16 Bit Daten enthalten? Also 0x12345678 wird zu 0x1234 auf 0xC0000 und 0x5678 auf 0xC0001. Oder mache ich einen Denkfehler?
Ich kenne den MicroBlaze nicht 100% genau, deshalb kann das folgende auch falsch sein. Normalerweise werden die Adressen für den Prozessor in Byte gezählt. 16 Bit Daten liegen deshalb immer in 2er Schritten an Adressen, 32 Bit Daten in 4er Schritten. 0xC00000 .. Word 0 für das Flash 0xC00002 .. Word 1 für das Flash ... usw. Deshalb die von mir vorgeschlagene Multiplikation mit 2. Laut Beschreibung des Memory-Controllers muß man achtgeben, daß der Prozessor wirklich einen 16 Bit Zugriff ausführt. Wenn der Datentyp short 16 Bit ist, dann sollte der von Dir verwendete cast korrekt sein. Mit uint16_t aus <stdint.h> bist Du sicher. *((short*)(0xC00000L + 2 * 0x0555))=0xAA; ... Klaus
Achso, ich ging bisher davon aus dass EINE Adresse bei einem 16-bittigen Speicher auch 16 Bit aufnehmen kann. Wenn die Adressen allerdings weiter 8-Bit-weise gezählt werden, ist mir deine Überlegung klar. Danke, werde es morgen mal ausprobieren. Genügt die Typumwandlung mit uint16_t, um einen 16-Bit-Zugriff zu gewährleisten, oder könnte der Prozessor intern trotzdem mit 8-Bit zugreifen?
Der MicroBlaze ist ein 32 Bit Prozessor, der würde eher 32 Bit Zugriffe machen.
TechInfo wrote: > Die Flash-Adressen sind tatsächlich 16 Bit breit. Zu der Umsetzung > konnte mir der HW-Entwickler aber auch nichts sagen und verwies darauf, > dass es beim externen SRAM ja auch richtig umgesetzt wird. Na das ist aber ein Armutszeugnis, wenn nicht mal der HW-Entwickler weiß, wie er den Flash verschaltet hat. Schmeiß ihm das Board vor die Füße. Und das der SRAM geht, hat überhaupt nichts zu bedeuten, SRAM ist kein Flash. Bei SRAM kann man Adressen und Daten beliebig anschließen. Der genannte Flash-Typ ist jedenfalls 16Bit und muß daher auch 16bittig angesprochen werden. Du mußt also die 16Bit Zugriffe der CPU benutzen. Ein 32Bit Zugriff wird warscheinlich in 2 aufeinanderfolgende 16Bit aufgeteilt und vorbei ist es mit der erforderlichen Enable-Sequenz. Auch sollten alle Interrupts gesperrt sein, damit nicht andere Zugrife dazwischen funken. Peter
Ein Zugriff auf eine uint16_t Variable oder Adresse sollte genügen: *((uint16_t*)(0xC00000L + 2 * 0x0555)) = 0x00AA;
Also wie besprochen. Wofür steht eigentlich das L hinter der Adresse? long-Konstante? Warum ist das nötig? Habe mir grade mal mehrere Speicheradressen im Debugger ausgeben lassen. 800000 0000FFFF 800004 0000FFFF 800008 0000FFFF Deutet also auf byteweise gezählte Adressen hin.
Wenn ich mir im Debugger Speicherbereiche im Flash zur Laufzeit angucke, ändert sich nach jedem Step der Inhalt der ersten angezeigten Adresse, egal wie der Code grade aussieht. Auch die Inhalte anderer Adressen ändern sich von Zeit zu Zeit. Ist dieses Verhalten normal? Oder ist das ein Anzeige-Fehler? Normalerweise dürfte sich in diesen Speicherbereichen doch nichts ändern. Speichert man den Wert einer Flash-Adresse in einer Variable, kommt immer 32 heraus. Obwohl die Adressen anscheinend alle mit 0x0000FFFF vorbelegt. Das versteh wer will.
Das lässt darauf schließen, daß der Speichercontroller wohl nicht so funktioniert, wie er sollte. Wenn ein Flash mehrfach ausgelesen wird, liefert es JEDESMAL denselben Wert. Wenn das nicht im Debugger ankommt, ist irgendwas sehr, sehr kaputt.
Hallo, bin nun soweit dass er etwas in das Flash schreibt, und zwar mit folgendem Code:
1 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA; |
2 | *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; |
3 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00A0; //Flash jetzt entriegelt |
4 | |
5 | *((short*)(0xC0F060))=8; //Flash beschreiben |
Schaue ich mir mit dem Debugger die Adresse an, steht dort folgendes: C0F060 DFFF0008 C0F064 0008FFFF Warum die 8 jetzt zweimal im Speicher steht, keine Ahnung. Auch wundert es mich dass ich im Code in der letzten Zeile die Adresse nicht mal 2 nehmen muss. Damit funktioniert es nämlich nicht. Lässt man dagegen in den 3 Zeilen darüber Verdopplung weg, geht es auch nicht. Kann sich da irgendjemand einen Reim drauf machen, oder ist das Flash einfach falsch angeschlossen?
> Auch wundert es mich dass ich im Code in der letzten Zeile die Adresse > nicht mal 2 nehmen muss. Damit funktioniert es nämlich nicht. Wieso, stimmt doch. Wenn Du an die Stelle 0xC0060 schreibst, dann stehts auch an dieser Stelle drin. Adresse 0xC0060 entspricht zwar Adresse 0x30 für das Flash, weil dieses 16 Bit Worte speichert, aber im Adressraum des Microblaze liegen diese an Byte Adressen. Adresse 0x60 für das Flash steht im Adressraum des MicroBlaze an 0xC000C0. Du darfst nur keine ungeraden Adressen schreiben, weil der Memory Controller das dann auf 2 Worte aufteilen wird, und dann kommt ein Blödsinn herausl Für Dich als Programmierer hast Du jetzt zwischen 0x0C00000 und 0xFFFFFF den Flash Adressraum zur Verfügung. Warum das Auslesen so merkwürdig ist, weiß ich auf die Schnelle nicht. Vielleicht hängt es damit zusammen, daß Du einen 32 Bit Lese-Zugriff machst, der vom Memory-Kontroller nicht korrekt umgesetzt wird. Vielleicht muß man das Flash auch mit 16 Bit Zugriffen lesen.
...ist zwar bascom aber die programmiersequenz ist gleich und leicht verständlich, da ich die ports komplett hinterher übernehme. man kann also im code direkt nachvollziehen, was an data/adr anliegt. Beitrag "M32 Bascom Programm zum Beschreiben von AM29F040 Flash"
@Klaus Falser Klaro, du hast Recht, wieder was gelernt. Habe noch ein bißchen rumgespielt und anstatt short-Pointer char benutzt. Dann sieht die Ausgabe folgendermaßen aus: C0F060 DFFF0808 C0F064 0808FFFF Bei long funktioniert es nicht. @Heyn Das ist schon ein Unterschied, weil du ja auch auf die Steuerleitungen zugreifst. Bei mir hängt das Flash ja an einem Bus.
Noch eine Verständnisfrage: Wenn ich den Wert 8 in 0xC0F060 ablege, müßte das dann nicht so aussehen: C0F060 0008FFFF anstatt C0F060 FFFF0008 Denn C0F060 steht doch für das erste Paar Ziffern. Bei fängt der Wert ja eigentlich in C0F062 an.
> 800004 0000FFFF > 800008 0000FFFF > Deutet also auf byteweise gezählte Adressen hin. Nein. Es deutet auf einen unglücklich eingestellten Debugger und auf 16-Bit Adressierung hin. Ein besser eingestellter Debugger würde ausgeben: 800000 FFFF 800001 FFFF 800002 FFFF 800003 FFFF 800004 FFFF > Kann sich da irgendjemand einen Reim drauf machen, oder ist das Flash > einfach falsch angeschlossen? Möglich. Du verschweigst ja seit etlicher Zeit hartnäckig, wie das Flash überhaupt angeschlossen ist ;-) > *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA; > *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; > *((short*)(0xC00000L + 2 * 0x0555)) = 0x00A0; //Flash jetzt entriegelt > Lässt man dagegen in den 3 Zeilen darüber Verdopplung weg, geht es auch > nicht. Das ist klar. Du musst die unterschiedliche Adressierung bei Flash und bei deinem µC beachten. 555h ist eine wordweise organisierte (x16) Adresse des Flash. Zum Umrechnen in eine byteweise organisierte (x8) Adresse des µC musst erstere mit 2 multiplizieren. Bei kleineren Zahlen sieht es so aus: x16 | x8 =====+===== 0 | 0 | 1 1 | 2 | 3 2 | 4 | 5 3 | 6 > *((short*)(0xC0F060))=8; //Flash beschreiben > Schaue ich mir mit dem Debugger die Adresse an, steht dort folgendes: > C0F060 DFFF0008 > C0F064 0008FFFF > Warum die 8 jetzt zweimal im Speicher steht, keine Ahnung. Du denkst, der Debugger zeigt dir den richtigen Inhalt von Flashadresse F060h ff.? DAS denke ich nicht. Wohin hast du denn tatsächlich geschrieben? 0xC0F060 ist gemäß obigen Ausführungen zunächst eine x8 Adresse vom µC. Zurückgerechnet (/2) in eine x16 Adresse fürs Flash hast du nach 7830h (x16) ins Flash geschrieben! Wieso zeigt der Debugger an der Adresse die geschriebene 8? Der Debugger (welcher?) verhält sich in der derzeitigen Einstellung vermutlich auch wie ein µC und arbeitet mit x8 Adressen, d.h. adressiert auch byteweise. So liest er schlussendlich ebenfalls von der Flashadresse 7830h. Wieso sieht der Flashinhalt dann so komisch aus? Um das zu beantworten, müsste man wissen, hat der Sourcecode (Assemblerlisting?) Probleme und Mist geschrieben und/oder der Debugger Mist gelesen. Du könntest dich beim Beschreiben zunächst auf die Adresse 0h beschränken, denn die ist bei x16 und x8 identisch. Und du solltest "sinnvolle" Daten wie z.B. 1234h benutzen. Und du solltest analog zum Beschreiben die Daten per Programm Auslesen und den Debugger zunächst aussen vor lassen. Auch daran denken, dass du einen Datenwert im Flash nur Schreiben kannst, wenn du dich per Programm verkritzelst (Adresse verhauen) ist ein Chip Erase notwendig oder du findest Daten von den Fehlversuchen. Daher Daten und Adressen von Programmlauf zu Programmlauf wechseln, wenn kein Chip Erase gemacht wird.
@Stefan Danke für Dein ausführliches Posting. Aber widersprichst du Dir hier nicht: >Nein. Es deutet auf einen unglücklich eingestellten Debugger und auf >16-Bit Adressierung hin. Ein besser eingestellter Debugger würde >ausgeben: > >800000 FFFF >800001 FFFF >800002 FFFF >800003 FFFF >800004 FFFF >[...] >Wieso zeigt der Debugger an der Adresse die geschriebene 8? Der Debugger >(welcher?) verhält sich in der derzeitigen Einstellung vermutlich auch >wie ein µC und arbeitet mit x8 Adressen, d.h. adressiert auch byteweise. >So liest er schlussendlich ebenfalls von der Flashadresse 7830h. Der Debugger ist auf die Darstellung von 16-Bit-Werten eingestellt. Es handelt sich um den GNU-Debugger GDB. Siehe Anhang. Dass uC und Speicher anders adressieren, habe ich verstanden. Mein Programm sieht jetzt so aus:
1 | short f=0; |
2 | |
3 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA; |
4 | *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; |
5 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x0090; //Enter AutoSelect-Mode |
6 | f=*((short*)(0xC00000L + 2 * 0x0001)); //Get DeviceID |
7 | *((short*)(0xC00000L + 2 * 0x0000)) = 0x00F0; //Reset |
8 | |
9 | f=0; |
10 | |
11 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA;//Write Command |
12 | *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; |
13 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00A0; |
14 | *((short*) 0xC0F020L)=0x1234; |
15 | f=*((short*)0xC0F020L); //Lese Wert zurück |
16 | |
17 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA;//Sector Erase Command |
18 | *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; |
19 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x0080; |
20 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA; |
21 | *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; |
22 | *((short*)(0xC00000L + 2 * 0x000E)) = 0x0030; |
Stand der Dinge: Das Auslesen der DeviceID funktioniert, f enthält den richtigen Wert. Das Programmieren ergibt ein Speicherbild wie schon beschrieben. Der Wert wird zweimal geschrieben in aufeinanderfolgende Adressen. Das Zurücklesen in die Variable f ergibt einen falschen Wert! Sector Erase funktioniert. Wo ist jetzt das Problem beim Programmieren bzw. Auslesen der programmierten Daten?
Kann es sein daß ein Pin nicht richtig funktioniert? Der Debugger zeigt 0xdfffffff statt 0xfffffff ! Der Debugger ist auf 32 Bit Werte eingestellt ! 2 x Hexzahl = 8 Bit 4 x Hexzahl = 16 Bit 8 x Hexzahl = 32 Bit
Mag sein, aber in der Einstellung sitzt das Häkchen bei 16 Bit. Zum Pin kann ich dir nichts sagen, aber im Debugger springt das erste Bit auch oft auf ein F während ich durch das Programm steppe. Und die erste angezeigte Adresse ist komischerweise immer 0000FFFF. Könnte auch ein Anzeigefehler sein.
Hab's gemerkt ;) Anbei die Darstellung des Speichers bei 16 Bit.
Ich denke, das ist kein Widerspruch. Bzw. du solltest mir erklären, wo du den Widerspruch siehst. Die Adressangabe bei diesem "idealen Debugger" mit Adressabstufung 1 wäre die Sichtweise auf die Adressen eines x16 organisierten Devices. Quasi wenn ich wissen will, was aus Sicht des Devices an welchen Adressen im Device ist z.B. zum Vergleich mit Datenblättern. Du darfst das nicht verwechseln mit der Sicht auf die Daten (Werte), also ob 8-Bit oder 16-Bit angezeigt werden sollen. Ich weiss nicht ob GDB auf x16 Adressen eingestellt werden kann (bin GDB Laie). Ein Punkt hierbei ist vielleicht "8.14.1.2 Memory Access Size" aus dem Manual. Bzw. insgesamt eine saubere Definition des Flash-Speichers in GDB per "8.14 Memory Region Attributes". Dass dein Sektor Erase funktioniert halte ich für "Zufall". Die benutzte Adresse *((short*) 0xC0F020L /*x8*/)=0x1234; d.h. 7810h (x16) liegt im Sektor SA0 (Tabelle 2 im Flash-Datenblatt). Zufällig sind die Bits 21-15 (x16) der Zieladresse 0, d.h. SA0 wird gelöscht. Die Bits 14-0 (x16) sind anscheinend irrelevant. Das ist möglicherweise wichtig, wenn du später andere Sektoren löschen willst. Z.B. Sektor SA1 löschen würde ich mit *((short*)(0xC00000L + 2 * 0x008000L)) = 0x0030; versuchen.
Das doppelte Schreiben (und die Leseprobleme) bei einer Sourcecodezeile kann mit dem OPB zusammenhängen. Interessant wären es hier, die OPD EMC Design Parameter deines Boards zu kennen.
> Zufällig sind die Bits 21-15 (x16) der Zieladresse 0, d.h. SA0 wird > gelöscht. Die Bits 14-0 (x16) sind anscheinend irrelevant. Das bezieht sich auf die Zeile *((short*)(0xC00000L + 2 * 0x000E)) = 0x0030;
Hm bei den Sektoren scheine ich mich wirklich vertan zu haben. Habe eine Stelle in der Adresse übersehen. Dann reicht aber ja die Basisadresse C00000 gar nicht aus, um alle Adressen zu erreichen, oder? Denn die Adressen in den höheren Sektoren haben 6 Stellen. Der Chip-Erase funktionierte allerdings auch.
Wenn du mit x8 Adressen weiter machst (0-7FFFFE in 2er Schritten), hast du mit der Basisadresse C00000h bei Bit 22 eine Überschneidung, die laut OPB Datenblatt Abschnitt "Allowable Parameter Combinations" nicht erlaubt ist. Eine taugliche Basisadresse wäre 800000h. Interessanterweise taucht diese Adresse in einem deiner Reports oben bereits auf - Zufall? Wenn du konsequent mit x16 Adressen arbeitest (0-3FFFFF in 1er Schritten), bleibt Bit 22 unberührt und du kannst C00000h als Basisadresse verwenden. Das OPB muss wahrscheinlich entsprechend konfiguriert werden.
Sorry, dieses ständige hin und her zwischen x8 und x16-Adressen verwirrt mich. Soweit ich das jetzt verstanden habe kann ich auf dem Speicher doch nur mit x16-Adressen arbeiten, wie man an der nötigen Verdopplung des Adress-Offsets sieht. Wo arbeite ich also mit x8 weiter?
Nochmal drüber nachgedacht: Ich müßte also den Adressen, in die ich schreibe, auch das "mal 2" davor stellen. Dadurch bewege ich mich im 16-Bit-Adressraum des Speichers und kann mich nach den Adressen im Datenblatt des Flash richten.
Das verwirrende ist derzeit vielleicht, dass du manchmal aus x16 Adressen x8 Adressen machst bzw. du (und der GDB) ein anderes mal direkt x8 Adressen verwenden (0xC0F020L und beim Memdump) und das OPB aus allen x8 Adressen wieder x16 Adressen bastelt... (*) Schau dir diesen Ausdruck an: f=*((short*)(0xC00000L + 2 * 0x0001)); //Get DeviceID Du bildest eine x8 Adresse (0xC00002L) aus einer x16 Adresse (0x000001). Man könnte einiges lesbarer so schreiben z.B. mit einem Makro // OPB_BASEADR als Konstante betrachten! Ist im OPB "verdrahtet" #define OPB_BASEADR 0xC00000L #define X16_to_X8_ADR(x16Adr) ((short*)(OPB_BASEADR + 2 * (x16Adr))) Dann wird es im Code übersichtlicher: f = *X16_to_X8_ADR(0x0001); *X16_to_X8_ADR(0x0001) = 0x1234; Beispiel Kopierschleifen z.B. komplettes Flash vollschreiben (nicht über 1FFFFFUL testen, bevor die Sache mit der Basisadresse geklärt ist!) unsigned long l; short *p = X16_to_X8_ADR(0); for (l=0; l<= 0x3FFFFFUL; l++) *p++ = l & 0x00FFFF; Anders per Schleife unsigned long x16adr; for (x16adr=0; x16adr<= 0x3FFFFFUL; x16adr++) *X16_to_X8_ADR(x16adr) = x16adr & 0x00FFFF;
Du denkst meiner Meinung nach zu kompliziert. Dein Flash ist so konfiguriert, daß es für den Prozessor im Speicherbereich 0x0C00000 bis 0x0FFFFFF liegt. Bei Lesen kann man beliebig (8 Bit, 16 Bit, 32 Bit) zugreifen, der Memory Controller wandelt alle Zugriffe auf die 16 Bit Zugriffe um, völlig transparent. Zum Beschreiben und Löschen des Flash-Roms stellst Du bestimmte Funktionen zur Verfügung. Nur in diesen mußt Du achtgeben, daß die genauen Adressen des Flashs angesprochen werden, aber Du weisst ja jetzt wie. Beim Schreiben mußt Du außerdem beachten, daß Du nur gerade Adressen beschreiben kannst, weil Du 16 Bit in einem mal änderst. Das Problem mit dem doppelten Lesen muß ein Lesefehler sein, denn das Flash braucht für jede Speicherstelle dies 4 x Zugriff Sequenz, in einem mal 2 Speicherstellen ändern geht gar nicht.
Wobei das mit den Schleifen nicht so funktionieren wird, da vor jeder Schreiboperation die Kommando-Sequenz durchlaufen werden muss. Warum die Verundung mit 0x00FFFF? Klaus Falser schrieb weiter oben, dass ich nur gerade Adressen schreiben darf. Ist das in deinen Schleifen berücksichtigt?
@Klaus Falser Beziehen sich die graden Adressen auf die 16-Bit-Adressen des Speichers oder die 8-Bit-Adressen der CPU? *((short*)(0xC00000L + 2 * 0x0555)) = 0x00A0; Wenn sich die Aussage auf 0xC00555 bezieht, wäre das doch eine ungerade Adresse, oder?
>Bei Lesen kann man beliebig (8 Bit, 16 Bit, 32 Bit) zugreifen, der >Memory Controller wandelt alle Zugriffe auf die 16 Bit Zugriffe um, >völlig transparent. Bist du sicher? Muss ich f=*((short*)0xC0F020L); oder f=*((short*)(0xC00000L + 2 * 0xF020L); schreiben? Das kann doch nicht dasselbe sein.
Die geraden Adressen beziehen sich auf den Speicher des Prozessors, vergiss die Adressen des EEPROMS. Zur Verdeutlichung mache ich ein Beispiel : Dein Flash ist zwischen 0x00C00000 und 0x00FFFFFF. Eine Arrayvariable test vom type char[10] liegt an Adresse 0x00C23456. Auf diese Variable kannst Du beliebig lesend zugreifen, x = test[5] + test[1]; usw. Wenn Du schreibend auf test zugreifst, passiert nichts, das Flash wird nicht verändert. test[6] = 'A'; -> keine Wirkung. Zum Ändern von test brauchst Du eine Funktion write_flash(uint16_t *pFlash, const uint16_t *pNewValue, int len ). Diese Funktion bekommt die Adresse von test, einen Zeiger auf die neuen Werte und die Länge des zu schreibenden Bereichs (in 16 Bit-Worten). write_flash((uint16_t *) &test[0], &newValue, sizeof(test)/2); Beim Aufruf wird die Adresse von test auf eine 16 Bit Pointer gecastet, die Adresse muß aber gerade sein. Die Funktion besteht intern aus einer Schleife for (i = 0; i < len; i++) { // Unlock Flash *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA; *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; *((short*)(0xC00000L + 2 * 0x0555)) = 0x00A0; // schreibe neuer Wert *pFlash++ = *pNewValue++; delay(..); // warte bis Zelle programmiert } Den Rest und die Details überlasse ich Dir. Aber was wollt ihr mit dem Flash überhaupt machen? Klaus
Du verwirrst mich immer mehr ;) In Deiner Schleife werden mit pFlash ja die Adressen des Prozessors verwendet, nicht die Adressen auf 16-Bit-Basis (da keine Multiplikation mit 2). Weiter oben hieß es aber, ich solle mich nur im Adressraum des Flash bewegen und deshalb bei jedem Zugriff den Adressoffset mal 2 nehmen. Außerdem werden doch bei der Inkrementierung von pFlash auch ungerade Adressen angesprochen, oder nicht?
TechInfo wrote: > In Deiner Schleife werden mit pFlash ja die Adressen des Prozessors > verwendet, nicht die Adressen auf 16-Bit-Basis (da keine Multiplikation > mit 2). > Weiter oben hieß es aber, ich solle mich nur im Adressraum des Flash > bewegen und deshalb bei jedem Zugriff den Adressoffset mal 2 nehmen. > Du kannst mit beiden Arten von Adressen arbeiten, bloss erfordern beide Arten unterschiedlichen Code. Um es im Hirn einfacher zu haben, sollte man im (Anwendungs-)Programm möglichst bei einer Art von Adressen bleiben. Klaus hält es für am einfachsten, mit den gewohnten x8 Adressen wie beim µC zu arbeiten und die Umrechnung einmal in einer Funktion zu "verstecken". Ich hatte vorgeschlagen mit den nativen x16 Adressen zu arbeiten und die Umrechnung einmal in einem Makro zu "verstecken". Gehen tut beides, wobei dein Einwand mit der Unlock Sequenz beim Schreiben bzgl. meinem Makro berechtigt ist. Jedesmal die Unlock-Sequenz voranzustellen ist allerdings eine ungewöhnliche Art ein Flash zu programmieren - gibt es keinen "Bulkmodus" bei dem man nur weitere Daten schnell genug anhängen muss? Die Verundung im Beispiel ist reiner Schönheitscode, der beim Sourcecode lesen daran erinnert, dass die Zählvariable 32-Bit hat und beim Schreiben ins Flash auf 16-Bit gestutzt wird. Die Lösung von Klaus für das Beschreiben ist elegant und funktionell. Insbesondere wenn z.B. Delays berücksichtigt werden sollen, ist der Code in einer Funktion besser aufgehoben als in einem Makro. > Außerdem werden doch bei der Inkrementierung von pFlash auch ungerade > Adressen angesprochen, oder nicht? Ist OK, da pFlash vom Typ uint16_t * ist und ein pFlash++ den Zähler physikalisch um 2 ( genauer sizeof(uint16_t)) Bytes inkrementiert. > Du verwirrst mich immer mehr ;) > Du solltest 1-2 Tage Auszeit nehmen, den Vorgang reifen lassen und am Montag weitermachen. Im Moment hast du eine Hirnverknotung ;-)
>Jedesmal die Unlock-Sequenz voranzustellen ist allerdings eine >ungewöhnliche Art ein Flash zu programmieren - gibt es keinen >"Bulkmodus" bei dem man nur weitere Daten schnell genug anhängen muss? Es gibt die Möglichkeit des Unlock Bypass Command. Nachdem man dieses geschrieben hat braucht ein Programmierzugriff nur 2 Kommandos anstatt 4. Aber einen speziellen Bulk-Modus lese ich aus dem Datenblatt nicht heraus. Habe den Code jetzt nochmal geändert. Bevor ich mich mir Programmierschleifen befasse muss ich ja erstmal sicher stellen dass ich aus dem Flash in Variablen lesen kann. Das funktioniert leider nicht. Schreibe jetzt in x16-Adresse 0xC00002, also für die CPU und den Debugger 0xC00004. In der Variable f steht nach dem Auslesen aber immer der Wert 32 (20h). Egal welchen Wert ich vorher an die Adresse geschrieben habe. Woran könnte das liegen? Wenn man im Debugger schaut, und ich das richtig verstehe, liegt der Wert auch nicht an x8-Adresse 0xC00004, sondern an 0xC00006, wenn ich die Zweierpärchen (also byteweise) zähle.
1 | short f=0; |
2 | |
3 | |
4 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA;//Write Command |
5 | *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; |
6 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00A0; |
7 | *((short*)(0xC00000L + 2 * 0x0002)) = 0x0001; |
8 | f=*((short*)(0xC00000L + 2 * 0x0002)); //Lese Wert zurück: f=32 |
9 | |
10 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA;//Sector Erase Command |
11 | *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; |
12 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x0080; |
13 | *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA; |
14 | *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; |
15 | *((short*)(0xC00000L + 2 * 0x0000)) = 0x0030; |
Wenn Du sofort nach dem Programmieren den Wert zurückliest, dann ist das Flash vielleicht noch nicht einmal programmiert. Muß man da nicht einen bestimmte Zeit warte oder pollen bis das Programmieren abgeschlossen ist? Vielleicht solltest Du einmal versuchen, ob das Auslesen der Device Information (Autoselect, CFI) richtig funktioniert.
Wie in meinem Beitrag von gestern, 16:11 geschrieben, funktioniert das Auslesen von Device ID und Manufacturer ID im Autoselect Mode. *((short*)(0xC00000L + 2 * 0x0555)) = 0x00AA; *((short*)(0xC00000L + 2 * 0x02AA)) = 0x0055; *((short*)(0xC00000L + 2 * 0x0555)) = 0x0090; //Enter AutoSelect-Mode f=*((short*)(0xC00000L + 2 * 0x0001)); //Get DeviceID *((short*)(0xC00000L + 2 * 0x0000)) = 0x00F0; //Reset In f steht dann die Device ID. Ich setze nach dem Programmieren einen Breakpoint und warte somit noch etwas mit dem Auslesen. Der Wert 32 steht übrigens auch dann in der Variablen, wenn ich eine x-beliebige nicht programmierte Adresse auslese. Dann müsste ja eigentlich FFFF drin stehen. Also egal welche Adresse ich lese, und ob vorher programmiert oder nicht, die Variable enthält immer den Inhalt 32. Während der Debugger etwas anderes anzeigt.
Bitte mach mal mit GDB zwei Memdumps des Bereichs 0xC00000 bis ca. 0xC0007F 1. nach dem Sektor Erase und 2. nach dem Schreiben des Wertes 0x1234 (*((short*)(0xC00000L + 2 * 0x0002)) = 0x1234;). So wie auf dem Bild debug2.gif oben.
Habe hier noch etwas gefunden: http://www.arava.co.il/matan/misc/amd.c Ein Treiber für den Flash-Baustein. Versuche das grade nachzuvollziehen und nach Unterschieden zu schauen. Könnt es euch ja mal angucken.
Die Memdumps sind ziemlich verblüffend. Es sind fünf Ungereimtheiten aufzuklären: 1/ Wieso ist 0xC00000 nach dem Löschen nicht 0xFFFF sondern 0x0000? 2/ Wieso sind nicht alle Speicherstellen 0xFFFF sondern eine über die andere 0xDFFF? Oben wurde bereits gefragt, ob eine Datenleitung defekt ist. Wie sieht es aus, wenn man Werte ins Flash schreibt, die auf das besondere Bit angewiesen sind z.B. den Wert 0x2345? 3/ Wieso wird 0x1234 doppelt geschrieben oder doppelt ausgelesen? Wieso funktioniert das Auslesen mit GDB, aber nicht das Auslesen im Programm? 4/ Wieso steht 0x1234 nicht bei 0xC00004 sondern bei 0xC00006 und 0xC00008? Hängt das möglicherweise mit 1/ und 3/ zusammen, d.h. ist der Offset konstant 2/4 Bytes? 5/ Woher kommt der Wert 0x0004 nach dem Schreiben in 0xC00000? Wenn 0xC00000 eine Flash-Adresse wäre, wäre sie mit 0x0000 nach dem Sektor Erase bereits beschrieben. Es ist nicht möglich im Flash wieder Bits zu setzen; es kann nur von 1 auf 0 gewechselt werden (Daher das "Füllen" mit 0xFFFF beim Erase). Die Adresse kann also keine Flash-Adresse sein. Korreliert der Wert 0x0004 mit der Anzahl der geschriebenen Bytes (2x 0x1234 = 4 Bytes)? Meine Vermutung ist, dass das OPB EMC eine grössere Rolle spielt als bisher berücksichtigt wurde. Daher wäre es sinnvoll, die OPB EMC Design Parameter zusammenzutragen und sich dann ins Datenblatt zustürzen. Es gibt dort die Möglichkeit 32-Bit Werte automatisch auf mehrere 16-Bit Zugriffe zu verteilen. Das könnte ein Ansatzpunkt für 3/ sein.
zu 1) Das erste Adressfeld was im Debugger angezeigt wird steht immer auf 0x0000. Würde ich also im Bild von oben runter scrollen und mir als erste Adresse 0xC00010 anzeigen lassen, wäre dieses Feld auf 0x0000 gesetzt. Das kann doch eigentlich nur mit der Anzeige zusammen hängen? zu 2) Wäre zu prüfen (aber nicht von mir) zu 3)keine Antwort zu 4)könnte das evtl. auch an einer defekten Datenleitung liegen? zu 5) Auch hier wird im Debugger im obersten Feld Mist angezeigt. Wenn ich durch das Programm steppe, ändert sich der Wert des obersten Feldes mit jedem Step. Hier stand er zufällig auf 0x4. Beim nächsten step hätte dort ein anderer Wert gestanden. Anzeigefehler? Ich kann doch jetzt davon ausgehen, dass mein C-Code bzw. die Kommandos richtig umgesetzt werden, oder? Sonst könnte er ja auch nicht die DeviceID auslesen oder einen Sektor löschen. Also kann ich den Ball an den Hardwerker zurück spielen.
Grmppf. Das ist aber eine böse Falle, wenn man seinen Werkzeugen nicht trauen kann. Aber wenigstens haben sich die 5 Unbekannten auf 2,5 Unbekannte reduziert. Hast du GDB die Memory Region 0xC00000 - ... bekannt gemacht, wie oben schon mal erwähnt? Ansonsten die Anzeige VOR 0xC00000 beginnen lassen... oder eigene Memdump-Funktion schreiben (würde ich machen). "Ball zurückspielen" finde ich nicht effektiv/produktiv. Du solltest dich mit dem Hardwareler zusammensetzen und die Ergebnisse bis jetzt diskutieren. Lass dir mehr vom OPB EMC erzählen - ich habe das Gefühl, dass 3/ mit dem OPB EMC zusammenhängt.
Verstehe aber nicht, wieso das Schreiben von Werten z.B. beim Entriegeln des ROMs funktioniert. Da mache ich doch auch nichts anderes als bestimmte Werte in bestimmte Adressen zu schreiben. Würde etwas mit den Leitungen oder dem OPB nicht stimmen, dürfte das doch auch nicht funktionieren bzw. Müll geschrieben werden. Was meinst du mit bekannt machen? Ich öffne einfach das Memory View Fenster. Ball zurückspielen deshalb, weil ich meine Diplomarbeit schreibe, und das Thema ausdrücklich die Software Entwicklung ist. Ich habe noch jede Menge andere Funktionalitäten zu entwickeln und kann mich leider nicht lange aufhalten, um Hardware-Probleme zu lösen, da ich ja auch nur eine begrenzte Zeit zur Verfügung habe und am Ende Code vorweisen muss. Mein betreuender Prof ist genau derselben Meinung. Mir muss in erster Linie wichtig sein, Funktionen zu entwickeln und die später zu dokumentieren. Das ganze Projekt zum Laufen zu bringen ist nicht meine Aufgabe. Da das Auslesen der Chip-Daten und der Erase funktionieren, kann an meinem Code ja eigentlich nichts falsch sein. Trotzdem Vielen Dank für die ausführliche Hilfe und ein schönes Wochenende!
TechInfo wrote: > Verstehe aber nicht, wieso das Schreiben von Werten z.B. beim Entriegeln > des ROMs funktioniert. Da mache ich doch auch nichts anderes als > bestimmte Werte in bestimmte Adressen zu schreiben. Würde etwas mit den > Leitungen oder dem OPB nicht stimmen, dürfte das doch auch nicht > funktionieren bzw. Müll geschrieben werden. > Diese Kommandosequenzen arbeiten anders als die IO-Funktionen. Dem Flash ist bei Kommandosequenzen nur wichtig, dass bestimmte Bitmuster ("555 AAA") an den Ports anliegen. Diese Adressen werden nicht als reale Adressen im Flash umgesetzt. Ausserdem liest du bei den Rückmeldungen der Kommandos nicht das Bit, welches den Unterschied zwischen 0xFFFF und 0xDFFF ausmacht. Oder gibt es Statusmeldungen, wo an der Stelle eine 1 ist? > Was meinst du mit bekannt machen? Ich öffne einfach das Memory View > Fenster. > Dem GDB mitteilen, dass der Speicher zwischen X und Y als 16-Bit Speicher organisiert ist und ggf. Read-only ist. Siehe Hinweis zur Doku oben. Der Code ist bis jetzt, was ich als Hack bezeichne. Sehr nützlich zum Proof-of-Concept (für bestimmte Kommandos OK, für Schreiben/Lesen nicht OK) aber insgesamt nicht tauglich für die Produktion. In dem Treibercode oben werden z.B. 32-Bit Zugriffe durchgeführt, während du mit *((short *)... 16-Bit Zugriffe machst. Das OPB arbeitet zum µC hin mit 32-Bit und zum Memory hin mit 32, 16 oder 8 Bit je nach Einstellung des OPB. Es kann eine Einstellungssache des OPB sein, weshalb Werte verdoppelt erscheinen. > Ball zurückspielen deshalb, weil ich meine Diplomarbeit schreibe, und > das Thema ausdrücklich die Software Entwicklung ist. Ich habe noch jede > Menge andere Funktionalitäten zu entwickeln und kann mich leider nicht > lange aufhalten, um Hardware-Probleme zu lösen, da ich ja auch nur eine > begrenzte Zeit zur Verfügung habe und am Ende Code vorweisen muss. Mein > betreuender Prof ist genau derselben Meinung. > > Mir muss in erster Linie wichtig sein, Funktionen zu entwickeln und die > später zu dokumentieren. Das ganze Projekt zum Laufen zu bringen ist > nicht meine Aufgabe. Da das Auslesen der Chip-Daten und der Erase > funktionieren, kann an meinem Code ja eigentlich nichts falsch sein. > > Trotzdem Vielen Dank für die ausführliche Hilfe und ein schönes > Wochenende! Wenn du dich mit dem Betreuer einigen kannst, dass es für deine Arbeit auf den restlichen Code ankommt und der Flash-Code "aus Zeitlichen und technischen Gründen Gegenstand anderer Arbeiten sein soll", ist es doch OK.
>Ausserdem liest du bei den Rückmeldungen >der Kommandos nicht das Bit, welches den Unterschied zwischen 0xFFFF und >0xDFFF ausmacht. Oder gibt es Statusmeldungen, wo an der Stelle eine 1 >ist? Es handelt sich um das 14. Bit, oder? >In dem Treibercode oben werden z.B. 32-Bit Zugriffe durchgeführt, >während du mit *((short *)... 16-Bit Zugriffe machst. Das OPB arbeitet >zum µC hin mit 32-Bit und zum Memory hin mit 32, 16 oder 8 Bit je nach >Einstellung des OPB. Es kann eine Einstellungssache des OPB sein, >weshalb Werte verdoppelt erscheinen. Moment, ich dachte der Grund dafür, dass ich 16-Bit-Zugriffe im Code mache, ist die Organisation des Speichers (16-bittig). Jetzt sagst du aber, der Zugriff im Code soll sich am Zugriff des OPB orientieren?
Es geht darum, wie das OPB eingestellt ist und wie daraufhin die 16-Bit Daten (die über 32-Bit Adressen angeliefert werden) verwurstet werden und ob man dem OPB vielleicht auch 32-Bit Daten geben muss. Im Moment ist OPB eine Blackbox, die anders funktioniert als gedacht. Also entweder die Sache sein lassen, oder die Blackbox systematisch von aussen erkunden, oder denjenigen fragen, der die Blackbox implementiert hat.
Es stimmt zwar, daß der Memory Controller 32 Bit Zugriffe usw. akzeptiert und diese auf die 16 Bit Zugriffe transparent umsetzt. Beim Beschreiben des Flashs muß man eine gewisse Schreibsequenz AM FLASH einhalten (siehe oben). Wenn man nun 32 Bit Zugriffe macht, dann werden daraus 2 Zugriffe am Flash und dieses erkennt die geforderte Sequenz nicht mehr. Die Sequenz aus 16 Bit Zugriffen ist also sehr wohl richtig und nötig. Das gilt aber nur für die Sequenz beim Schreiben. Lesen kann man beliebig.
Moin, ich habe heute nochmal auf Stefan B.'s Einwurf hin den Flash mit dem Wert 0x2345 beschrieben. Das Ergebnis seht ihr im Anhang. Wieder mal was neues ;) Sagt euch das irgendwas? Der erste Wert ist korrekt, der zweite nicht...
Und noch eine Neuigkeit: Ich habe grade den Lesezugriff mit (int *) gecastet, anstatt (unsignend short* ), und ich bekomme den richtigen Wert in die Variable geschrieben!
Ein Silberstreif am Horizont! Vielleicht wird es ja doch was. Daumendrücken!
Wie kann ich denn jetzt Variablen und Arrays im Flash ablegen? Gibt es da Präpozessor-Direktiven? Oder mache ich das über Pointer?
Mann, bist Du hastig. Du hast das erste Problem noch nicht gelöst und bist jetzt schon beim zweiten. Funktionieren Deine Zugriffe jetzt alle und wieso haben sie vorher nicht funktioniert?
Die Probleme mit der doppelten Speicherung (oder Anzeige) sowie der anscheinend fehlerhaften Datenleitung bestehen noch. Aber da ich wie gesagt keine Zeit habe, mich um den Hardwareteil zu kümmern, werde ich dem entsprechenden Kollegen bescheid sagen und bis dahin ein bißchen herumexperimentieren, da die Zugriffe ja mit dem workaround funktionieren und es evtl. sein kann dass derjenige bis zum Ende meiner Diplomarbeit gar nicht mehr dazu kommt, etwas für das Projekt zu tun. Ich muss aber Funktionalität vorweisen können am Ende. Ich kann nicht einfach schreiben "da es Probleme mit der Hardware gab, habe ich mich nicht weiter darum gekümmert." Also ist mein nächstes Ziel jetzt, wie ich am besten eine Tabelle im Flash ablege, und dafür müßte ich wissen wie mich Variablen dort deklariere
Da bei Deinem Prozessor das Flash im normalen Adressraum eingebunden wird (anders als bei Harvard-Prozessoren), ist das Deklarieren von Variablen* im Flash kein Kunststück. Du musst nur Deinem C-Compiler klarmachen, daß bestimmte Variablen an bestimmten Adressen im Speicher liegen; bei gcc geht das mit einem Linkerskript, andere C-Compiler haben dafür andere Mechanismen. Du kannst diesen Teil der Übung auch ohne Flash ausprobieren, indem Du nämlich versuchst, eine Variable irgendwo in einem nicht benutzten** RAM-Bereich unterzubringen. Ob die Variable wirklich an der richtigen Stelle im Speicher landet, kannst Du sogar programmatisch untersuchen, indem Du mit dem &-Operator deren Adresse bestimmst ... und die kannst Du ja irgendwohin ausgeben. *) Eigentlich sinds ja Konstanten, da nicht (direkt) beschreibbar. **) darf weder für Stack noch Heap oder statische Variablen verwendet werden, der C-Startup-Code ist gegebenenfalls anzupassen bzw. ein weiteres Linkerskript
In meinem Linkerscript sind die Adressbereiche der eingebundenen Speicherbausteine sowie die Orte, an denen er Stack, Heap, Data etc. ablegen soll, definiert. Ich kann aber doch nicht einstellen, dass die Variable (Konstante) unsigned int tabelle[100][100] im Flash abliegt, aber die Variable int i im RAM. Oder gibt es ein Schlüsselwort dafür? Wie ich auf Adressen zugreife ist mir klar, und natürlich kann ich einen Pointer auf eine Adresse im Flash definieren, und damit dann arbeiten. Aber ich suche eine Möglichkeit, direkt ein Array im Flash zu deklarieren. Könnte man nicht einfach sagen, dass globale Variablen im Flash deklariert werden sollen? Dann müßte ich die Tabelle global deklarieren, und aufpassen dass ich sonst keine globalen Variablen habe.
Hallo, möchte mal schnell Feedback geben: Das Problem war das Timing des Flash-ROMs. Der Hardware-Designer hat die Einstellung geändert, nun sind alle Fehler plötzlich behoben. Vielen Dank an alle, die mir geholfen haben. Eure Vorschläge bzgl. Funktionen kann ich nun verwirklichen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.