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.
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.
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?
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
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.
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:
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.
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.
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!
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.