Forum: Compiler & IDEs ext. Flash-ROM in C beschreiben


von TechInfo (Gast)


Angehängte Dateien:

Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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?

von TechInfo (Gast)


Lesenswert?

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?

von TechInfo (Gast)


Lesenswert?

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?

von Michael U. (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.


von TechInfo (Gast)


Lesenswert?

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?

von TechInfo (Gast)


Lesenswert?

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 ;)

von Karl H. (kbuchegg)


Lesenswert?

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.

von TechInfo (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Klaus F. (kfalser)


Lesenswert?

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


von TechInfo (Gast)


Lesenswert?

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.

von Klaus F. (kfalser)


Lesenswert?

Schnellschuß :
Wenn die Flash-Adressen in 16 Bit zählen, dann muß man vielleicht die 
Adresse 0xC00000 + 2 * 555 ansprechen.

von TechInfo (Gast)


Lesenswert?

Warum 2* 555?

von TechInfo (Gast)


Lesenswert?

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?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

Wie der Zugriff erfolgt, weiß ich nicht. Der Speicher ist jedenfalls in 
16-Bit-Worten organisiert.

von TechInfo (Gast)


Lesenswert?

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?

von Klaus Falser (Gast)


Lesenswert?

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

von TechInfo (Gast)


Lesenswert?

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?

von Klaus Falser (Gast)


Lesenswert?

Der MicroBlaze ist ein 32 Bit Prozessor, der würde eher 32 Bit Zugriffe 
machen.

von Peter D. (peda)


Lesenswert?

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

von TechInfo (Gast)


Lesenswert?

Und wie sage ich der CPU, dass sie 16-bittig zugreifen soll?

von Klaus F. (kfalser)


Lesenswert?

Ein Zugriff auf eine uint16_t Variable oder Adresse sollte genügen:

*((uint16_t*)(0xC00000L + 2 * 0x0555)) = 0x00AA;

von TechInfo (Gast)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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?

von Klaus F. (kfalser)


Lesenswert?

> 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.

von Sebastian Heyn (Gast)


Lesenswert?

...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"

von TechInfo (Gast)


Lesenswert?

@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.

von TechInfo (Gast)


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das kann an der von mir bereits erwähnten "endianness" liegen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> 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.

von TechInfo (Gast)


Angehängte Dateien:

Lesenswert?

@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?

von Klaus F. (kfalser)


Lesenswert?

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

von TechInfo (Gast)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

Sorry, es die Einstellung lautet "Word", sind das 32 Bit?

von TechInfo (Gast)


Angehängte Dateien:

Lesenswert?

Hab's gemerkt ;) Anbei die Darstellung des Speichers bei 16 Bit.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> 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;

von TechInfo (Gast)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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?

von TechInfo (Gast)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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;

von Klaus Falser (Gast)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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?

von TechInfo (Gast)


Lesenswert?

@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?

von TechInfo (Gast)


Lesenswert?

>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.

von Klaus Falser (Gast)


Lesenswert?

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

von TechInfo (Gast)


Lesenswert?

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?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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 ;-)

von TechInfo (Gast)


Lesenswert?

>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;

von Klaus F. (kfalser)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von TechInfo (Gast)


Angehängte Dateien:

Lesenswert?

Sector Erase

von TechInfo (Gast)


Angehängte Dateien:

Lesenswert?

Nach Beschreiben

von TechInfo (Gast)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

>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?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von Klaus Falser (Gast)


Lesenswert?

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.

von TechInfo (Gast)


Angehängte Dateien:

Lesenswert?

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...

von TechInfo (Gast)


Lesenswert?

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!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ein Silberstreif am Horizont! Vielleicht wird es ja doch was. 
Daumendrücken!

von TechInfo (Gast)


Lesenswert?

Wie kann ich denn jetzt Variablen und Arrays im Flash ablegen? Gibt es 
da Präpozessor-Direktiven? Oder mache ich das über Pointer?

von Klaus F. (kfalser)


Lesenswert?

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?

von TechInfo (Gast)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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

von TechInfo (Gast)


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?


von TechInfo (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.